diff options
1441 files changed, 26425 insertions, 13745 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 297e32bd67e..c5992993f91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -349,7 +349,7 @@ mark_as_advanced(WITH_SYSTEM_GLOG) option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON) # Misc -if(WIN32) +if(WIN32 OR APPLE) option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON) endif() option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) @@ -1705,22 +1705,18 @@ if(WITH_PYTHON) endif() endif() -if(MSVC) - string(APPEND CMAKE_CXX_FLAGS " /std:c++17") - # Make MSVC properly report the value of the __cplusplus preprocessor macro - # Available MSVC 15.7 (1914) and up, without this it reports 199711L regardless - # of the C++ standard chosen above - if(MSVC_VERSION GREATER 1913) - string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus") - endif() -elseif( - CMAKE_COMPILER_IS_GNUCC OR - CMAKE_C_COMPILER_ID MATCHES "Clang" OR - CMAKE_C_COMPILER_ID MATCHES "Intel" -) - string(APPEND CMAKE_CXX_FLAGS " -std=c++17") -else() - message(FATAL_ERROR "Unknown compiler ${CMAKE_C_COMPILER_ID}, can't enable C++17 build") +# Select C++17 as the standard for C++ projects. +set(CMAKE_CXX_STANDARD 17) +# If C++17 is not available, downgrading to an earlier standard is NOT OK. +set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Do not enable compiler specific language extentions. +set(CMAKE_CXX_EXTENSIONS OFF) + +# Make MSVC properly report the value of the __cplusplus preprocessor macro +# Available MSVC 15.7 (1914) and up, without this it reports 199711L regardless +# of the C++ standard chosen above. +if(MSVC AND MSVC_VERSION GREATER 1913) + string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus") endif() # Visual Studio has all standards it supports available by default @@ -1915,6 +1911,7 @@ if(FIRST_RUN) info_cfg_option(WITH_IK_ITASC) info_cfg_option(WITH_IK_SOLVER) info_cfg_option(WITH_INPUT_NDOF) + info_cfg_option(WITH_INPUT_IME) info_cfg_option(WITH_INTERNATIONAL) info_cfg_option(WITH_OPENCOLLADA) info_cfg_option(WITH_OPENCOLORIO) diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index fb79eee62be..8c739dcd68e 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -56,6 +56,7 @@ else() endif() include(cmake/zlib.cmake) +include(cmake/zstd.cmake) include(cmake/openal.cmake) include(cmake/png.cmake) include(cmake/jpeg.cmake) @@ -164,6 +165,7 @@ endif() if(UNIX AND NOT APPLE) include(cmake/libglu.cmake) include(cmake/mesa.cmake) + include(cmake/wayland_protocols.cmake) endif() include(cmake/harvest.cmake) diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake index 27351ddee45..b4d96ea856f 100644 --- a/build_files/build_environment/cmake/download.cmake +++ b/build_files/build_environment/cmake/download.cmake @@ -87,7 +87,9 @@ download_source(LIBGLU) download_source(MESA) download_source(NASM) download_source(XR_OPENXR_SDK) +download_source(WL_PROTOCOLS) download_source(ISPC) download_source(GMP) download_source(POTRACE) download_source(HARU) +download_source(ZSTD) diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake index fc7e652a028..a19c332457d 100644 --- a/build_files/build_environment/cmake/harvest.cmake +++ b/build_files/build_environment/cmake/harvest.cmake @@ -126,6 +126,8 @@ if(UNIX AND NOT APPLE) harvest(xml2/include xml2/include "*.h") harvest(xml2/lib xml2/lib "*.a") + + harvest(wayland-protocols/share/wayland-protocols wayland-protocols/share/wayland-protocols/ "*.xml") else() harvest(blosc/lib openvdb/lib "*.a") harvest(xml2/lib opencollada/lib "*.a") @@ -190,6 +192,8 @@ harvest(potrace/include potrace/include "*.h") harvest(potrace/lib potrace/lib "*.a") harvest(haru/include haru/include "*.h") harvest(haru/lib haru/lib "*.a") +harvest(zstd/include zstd/include "*.h") +harvest(zstd/lib zstd/lib "*.a") if(UNIX AND NOT APPLE) harvest(libglu/lib mesa/lib "*.so*") diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index d93b8463b4b..a71fc4b85e4 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -216,9 +216,9 @@ set(OPENVDB_HASH 01b490be16cc0e15c690f9a153c21461) set(OPENVDB_HASH_TYPE MD5) set(OPENVDB_FILE openvdb-${OPENVDB_VERSION}.tar.gz) -set(NANOVDB_GIT_UID e62f7a0bf1e27397223c61ddeaaf57edf111b77f) +set(NANOVDB_GIT_UID dc37d8a631922e7bef46712947dc19b755f3e841) set(NANOVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/${NANOVDB_GIT_UID}.tar.gz) -set(NANOVDB_HASH 90919510bc6ccd630fedc56f748cb199) +set(NANOVDB_HASH e7b9e863ec2f3b04ead171dec2322807) set(NANOVDB_HASH_TYPE MD5) set(NANOVDB_FILE nano-vdb-${NANOVDB_GIT_UID}.tar.gz) @@ -456,12 +456,18 @@ set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589) set(NASM_HASH_TYPE SHA256) set(NASM_FILE nasm-${NASM_VERSION}.tar.gz) -set(XR_OPENXR_SDK_VERSION 1.0.14) +set(XR_OPENXR_SDK_VERSION 1.0.17) set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz) -set(XR_OPENXR_SDK_HASH 0df6b2fd6045423451a77ff6bc3e1a75) +set(XR_OPENXR_SDK_HASH bf0fd8828837edff01047474e90013e1) set(XR_OPENXR_SDK_HASH_TYPE MD5) set(XR_OPENXR_SDK_FILE OpenXR-SDK-${XR_OPENXR_SDK_VERSION}.tar.gz) +set(WL_PROTOCOLS_VERSION 1.21) +set(WL_PROTOCOLS_FILE wayland-protocols-${WL_PROTOCOLS_VERSION}.tar.gz) +set(WL_PROTOCOLS_URI https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/${WL_PROTOCOLS_VERSION}/${WL_PROTOCOLS_FILE}) +set(WL_PROTOCOLS_HASH af5ca07e13517cdbab33504492cef54a) +set(WL_PROTOCOLS_HASH_TYPE MD5) + if(BLENDER_PLATFORM_ARM) # Unreleased version with macOS arm support. set(ISPC_URI https://github.com/ispc/ispc/archive/f5949c055eb9eeb93696978a3da4bfb3a6a30b35.zip) @@ -494,5 +500,11 @@ set(HARU_HASH 4f916aa49c3069b3a10850013c507460) set(HARU_HASH_TYPE MD5) set(HARU_FILE libharu-${HARU_VERSION}.tar.gz) +set(ZSTD_VERSION 1.5.0) +set(ZSTD_URI https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}/zstd-${ZSTD_VERSION}.tar.gz) +set(ZSTD_HASH 5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94) +set(ZSTD_HASH_TYPE SHA256) +set(ZSTD_FILE zstd-${ZSTD_VERSION}.tar.gz) + set(SSE2NEON_GIT https://github.com/DLTcollab/sse2neon.git) set(SSE2NEON_GIT_HASH fe5ff00bb8d19b327714a3c290f3e2ce81ba3525) diff --git a/build_files/build_environment/cmake/wayland_protocols.cmake b/build_files/build_environment/cmake/wayland_protocols.cmake new file mode 100644 index 00000000000..02db453be42 --- /dev/null +++ b/build_files/build_environment/cmake/wayland_protocols.cmake @@ -0,0 +1,27 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ***** END GPL LICENSE BLOCK ***** + +ExternalProject_Add(external_wayland_protocols + URL file://${PACKAGE_DIR}/${WL_PROTOCOLS_FILE} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH ${WL_PROTOCOLS_HASH_TYPE}=${WL_PROTOCOLS_HASH} + PREFIX ${BUILD_DIR}/wayland-protocols + CONFIGURE_COMMAND meson --prefix ${LIBDIR}/wayland-protocols . ../external_wayland_protocols -Dtests=false + BUILD_COMMAND ninja + INSTALL_COMMAND ninja install +) diff --git a/build_files/build_environment/cmake/zstd.cmake b/build_files/build_environment/cmake/zstd.cmake new file mode 100644 index 00000000000..86cb2d016c6 --- /dev/null +++ b/build_files/build_environment/cmake/zstd.cmake @@ -0,0 +1,51 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ***** END GPL LICENSE BLOCK ***** + +set(ZSTD_EXTRA_ARGS + -DZSTD_BUILD_PROGRAMS=OFF + -DZSTD_BUILD_SHARED=OFF + -DZSTD_BUILD_STATIC=ON + -DZSTD_BUILD_TESTS=OFF + -DZSTD_LEGACY_SUPPORT=OFF + -DZSTD_LZ4_SUPPORT=OFF + -DZSTD_LZMA_SUPPORT=OFF + -DZSTD_MULTITHREAD_SUPPORT=ON + -DZSTD_PROGRAMS_LINK_SHARED=OFF + -DZSTD_USE_STATIC_RUNTIME=OFF + -DZSTD_ZLIB_SUPPORT=OFF +) + +ExternalProject_Add(external_zstd + URL file://${PACKAGE_DIR}/${ZSTD_FILE} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH ${ZSTD_HASH_TYPE}=${ZSTD_HASH} + PREFIX ${BUILD_DIR}/zstd + SOURCE_SUBDIR build/cmake + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/zstd ${DEFAULT_CMAKE_FLAGS} ${ZSTD_EXTRA_ARGS} + INSTALL_DIR ${LIBDIR}/zstd +) + +if(WIN32) + if(BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_zstd after_install + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/zstd/lib/zstd_static${LIBEXT} ${HARVEST_TARGET}/zstd/lib/zstd_static${LIBEXT} + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/zstd/include/ ${HARVEST_TARGET}/zstd/include/ + DEPENDEES install + ) + endif() +endif() diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 808e154955d..c5b7198d012 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -572,7 +572,7 @@ FFMPEG_FORCE_REBUILD=false FFMPEG_SKIP=false _ffmpeg_list_sep=";" -XR_OPENXR_VERSION="1.0.14" +XR_OPENXR_VERSION="1.0.17" XR_OPENXR_VERSION_SHORT="1.0" XR_OPENXR_VERSION_MIN="1.0.8" XR_OPENXR_VERSION_MAX="2.0" @@ -1073,7 +1073,7 @@ OPENVDB_SOURCE=( "https://github.com/AcademySoftwareFoundation/openvdb/archive/v #~ OPENVDB_SOURCE_REPO_BRANCH="dev" NANOVDB_USE_REPO=false -NANOVDB_SOURCE_REPO_UID="e62f7a0bf1e27397223c61ddeaaf57edf111b77f" +NANOVDB_SOURCE_REPO_UID="dc37d8a631922e7bef46712947dc19b755f3e841" NANOVDB_SOURCE=( "https://github.com/AcademySoftwareFoundation/openvdb/archive/${NANOVDB_SOURCE_REPO_UID}.tar.gz" ) ALEMBIC_USE_REPO=false @@ -1108,9 +1108,9 @@ FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" ) XR_OPENXR_USE_REPO=false XR_OPENXR_SOURCE=("https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_VERSION}.tar.gz") -#~ XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK.git") -#~ XR_OPENXR_REPO_UID="5900c51562769b03bea699dc0352cae56acb6419d" -#~ XR_OPENXR_REPO_BRANCH="master" +XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK.git") +XR_OPENXR_REPO_UID="bf21ccb1007bb531b45d9978919a56ea5059c245" +XR_OPENXR_REPO_BRANCH="master" # C++11 is required now CXXFLAGS_BACK=$CXXFLAGS @@ -1128,6 +1128,7 @@ Those libraries should be available as packages in all recent distributions (opt * Basics of dev environment (cmake, gcc, svn , git, ...). * libjpeg, libpng, libtiff, [openjpeg2], [libopenal]. * libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed). + * libwayland-client0, libwayland-cursor0, libwayland-egl1, libxkbcommon0, libdbus-1-3, libegl1 (Wayland) * libsqlite3, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp. * libsdl2, libglew, libpugixml, libpotrace, [libgmp], [libglewmx], fontconfig, [libharu/libhpdf].\"" @@ -2737,7 +2738,7 @@ _init_openvdb() { _git=false _inst=$INST/openvdb-$OPENVDB_VERSION_SHORT _inst_shortcut=$INST/openvdb - + _openvdb_source=$OPENVDB_SOURCE if [ "$WITH_NANOVDB" = true ]; then _openvdb_source=$NANOVDB_SOURCE @@ -2842,7 +2843,7 @@ compile_OPENVDB() { if [ -d $INST/blosc ]; then cmake_d="$cmake_d -D Blosc_ROOT=$INST/blosc" fi - + cmake $cmake_d .. make -j$THREADS install @@ -3839,6 +3840,7 @@ install_DEB() { _packages="gawk cmake cmake-curses-gui build-essential libjpeg-dev libpng-dev libtiff-dev \ git libfreetype6-dev libfontconfig-dev libx11-dev flex bison libxxf86vm-dev \ libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \ + libwayland-dev wayland-protocols libegl-dev libxkbcommon-dev libdbus-1-dev linux-libc-dev \ libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \ libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \ libsdl2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev \ @@ -4508,6 +4510,7 @@ install_RPM() { _packages="gcc gcc-c++ git make cmake tar bzip2 xz findutils flex bison fontconfig-devel \ libtiff-devel libjpeg-devel libpng-devel sqlite-devel fftw-devel SDL2-devel \ libX11-devel libXi-devel libXcursor-devel libXrandr-devel libXinerama-devel \ + wayland-devel wayland-protocols-devel mesa-libEGL-devel libxkbcommon-devel dbus-devel kernel-headers \ wget ncurses-devel readline-devel $OPENJPEG_DEV openal-soft-devel \ glew-devel yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV patch \ libxml2-devel yaml-cpp-devel tinyxml-devel jemalloc-devel \ diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff index e195ca272de..5a50a3f8756 100644 --- a/build_files/build_environment/patches/ffmpeg.diff +++ b/build_files/build_environment/patches/ffmpeg.diff @@ -68,3 +68,32 @@ + return ret; } +--- a/libavcodec/rl.c ++++ b/libavcodec/rl.c +@@ -71,7 +71,7 @@ av_cold void ff_rl_init(RLTable *rl, + av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) + { + int i, q; +- VLC_TYPE table[1500][2] = {{0}}; ++ VLC_TYPE (*table)[2] = av_calloc(sizeof(VLC_TYPE), 1500 * 2); + VLC vlc = { .table = table, .table_allocated = static_size }; + av_assert0(static_size <= FF_ARRAY_ELEMS(table)); + init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); +@@ -80,8 +80,10 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) + int qmul = q * 2; + int qadd = (q - 1) | 1; + +- if (!rl->rl_vlc[q]) ++ if (!rl->rl_vlc[q]){ ++ av_free(table); + return; ++ } + + if (q == 0) { + qmul = 1; +@@ -113,4 +115,5 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) + rl->rl_vlc[q][i].run = run; + } + } ++ av_free(table); + } diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py index 8e626f8d056..bf842466add 100644 --- a/build_files/cmake/cmake_consistency_check_config.py +++ b/build_files/cmake/cmake_consistency_check_config.py @@ -8,6 +8,9 @@ IGNORE_SOURCE = ( # specific source files "extern/audaspace/", + # Use for `WIN32` only. + "source/creator/blender_launcher_win32.c", + # specific source files "extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp", "extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp", diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index ee6413774aa..ccd5b47c776 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -29,6 +29,7 @@ set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE) set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE) set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE) set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE) +set(WITH_INPUT_IME ON CACHE BOOL "" FORCE) set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE) set(WITH_LIBMV ON CACHE BOOL "" FORCE) set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index 75aafd45c82..b8180d733de 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -30,6 +30,7 @@ set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE) set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE) set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE) set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE) +set(WITH_INPUT_IME ON CACHE BOOL "" FORCE) set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE) set(WITH_LIBMV ON CACHE BOOL "" FORCE) set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE) diff --git a/build_files/windows/autodetect_msvc.cmd b/build_files/windows/autodetect_msvc.cmd index 6cee4765b93..a4ab8929040 100644 --- a/build_files/windows/autodetect_msvc.cmd +++ b/build_files/windows/autodetect_msvc.cmd @@ -1,9 +1,9 @@ echo No explicit msvc version requested, autodetecting version. -call "%~dp0\detect_msvc2017.cmd" +call "%~dp0\detect_msvc2019.cmd" if %ERRORLEVEL% EQU 0 goto DetectionComplete -call "%~dp0\detect_msvc2019.cmd" +call "%~dp0\detect_msvc2017.cmd" if %ERRORLEVEL% EQU 0 goto DetectionComplete call "%~dp0\detect_msvc2022.cmd" diff --git a/doc/python_api/examples/bpy.app.handlers.2.py b/doc/python_api/examples/bpy.app.handlers.2.py index aaaedeabecb..d514fa3fa4b 100644 --- a/doc/python_api/examples/bpy.app.handlers.2.py +++ b/doc/python_api/examples/bpy.app.handlers.2.py @@ -12,6 +12,7 @@ such cases, lock the interface (Render → Lock Interface or Below is an example of a mesh that is altered from a handler: """ + def frame_change_pre(scene): # A triangle that shifts in the z direction zshift = scene.frame_current * 0.1 diff --git a/doc/python_api/examples/bpy.app.timers.5.py b/doc/python_api/examples/bpy.app.timers.5.py index 821a047d7c7..dda5ea12e73 100644 --- a/doc/python_api/examples/bpy.app.timers.5.py +++ b/doc/python_api/examples/bpy.app.timers.5.py @@ -16,10 +16,12 @@ execution_queue = queue.Queue() def run_in_main_thread(function): execution_queue.put(function) + def execute_queued_functions(): while not execution_queue.empty(): function = execution_queue.get() function() return 1.0 + bpy.app.timers.register(execute_queued_functions) diff --git a/doc/python_api/examples/bpy.msgbus.1.py b/doc/python_api/examples/bpy.msgbus.1.py index 21198471ffa..8164272d521 100644 --- a/doc/python_api/examples/bpy.msgbus.1.py +++ b/doc/python_api/examples/bpy.msgbus.1.py @@ -31,11 +31,13 @@ owner = object() subscribe_to = bpy.context.object.location + def msgbus_callback(*args): # This will print: # Something changed! (1, 2, 3) print("Something changed!", args) + bpy.msgbus.subscribe_rna( key=subscribe_to, owner=owner, diff --git a/doc/python_api/examples/bpy.types.Depsgraph.7.py b/doc/python_api/examples/bpy.types.Depsgraph.7.py index 11982730fc9..afea8dfd618 100644 --- a/doc/python_api/examples/bpy.types.Depsgraph.7.py +++ b/doc/python_api/examples/bpy.types.Depsgraph.7.py @@ -44,7 +44,7 @@ class OBJECT_OT_object_to_curve(bpy.types.Operator): # Remove temporary curve. obj.to_curve_clear() # Invoke to_curve() with applying modifiers. - curve_with_modifiers = obj.to_curve(depsgraph, apply_modifiers = True) + curve_with_modifiers = obj.to_curve(depsgraph, apply_modifiers=True) self.report({'INFO'}, f"{len(curve_with_modifiers.splines)} splines in new curve with modifiers.") # Remove temporary curve. obj.to_curve_clear() diff --git a/doc/python_api/examples/gpu.6.py b/doc/python_api/examples/gpu.6.py index 334a606055a..be164a03028 100644 --- a/doc/python_api/examples/gpu.6.py +++ b/doc/python_api/examples/gpu.6.py @@ -21,6 +21,7 @@ batch = batch_for_shader( }, ) + def draw(): shader.bind() shader.uniform_sampler("image", texture) diff --git a/extern/audaspace/include/devices/SoftwareDevice.h b/extern/audaspace/include/devices/SoftwareDevice.h index 209be9941b1..c3af5cfd902 100644 --- a/extern/audaspace/include/devices/SoftwareDevice.h +++ b/extern/audaspace/include/devices/SoftwareDevice.h @@ -266,6 +266,12 @@ protected: void setSpecs(Specs specs); /** + * Sets the audio output specification of the device. + * \param specs The output specification. + */ + void setSpecs(DeviceSpecs specs); + + /** * Empty default constructor. To setup the device call the function create() * and to uninitialize call destroy(). */ diff --git a/extern/audaspace/include/respec/Mixer.h b/extern/audaspace/include/respec/Mixer.h index 600467826cd..9880d5fdcae 100644 --- a/extern/audaspace/include/respec/Mixer.h +++ b/extern/audaspace/include/respec/Mixer.h @@ -88,6 +88,12 @@ public: void setSpecs(Specs specs); /** + * Sets the target specification for superposing. + * \param specs The target specification. + */ + void setSpecs(DeviceSpecs specs); + + /** * Mixes a buffer. * \param buffer The buffer to superpose. * \param start The start sample of the buffer. diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp index 3ffe97661d8..cbfb5e96e6c 100644 --- a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp +++ b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp @@ -78,6 +78,7 @@ void PulseAudioDevice::runMixingThread() if(shouldStop()) { AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr); + AUD_pa_stream_flush(m_stream, nullptr, nullptr); doStop(); return; } @@ -86,7 +87,10 @@ void PulseAudioDevice::runMixingThread() if(AUD_pa_stream_is_corked(m_stream)) AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr); - AUD_pa_mainloop_iterate(m_mainloop, true, nullptr); + // similar to AUD_pa_mainloop_iterate(m_mainloop, false, nullptr); except with a longer timeout + AUD_pa_mainloop_prepare(m_mainloop, 1 << 14); + AUD_pa_mainloop_poll(m_mainloop); + AUD_pa_mainloop_dispatch(m_mainloop); } } diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h index 4b9e1ffea2b..361aa518087 100644 --- a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h +++ b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h @@ -24,6 +24,7 @@ PULSEAUDIO_SYMBOL(pa_context_unref); PULSEAUDIO_SYMBOL(pa_stream_begin_write); PULSEAUDIO_SYMBOL(pa_stream_connect_playback); PULSEAUDIO_SYMBOL(pa_stream_cork); +PULSEAUDIO_SYMBOL(pa_stream_flush); PULSEAUDIO_SYMBOL(pa_stream_is_corked); PULSEAUDIO_SYMBOL(pa_stream_new); PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr); @@ -35,3 +36,6 @@ PULSEAUDIO_SYMBOL(pa_mainloop_free); PULSEAUDIO_SYMBOL(pa_mainloop_get_api); PULSEAUDIO_SYMBOL(pa_mainloop_new); PULSEAUDIO_SYMBOL(pa_mainloop_iterate); +PULSEAUDIO_SYMBOL(pa_mainloop_prepare); +PULSEAUDIO_SYMBOL(pa_mainloop_poll); +PULSEAUDIO_SYMBOL(pa_mainloop_dispatch); diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp index b4632ebb83e..a5382bb9692 100644 --- a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp +++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp @@ -31,65 +31,81 @@ template <class T> void SafeRelease(T **ppT) } } -void WASAPIDevice::runMixingThread() +HRESULT WASAPIDevice::setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size) { - UINT32 buffer_size; + const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); + UINT32 padding; UINT32 length; data_t* buffer; - IAudioRenderClient* render_client = nullptr; + HRESULT result; - { - std::lock_guard<ILockable> lock(*this); + if(FAILED(result = m_audio_client->GetBufferSize(&buffer_size))) + return result; - const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); + if(FAILED(result = m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client)))) + return result; - if(FAILED(m_audio_client->GetBufferSize(&buffer_size))) - goto init_error; + if(FAILED(result = m_audio_client->GetCurrentPadding(&padding))) + return result; - if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client)))) - goto init_error; + length = buffer_size - padding; - if(FAILED(m_audio_client->GetCurrentPadding(&padding))) - goto init_error; + if(FAILED(result = render_client->GetBuffer(length, &buffer))) + return result; - length = buffer_size - padding; + mix((data_t*)buffer, length); - if(FAILED(render_client->GetBuffer(length, &buffer))) - goto init_error; + if(FAILED(result = render_client->ReleaseBuffer(length, 0))) + return result; - mix((data_t*)buffer, length); + m_audio_client->Start(); - if(FAILED(render_client->ReleaseBuffer(length, 0))) - { - init_error: - SafeRelease(&render_client); - doStop(); - return; - } - } + return result; +} - m_audio_client->Start(); +void WASAPIDevice::runMixingThread() +{ + UINT32 buffer_size; + + IAudioRenderClient* render_client = nullptr; + + std::chrono::milliseconds sleep_duration; - auto sleepDuration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2); + bool run_init = true; for(;;) { + HRESULT result = S_OK; + { + UINT32 padding; + UINT32 length; + data_t* buffer; std::lock_guard<ILockable> lock(*this); - if(FAILED(m_audio_client->GetCurrentPadding(&padding))) + if(run_init) + { + result = setupRenderClient(render_client, buffer_size); + + if(FAILED(result)) + goto stop_thread; + + sleep_duration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2); + } + + if(FAILED(result = m_audio_client->GetCurrentPadding(&padding))) goto stop_thread; length = buffer_size - padding; - if(FAILED(render_client->GetBuffer(length, &buffer))) + if(FAILED(result = render_client->GetBuffer(length, &buffer))) goto stop_thread; mix((data_t*)buffer, length); - if(FAILED(render_client->ReleaseBuffer(length, 0))) + if(FAILED(result = render_client->ReleaseBuffer(length, 0))) goto stop_thread; // stop thread @@ -98,53 +114,51 @@ void WASAPIDevice::runMixingThread() stop_thread: m_audio_client->Stop(); SafeRelease(&render_client); - doStop(); - return; + + if(result == AUDCLNT_E_DEVICE_INVALIDATED) + { + DeviceSpecs specs = m_specs; + if(!setupDevice(specs)) + result = S_FALSE; + else + { + setSpecs(specs); + + run_init = true; + } + } + + if(result != AUDCLNT_E_DEVICE_INVALIDATED) + { + doStop(); + return; + } } } - std::this_thread::sleep_for(sleepDuration); + std::this_thread::sleep_for(sleep_duration); } } -WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) : - m_imm_device_enumerator(nullptr), - m_imm_device(nullptr), - m_audio_client(nullptr), - - m_wave_format_extensible({}) +bool WASAPIDevice::setupDevice(DeviceSpecs &specs) { - // initialize COM if it hasn't happened yet - CoInitializeEx(nullptr, COINIT_MULTITHREADED); + SafeRelease(&m_audio_client); + SafeRelease(&m_imm_device); - const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); - const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); const IID IID_IAudioClient = __uuidof(IAudioClient); + if(FAILED(m_imm_device_enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_imm_device))) + return false; + + if(FAILED(m_imm_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audio_client)))) + return false; + WAVEFORMATEXTENSIBLE wave_format_extensible_closest_match; WAVEFORMATEXTENSIBLE* closest_match_pointer = &wave_format_extensible_closest_match; - HRESULT result; - REFERENCE_TIME minimum_time = 0; REFERENCE_TIME buffer_duration; - if(FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void**>(&m_imm_device_enumerator)))) - goto error; - - if(FAILED(m_imm_device_enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_imm_device))) - goto error; - - if(FAILED(m_imm_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audio_client)))) - goto error; - - if(specs.channels == CHANNELS_INVALID) - specs.channels = CHANNELS_STEREO; - if(specs.format == FORMAT_INVALID) - specs.format = FORMAT_FLOAT32; - if(specs.rate == RATE_INVALID) - specs.rate = RATE_48000; - switch(specs.format) { case FORMAT_U8: @@ -203,12 +217,14 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) : m_wave_format_extensible.Format.cbSize = 22; m_wave_format_extensible.Samples.wValidBitsPerSample = m_wave_format_extensible.Format.wBitsPerSample; - result = m_audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, reinterpret_cast<const WAVEFORMATEX*>(&m_wave_format_extensible), reinterpret_cast<WAVEFORMATEX**>(&closest_match_pointer)); + HRESULT result = m_audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, reinterpret_cast<const WAVEFORMATEX*>(&m_wave_format_extensible), reinterpret_cast<WAVEFORMATEX**>(&closest_match_pointer)); if(result == S_FALSE) { + bool errored = false; + if(closest_match_pointer->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) - goto error; + goto closest_match_error; specs.channels = Channels(closest_match_pointer->Format.nChannels); specs.rate = closest_match_pointer->Format.nSamplesPerSec; @@ -220,7 +236,7 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) : else if(closest_match_pointer->Format.wBitsPerSample == 64) specs.format = FORMAT_FLOAT64; else - goto error; + goto closest_match_error; } else if(closest_match_pointer->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) { @@ -239,44 +255,81 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) : specs.format = FORMAT_S32; break; default: - goto error; + goto closest_match_error; break; } } else - goto error; + goto closest_match_error; m_wave_format_extensible = *closest_match_pointer; + if(false) + { + closest_match_error: + errored = true; + } + if(closest_match_pointer != &wave_format_extensible_closest_match) { CoTaskMemFree(closest_match_pointer); closest_match_pointer = &wave_format_extensible_closest_match; } + + if(errored) + return false; } else if(FAILED(result)) - goto error; + return false; if(FAILED(m_audio_client->GetDevicePeriod(nullptr, &minimum_time))) - goto error; + return false; - buffer_duration = REFERENCE_TIME(buffersize) * REFERENCE_TIME(10000000) / REFERENCE_TIME(specs.rate); + buffer_duration = REFERENCE_TIME(m_buffersize) * REFERENCE_TIME(10000000) / REFERENCE_TIME(specs.rate); if(minimum_time > buffer_duration) buffer_duration = minimum_time; - m_specs = specs; - if(FAILED(m_audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, buffer_duration, 0, reinterpret_cast<WAVEFORMATEX*>(&m_wave_format_extensible), nullptr))) + return false; + + return true; +} + +WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) : + m_buffersize(buffersize), + m_imm_device_enumerator(nullptr), + m_imm_device(nullptr), + m_audio_client(nullptr), + + m_wave_format_extensible({}) +{ + // initialize COM if it hasn't happened yet + CoInitializeEx(nullptr, COINIT_MULTITHREADED); + + const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); + const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); + + if(specs.channels == CHANNELS_INVALID) + specs.channels = CHANNELS_STEREO; + if(specs.format == FORMAT_INVALID) + specs.format = FORMAT_FLOAT32; + if(specs.rate == RATE_INVALID) + specs.rate = RATE_48000; + + if(FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void**>(&m_imm_device_enumerator)))) + goto error; + + if(!setupDevice(specs)) goto error; + m_specs = specs; + create(); return; error: - if(closest_match_pointer != &wave_format_extensible_closest_match) - CoTaskMemFree(closest_match_pointer); SafeRelease(&m_imm_device); SafeRelease(&m_imm_device_enumerator); SafeRelease(&m_audio_client); diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.h b/extern/audaspace/plugins/wasapi/WASAPIDevice.h index 375f03bd255..3b11adc98ef 100644 --- a/extern/audaspace/plugins/wasapi/WASAPIDevice.h +++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.h @@ -43,16 +43,21 @@ AUD_NAMESPACE_BEGIN class AUD_PLUGIN_API WASAPIDevice : public ThreadedDevice { private: + int m_buffersize; IMMDeviceEnumerator* m_imm_device_enumerator; IMMDevice* m_imm_device; IAudioClient* m_audio_client; WAVEFORMATEXTENSIBLE m_wave_format_extensible; + AUD_LOCAL HRESULT setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size); + /** * Streaming thread main function. */ AUD_LOCAL void runMixingThread(); + AUD_LOCAL bool setupDevice(DeviceSpecs& specs); + // delete copy constructor and operator= WASAPIDevice(const WASAPIDevice&) = delete; WASAPIDevice& operator=(const WASAPIDevice&) = delete; diff --git a/extern/audaspace/src/devices/SoftwareDevice.cpp b/extern/audaspace/src/devices/SoftwareDevice.cpp index 7a2561515f4..e11b49a0967 100644 --- a/extern/audaspace/src/devices/SoftwareDevice.cpp +++ b/extern/audaspace/src/devices/SoftwareDevice.cpp @@ -756,6 +756,7 @@ void SoftwareDevice::mix(data_t* buffer, int length) // get the buffer from the source pos = 0; len = length; + eos = false; // update 3D Info sound->update(); @@ -842,6 +843,27 @@ void SoftwareDevice::setSpecs(Specs specs) { sound->setSpecs(specs); } + + for(auto& sound : m_pausedSounds) + { + sound->setSpecs(specs); + } +} + +void SoftwareDevice::setSpecs(DeviceSpecs specs) +{ + m_specs = specs; + m_mixer->setSpecs(specs); + + for(auto& sound : m_playingSounds) + { + sound->setSpecs(specs.specs); + } + + for(auto& sound : m_pausedSounds) + { + sound->setSpecs(specs.specs); + } } SoftwareDevice::SoftwareDevice() diff --git a/extern/audaspace/src/respec/Mixer.cpp b/extern/audaspace/src/respec/Mixer.cpp index ad8d885df4e..15872fbcff2 100644 --- a/extern/audaspace/src/respec/Mixer.cpp +++ b/extern/audaspace/src/respec/Mixer.cpp @@ -21,9 +21,25 @@ AUD_NAMESPACE_BEGIN -Mixer::Mixer(DeviceSpecs specs) : - m_specs(specs) +Mixer::Mixer(DeviceSpecs specs) { + setSpecs(specs); +} + +DeviceSpecs Mixer::getSpecs() const +{ + return m_specs; +} + +void Mixer::setSpecs(Specs specs) +{ + m_specs.specs = specs; +} + +void Mixer::setSpecs(DeviceSpecs specs) +{ + m_specs = specs; + switch(m_specs.format) { case FORMAT_U8: @@ -54,16 +70,6 @@ Mixer::Mixer(DeviceSpecs specs) : } } -DeviceSpecs Mixer::getSpecs() const -{ - return m_specs; -} - -void Mixer::setSpecs(Specs specs) -{ - m_specs.specs = specs; -} - void Mixer::clear(int length) { m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs)); diff --git a/extern/glog/README.blender b/extern/glog/README.blender index 5b4dab199bf..bc2ca9f958e 100644 --- a/extern/glog/README.blender +++ b/extern/glog/README.blender @@ -7,3 +7,4 @@ Local modifications: checks for functions and so are needed. * Added special definitions of HAVE_SNPRINTF and HAVE_LIB_GFLAGS in Windows' specific config.h. +* Silenced syscall deprecation warnings on macOS >= 10.12. diff --git a/extern/glog/src/raw_logging.cc b/extern/glog/src/raw_logging.cc index 3bbfda31868..15d14f6e4f5 100644 --- a/extern/glog/src/raw_logging.cc +++ b/extern/glog/src/raw_logging.cc @@ -59,7 +59,7 @@ # include <unistd.h> #endif -#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H) +#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && (!(defined OS_MACOSX)) # define safe_write(fd, s, len) syscall(SYS_write, fd, s, len) #else // Not so safe, but what can you do? diff --git a/extern/glog/src/utilities.cc b/extern/glog/src/utilities.cc index 25c4b760f1c..6387e14e123 100644 --- a/extern/glog/src/utilities.cc +++ b/extern/glog/src/utilities.cc @@ -259,7 +259,13 @@ pid_t GetTID() { #endif static bool lacks_gettid = false; if (!lacks_gettid) { +#ifdef OS_MACOSX + uint64_t tid64; + const int error = pthread_threadid_np(NULL, &tid64); + pid_t tid = error ? -1 : (pid_t)tid64; +#else pid_t tid = syscall(__NR_gettid); +#endif if (tid != -1) { return tid; } diff --git a/intern/atomic/intern/atomic_ops_unix.h b/intern/atomic/intern/atomic_ops_unix.h index dc1e71cda76..b08a0e9bc28 100644 --- a/intern/atomic/intern/atomic_ops_unix.h +++ b/intern/atomic/intern/atomic_ops_unix.h @@ -49,9 +49,9 @@ #include "atomic_ops_utils.h" -#if defined(__arm__) -/* Attempt to fix compilation error on Debian armel kernel. - * arm7 architecture does have both 32 and 64bit atomics, however +#if defined(__arm__) || defined(__riscv) +/* Attempt to fix compilation error on Debian armel and RISC-V kernels. + * Both architectures do have both 32 and 64bit atomics, however * its gcc doesn't have __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n defined. */ # define JE_FORCE_SYNC_COMPARE_AND_SWAP_1 diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 71e2f9fc3a5..b014811211f 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -482,7 +482,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): transparent_max_bounces: IntProperty( name="Transparent Max Bounces", - description="Maximum number of transparent bounces", + description="Maximum number of transparent bounces. This is independent of maximum number of other bounces ", min=0, max=1024, default=8, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 3d990467f04..30892cdbbc0 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -485,10 +485,12 @@ class CYCLES_RENDER_PT_light_paths_max_bounces(CyclesButtonsPanel, Panel): col = layout.column(align=True) col.prop(cscene, "diffuse_bounces", text="Diffuse") col.prop(cscene, "glossy_bounces", text="Glossy") - col.prop(cscene, "transparent_max_bounces", text="Transparency") col.prop(cscene, "transmission_bounces", text="Transmission") col.prop(cscene, "volume_bounces", text="Volume") + col = layout.column(align=True) + col.prop(cscene, "transparent_max_bounces", text="Transparent") + class CYCLES_RENDER_PT_light_paths_clamping(CyclesButtonsPanel, Panel): bl_label = "Clamping" diff --git a/intern/cycles/blender/blender_image.cpp b/intern/cycles/blender/blender_image.cpp index 3a9d159e461..f27275bd457 100644 --- a/intern/cycles/blender/blender_image.cpp +++ b/intern/cycles/blender/blender_image.cpp @@ -137,9 +137,9 @@ bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata, /* Premultiply, byte images are always straight for Blender. */ unsigned char *cp = (unsigned char *)pixels; for (size_t i = 0; i < num_pixels; i++, cp += channels) { - cp[0] = (cp[0] * cp[3]) >> 8; - cp[1] = (cp[1] * cp[3]) >> 8; - cp[2] = (cp[2] * cp[3]) >> 8; + cp[0] = (cp[0] * cp[3]) / 255; + cp[1] = (cp[1] * cp[3]) / 255; + cp[2] = (cp[2] * cp[3]) / 255; } } } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 635392fb3d4..f5e8db2aee1 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -109,23 +109,23 @@ void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob } Geometry *geom = object->get_geometry(); - geom->set_use_motion_blur(false); - geom->set_motion_steps(0); - uint motion_steps; + int motion_steps = 0; + bool use_motion_blur = false; if (need_motion == Scene::MOTION_BLUR) { motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS); - geom->set_motion_steps(motion_steps); if (motion_steps && object_use_deform_motion(b_parent, b_ob)) { - geom->set_use_motion_blur(true); + use_motion_blur = true; } } else { motion_steps = 3; - geom->set_motion_steps(motion_steps); } + geom->set_use_motion_blur(use_motion_blur); + geom->set_motion_steps(motion_steps); + motion.resize(motion_steps, transform_empty()); if (motion_steps) { diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 3b3a193b3e8..ce399579e25 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -404,8 +404,6 @@ void BlenderSync::sync_film(BL::SpaceView3D &b_v3d) Film *film = scene->film; - vector<Pass> prevpasses = scene->passes; - if (b_v3d) { film->set_display_pass(update_viewport_display_passes(b_v3d, scene->passes)); } @@ -435,11 +433,6 @@ void BlenderSync::sync_film(BL::SpaceView3D &b_v3d) break; } } - - if (!Pass::equals(prevpasses, scene->passes)) { - film->tag_passes_update(scene, prevpasses, false); - film->tag_modified(); - } } /* Render Layer */ @@ -749,10 +742,13 @@ vector<Pass> BlenderSync::sync_render_passes(BL::Scene &b_scene, DENOISING_CLEAN_ALL_PASSES); scene->film->set_denoising_prefiltered_pass(denoising.store_passes && denoising.type == DENOISER_NLM); - scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold()); - scene->film->tag_passes_update(scene, passes); - scene->integrator->tag_update(scene, Integrator::UPDATE_ALL); + + if (!Pass::equals(passes, scene->passes)) { + scene->film->tag_passes_update(scene, passes); + scene->film->tag_modified(); + scene->integrator->tag_update(scene, Integrator::UPDATE_ALL); + } return passes; } diff --git a/intern/cycles/blender/blender_viewport.cpp b/intern/cycles/blender/blender_viewport.cpp index 07408fee218..18bdfc74de0 100644 --- a/intern/cycles/blender/blender_viewport.cpp +++ b/intern/cycles/blender/blender_viewport.cpp @@ -40,8 +40,8 @@ BlenderViewportParameters::BlenderViewportParameters(BL::SpaceView3D &b_v3d) BL::View3DShading shading = b_v3d.shading(); PointerRNA cshading = RNA_pointer_get(&shading.ptr, "cycles"); - /* We only copy the shading parameters if we are in look dev mode. otherwise - * defaults are being used. These defaults mimic normal render settings */ + /* We only copy the shading parameters if we are in look-dev mode. + * Otherwise defaults are being used. These defaults mimic normal render settings. */ if (shading.type() == BL::View3DShading::type_RENDERED) { use_scene_world = shading.use_scene_world_render(); use_scene_lights = shading.use_scene_lights_render(); diff --git a/intern/cycles/kernel/bvh/bvh_util.h b/intern/cycles/kernel/bvh/bvh_util.h index 6c152cbb249..867ea3af8d1 100644 --- a/intern/cycles/kernel/bvh/bvh_util.h +++ b/intern/cycles/kernel/bvh/bvh_util.h @@ -86,8 +86,7 @@ ccl_device_inline float3 smooth_surface_offset(KernelGlobals *kg, ShaderData *sd float3 P = V[0] * u + V[1] * v + V[2] * w; /* Local space */ float3 n = N[0] * u + N[1] * v + N[2] * w; /* We get away without normalization */ - n = normalize( - transform_direction_transposed_auto(&sd->ob_itfm, n)); /* Normal x scale, world space */ + object_normal_transform(kg, sd, &n); /* Normal x scale, world space */ /* Parabolic approximation */ float a = dot(N[2] - N[0], V[0] - V[2]); diff --git a/intern/cycles/kernel/geom/geom_curve_intersect.h b/intern/cycles/kernel/geom/geom_curve_intersect.h index 40b2059194b..e25bf5b4660 100644 --- a/intern/cycles/kernel/geom/geom_curve_intersect.h +++ b/intern/cycles/kernel/geom/geom_curve_intersect.h @@ -237,7 +237,7 @@ ccl_device bool curve_intersect_iterative(const float3 ray_dir, return false; /* Rejects NaNs */ } - /* Backface culling. */ + /* Back-face culling. */ const float3 R = normalize(Q - P); const float3 U = dradiusdu * R + dPdu; const float3 V = cross(dPdu, R); @@ -458,10 +458,12 @@ ccl_device_inline bool cylinder_culling_test(const float2 p1, const float2 p2, c return num * num <= r * r * den2; } -/*! Intersects a ray with a quad with backface culling - * enabled. The quad v0,v1,v2,v3 is split into two triangles - * v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two - * triangles gets intersected. */ +/** + * Intersects a ray with a quad with back-face culling + * enabled. The quad v0,v1,v2,v3 is split into two triangles + * v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two + * triangles gets intersected. + */ ccl_device_inline bool ribbon_intersect_quad(const float ray_tfar, const float3 quad_v0, const float3 quad_v1, diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index bdedf0c20a8..d1f33a4d0f0 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -40,7 +40,7 @@ ccl_device_noinline void compute_light_pass( /* Evaluate surface shader. */ shader_eval_surface(kg, sd, &state, NULL, state.flag); - /* TODO, disable more closures we don't need besides transparent */ + /* TODO: disable more closures we don't need besides transparent. */ shader_bsdf_disable_transparency(kg, sd); /* Init ray. */ diff --git a/intern/cycles/kernel/svm/svm_vector_rotate.h b/intern/cycles/kernel/svm/svm_vector_rotate.h index 79a4ec2c40e..50045752484 100644 --- a/intern/cycles/kernel/svm/svm_vector_rotate.h +++ b/intern/cycles/kernel/svm/svm_vector_rotate.h @@ -50,24 +50,29 @@ ccl_device void svm_node_vector_rotate(ShaderData *sd, } else { float3 axis; + float axis_length; switch (type) { case NODE_VECTOR_ROTATE_TYPE_AXIS_X: axis = make_float3(1.0f, 0.0f, 0.0f); + axis_length = 1.0f; break; case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: axis = make_float3(0.0f, 1.0f, 0.0f); + axis_length = 1.0f; break; case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: axis = make_float3(0.0f, 0.0f, 1.0f); + axis_length = 1.0f; break; default: - axis = normalize(stack_load_float3(stack, axis_stack_offset)); + axis = stack_load_float3(stack, axis_stack_offset); + axis_length = len(axis); break; } float angle = stack_load_float(stack, angle_stack_offset); angle = invert ? -angle : angle; - result = (len_squared(axis) != 0.0f) ? - rotate_around_axis(vector - center, axis, angle) + center : + result = (axis_length != 0.0f) ? + rotate_around_axis(vector - center, axis / axis_length, angle) + center : vector; } diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 7970381f338..5abb4750764 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -81,7 +81,7 @@ class Camera : public Node { /* ** Rolling shutter effect. ** */ /* Defines rolling shutter effect type. */ NODE_SOCKET_API(RollingShutterType, rolling_shutter_type) - /* Specifies exposure time of scanlines when using + /* Specifies exposure time of scan-lines when using * rolling shutter effect. */ NODE_SOCKET_API(float, rolling_shutter_duration) diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp index fb6394e8917..4da11c8a140 100644 --- a/intern/cycles/render/image_vdb.cpp +++ b/intern/cycles/render/image_vdb.cpp @@ -16,8 +16,10 @@ #include "render/image_vdb.h" +#include "util/util_logging.h" +#include "util/util_openvdb.h" + #ifdef WITH_OPENVDB -# include <openvdb/openvdb.h> # include <openvdb/tools/Dense.h> #endif #ifdef WITH_NANOVDB @@ -26,6 +28,57 @@ CCL_NAMESPACE_BEGIN +#ifdef WITH_OPENVDB +struct NumChannelsOp { + int num_channels = 0; + + template<typename GridType, typename FloatGridType, typename FloatDataType, int channels> + bool operator()(const openvdb::GridBase::ConstPtr &) + { + num_channels = channels; + return true; + } +}; + +struct ToDenseOp { + openvdb::CoordBBox bbox; + void *pixels; + + template<typename GridType, typename FloatGridType, typename FloatDataType, int channels> + bool operator()(const openvdb::GridBase::ConstPtr &grid) + { + openvdb::tools::Dense<FloatDataType, openvdb::tools::LayoutXYZ> dense(bbox, + (FloatDataType *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<GridType>(grid), dense); + return true; + } +}; + +# ifdef WITH_NANOVDB +struct ToNanoOp { + nanovdb::GridHandle<> nanogrid; + + template<typename GridType, typename FloatGridType, typename FloatDataType, int channels> + bool operator()(const openvdb::GridBase::ConstPtr &grid) + { + if constexpr (!std::is_same_v<GridType, openvdb::MaskGrid>) { + try { + nanogrid = nanovdb::openToNanoVDB( + FloatGridType(*openvdb::gridConstPtrCast<GridType>(grid))); + } + catch (const std::exception &e) { + VLOG(1) << "Error converting OpenVDB to NanoVDB grid: " << e.what(); + } + return true; + } + else { + return false; + } + } +}; +# endif +#endif + VDBImageLoader::VDBImageLoader(const string &grid_name) : grid_name(grid_name) { } @@ -41,98 +94,40 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet return false; } - bbox = grid->evalActiveVoxelBoundingBox(); - if (bbox.empty()) { + /* Get number of channels from type. */ + NumChannelsOp op; + if (!openvdb::grid_type_operation(grid, op)) { return false; } - /* Set dimensions. */ - openvdb::Coord dim = bbox.dim(); - metadata.width = dim.x(); - metadata.height = dim.y(); - metadata.depth = dim.z(); + metadata.channels = op.num_channels; /* Set data type. */ - if (grid->isType<openvdb::FloatGrid>()) { - metadata.channels = 1; -# ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid)); - } -# endif - } - else if (grid->isType<openvdb::Vec3fGrid>()) { - metadata.channels = 3; -# ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid)); - } -# endif - } - else if (grid->isType<openvdb::BoolGrid>()) { - metadata.channels = 1; -# ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB( - openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid))); - } -# endif - } - else if (grid->isType<openvdb::DoubleGrid>()) { - metadata.channels = 1; -# ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB( - openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid))); - } -# endif - } - else if (grid->isType<openvdb::Int32Grid>()) { - metadata.channels = 1; # ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB( - openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid))); + if (features.has_nanovdb) { + /* NanoVDB expects no inactive leaf nodes. */ + /*openvdb::FloatGrid &pruned_grid = *openvdb::gridPtrCast<openvdb::FloatGrid>(grid); + openvdb::tools::pruneInactive(pruned_grid.tree()); + nanogrid = nanovdb::openToNanoVDB(pruned_grid);*/ + ToNanoOp op; + if (!openvdb::grid_type_operation(grid, op)) { + return false; } -# endif - } - else if (grid->isType<openvdb::Int64Grid>()) { - metadata.channels = 1; -# ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB( - openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid))); - } -# endif + nanogrid = std::move(op.nanogrid); } - else if (grid->isType<openvdb::Vec3IGrid>()) { - metadata.channels = 3; -# ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB( - openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid))); - } -# endif - } - else if (grid->isType<openvdb::Vec3dGrid>()) { - metadata.channels = 3; -# ifdef WITH_NANOVDB - if (features.has_nanovdb) { - nanogrid = nanovdb::openToNanoVDB( - openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid))); - } -# endif - } - else if (grid->isType<openvdb::MaskGrid>()) { - metadata.channels = 1; -# ifdef WITH_NANOVDB - return false; // Unsupported # endif - } - else { + + /* Set dimensions. */ + bbox = grid->evalActiveVoxelBoundingBox(); + if (bbox.empty()) { return false; } + openvdb::Coord dim = bbox.dim(); + metadata.width = dim.x(); + metadata.height = dim.y(); + metadata.depth = dim.z(); + # ifdef WITH_NANOVDB if (nanogrid) { metadata.byte_size = nanogrid.size(); @@ -200,45 +195,10 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size else # endif { - if (grid->isType<openvdb::FloatGrid>()) { - openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense); - } - else if (grid->isType<openvdb::Vec3fGrid>()) { - openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense( - bbox, (openvdb::Vec3f *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense); - } - else if (grid->isType<openvdb::BoolGrid>()) { - openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense); - } - else if (grid->isType<openvdb::DoubleGrid>()) { - openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense); - } - else if (grid->isType<openvdb::Int32Grid>()) { - openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense); - } - else if (grid->isType<openvdb::Int64Grid>()) { - openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense); - } - else if (grid->isType<openvdb::Vec3IGrid>()) { - openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense( - bbox, (openvdb::Vec3f *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense); - } - else if (grid->isType<openvdb::Vec3dGrid>()) { - openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense( - bbox, (openvdb::Vec3f *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense); - } - else if (grid->isType<openvdb::MaskGrid>()) { - openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); - openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense); - } + ToDenseOp op; + op.pixels = pixels; + op.bbox = bbox; + openvdb::grid_type_operation(grid, op); } return true; #else diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index a6dab06f8f2..2e7fe50d5cf 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -209,7 +209,7 @@ class SceneParams { int curve_subdivisions() { - /* Matching the tesselation rate limit in Embree. */ + /* Matching the tessellation rate limit in Embree. */ return clamp(1 << hair_subdivisions, 1, 16); } }; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index ca90af77f6e..19d4a66353d 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -227,66 +227,25 @@ void Session::run_gpu() progress.set_render_start_time(); while (!progress.get_cancel()) { - /* advance to next tile */ - bool no_tiles = !tile_manager.next(); + const bool no_tiles = !run_update_for_next_iteration(); - DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN; if (no_tiles) { - kernel_state = device->get_active_kernel_switch_state(); - } - - if (params.background) { - /* if no work left and in background mode, we can stop immediately */ - if (no_tiles) { + if (params.background) { + /* if no work left and in background mode, we can stop immediately */ progress.set_status("Finished"); break; } } - else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) { - reset_gpu(tile_manager.params, params.samples); + if (run_wait_for_work(no_tiles)) { + continue; } - else { - /* if in interactive mode, and we are either paused or done for now, - * wait for pause condition notify to wake up again */ - thread_scoped_lock pause_lock(pause_mutex); - - if (!pause && !tile_manager.done()) { - /* reset could have happened after no_tiles was set, before this lock. - * in this case we shall not wait for pause condition - */ - } - else if (pause || no_tiles) { - update_status_time(pause, no_tiles); - - while (1) { - scoped_timer pause_timer; - pause_cond.wait(pause_lock); - if (pause) { - progress.add_skip_time(pause_timer, params.background); - } - - update_status_time(pause, no_tiles); - progress.set_update(); - - if (!pause) - break; - } - } - - if (progress.get_cancel()) - break; + if (progress.get_cancel()) { + break; } if (!no_tiles) { - /* update scene */ - scoped_timer update_timer; - if (update_scene()) { - profiler.reset(scene->shaders.size(), scene->objects.size()); - } - progress.add_skip_time(update_timer, params.background); - if (!device->error_message().empty()) progress.set_error(device->error_message()); @@ -729,82 +688,27 @@ void Session::run_cpu() last_update_time = time_dt(); last_display_time = last_update_time; - { - /* reset once to start */ - thread_scoped_lock reset_lock(delayed_reset.mutex); - thread_scoped_lock buffers_lock(buffers_mutex); - thread_scoped_lock display_lock(display_mutex); - - reset_(delayed_reset.params, delayed_reset.samples); - delayed_reset.do_reset = false; - } - while (!progress.get_cancel()) { - /* advance to next tile */ - bool no_tiles = !tile_manager.next(); + const bool no_tiles = !run_update_for_next_iteration(); bool need_copy_to_display_buffer = false; - DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN; if (no_tiles) { - kernel_state = device->get_active_kernel_switch_state(); - } - - if (params.background) { - /* if no work left and in background mode, we can stop immediately */ - if (no_tiles) { + if (params.background) { + /* if no work left and in background mode, we can stop immediately */ progress.set_status("Finished"); break; } } - else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) { - reset_cpu(tile_manager.params, params.samples); + if (run_wait_for_work(no_tiles)) { + continue; } - else { - /* if in interactive mode, and we are either paused or done for now, - * wait for pause condition notify to wake up again */ - thread_scoped_lock pause_lock(pause_mutex); - - if (!pause && delayed_reset.do_reset) { - /* reset once to start */ - thread_scoped_lock reset_lock(delayed_reset.mutex); - thread_scoped_lock buffers_lock(buffers_mutex); - thread_scoped_lock display_lock(display_mutex); - - reset_(delayed_reset.params, delayed_reset.samples); - delayed_reset.do_reset = false; - } - else if (pause || no_tiles) { - update_status_time(pause, no_tiles); - - while (1) { - scoped_timer pause_timer; - pause_cond.wait(pause_lock); - if (pause) { - progress.add_skip_time(pause_timer, params.background); - } - - update_status_time(pause, no_tiles); - progress.set_update(); - - if (!pause) - break; - } - } - - if (progress.get_cancel()) - break; + if (progress.get_cancel()) { + break; } if (!no_tiles) { - /* update scene */ - scoped_timer update_timer; - if (update_scene()) { - profiler.reset(scene->shaders.size(), scene->objects.size()); - } - progress.add_skip_time(update_timer, params.background); - if (!device->error_message().empty()) progress.set_error(device->error_message()); @@ -894,6 +798,63 @@ void Session::run() progress.set_update(); } +bool Session::run_update_for_next_iteration() +{ + thread_scoped_lock scene_lock(scene->mutex); + thread_scoped_lock reset_lock(delayed_reset.mutex); + + if (delayed_reset.do_reset) { + thread_scoped_lock buffers_lock(buffers_mutex); + reset_(delayed_reset.params, delayed_reset.samples); + delayed_reset.do_reset = false; + } + + const bool have_tiles = tile_manager.next(); + + if (have_tiles) { + scoped_timer update_timer; + if (update_scene()) { + profiler.reset(scene->shaders.size(), scene->objects.size()); + } + progress.add_skip_time(update_timer, params.background); + } + + return have_tiles; +} + +bool Session::run_wait_for_work(bool no_tiles) +{ + /* In an offline rendering there is no pause, and no tiles will mean the job is fully done. */ + if (params.background) { + return false; + } + + thread_scoped_lock pause_lock(pause_mutex); + + if (!pause && !no_tiles) { + return false; + } + + update_status_time(pause, no_tiles); + + while (true) { + scoped_timer pause_timer; + pause_cond.wait(pause_lock); + if (pause) { + progress.add_skip_time(pause_timer, params.background); + } + + update_status_time(pause, no_tiles); + progress.set_update(); + + if (!pause) { + break; + } + } + + return no_tiles; +} + bool Session::draw(BufferParams &buffer_params, DeviceDrawParams &draw_params) { if (device_use_gl) @@ -1012,8 +973,6 @@ void Session::wait() bool Session::update_scene() { - thread_scoped_lock scene_lock(scene->mutex); - /* update camera if dimensions changed for progressive render. the camera * knows nothing about progressive or cropped rendering, it just gets the * image dimensions passed in */ diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 43ff07e5884..bc3b8366c05 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -178,6 +178,9 @@ class Session { void run(); + bool run_update_for_next_iteration(); + bool run_wait_for_work(bool no_tiles); + void update_status_time(bool show_pause = false, bool show_done = false); void render(bool use_denoise); diff --git a/intern/cycles/util/util_openvdb.h b/intern/cycles/util/util_openvdb.h index a3ebb03e5a4..ae5326e3199 100644 --- a/intern/cycles/util/util_openvdb.h +++ b/intern/cycles/util/util_openvdb.h @@ -25,6 +25,42 @@ namespace openvdb { using Vec4fTree = tree::Tree4<Vec4f, 5, 4, 3>::Type; using Vec4fGrid = Grid<Vec4fTree>; +/* Apply operation to known grid types. */ +template<typename OpType> +bool grid_type_operation(const openvdb::GridBase::ConstPtr &grid, OpType &&op) +{ + if (grid->isType<openvdb::FloatGrid>()) { + return op.template operator()<openvdb::FloatGrid, openvdb::FloatGrid, float, 1>(grid); + } + else if (grid->isType<openvdb::Vec3fGrid>()) { + return op.template operator()<openvdb::Vec3fGrid, openvdb::Vec3fGrid, openvdb::Vec3f, 3>(grid); + } + else if (grid->isType<openvdb::BoolGrid>()) { + return op.template operator()<openvdb::BoolGrid, openvdb::FloatGrid, float, 1>(grid); + } + else if (grid->isType<openvdb::DoubleGrid>()) { + return op.template operator()<openvdb::DoubleGrid, openvdb::FloatGrid, float, 1>(grid); + } + else if (grid->isType<openvdb::Int32Grid>()) { + return op.template operator()<openvdb::Int32Grid, openvdb::FloatGrid, float, 1>(grid); + } + else if (grid->isType<openvdb::Int64Grid>()) { + return op.template operator()<openvdb::Int64Grid, openvdb::FloatGrid, float, 1>(grid); + } + else if (grid->isType<openvdb::Vec3IGrid>()) { + return op.template operator()<openvdb::Vec3IGrid, openvdb::Vec3fGrid, openvdb::Vec3f, 3>(grid); + } + else if (grid->isType<openvdb::Vec3dGrid>()) { + return op.template operator()<openvdb::Vec3dGrid, openvdb::Vec3fGrid, openvdb::Vec3f, 3>(grid); + } + else if (grid->isType<openvdb::MaskGrid>()) { + return op.template operator()<openvdb::MaskGrid, openvdb::FloatGrid, float, 1>(grid); + } + else { + return false; + } +} + }; // namespace openvdb #endif diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 77ec307e604..76cac1049fb 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -155,6 +155,9 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL) endif() elseif(APPLE AND NOT WITH_GHOST_X11) + if(WITH_INPUT_IME) + add_definitions(-DWITH_INPUT_IME) + endif() list(APPEND SRC intern/GHOST_DisplayManagerCocoa.mm intern/GHOST_SystemCocoa.mm @@ -285,16 +288,37 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) ${dbus_INCLUDE_DIRS} ) + include(CheckSymbolExists) + set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE") + check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE) + if (HAVE_MEMFD_CREATE) + add_definitions(-DHAVE_MEMFD_CREATE) + endif() + list(APPEND SRC intern/GHOST_SystemWayland.cpp intern/GHOST_WindowWayland.cpp intern/GHOST_SystemWayland.h + intern/GHOST_WaylandCursorSettings.h intern/GHOST_WindowWayland.h ) pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner) - pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) + + pkg_check_modules(wayland-protocols wayland-protocols>=1.15) + if (${wayland-protocols_FOUND}) + pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) + else() + find_path(WAYLAND_PROTOCOLS_DIR + NAMES unstable/xdg-decoration/xdg-decoration-unstable-v1.xml + PATH_SUFFIXES share/wayland-protocols + ) + endif() + + if (NOT EXISTS ${WAYLAND_PROTOCOLS_DIR}) + message(FATAL_ERROR "path to wayland-protocols not found") + endif() # Generate protocols bindings. macro(generate_protocol_bindings NAME PROT_DEF) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 2bd9af6df5c..db3f9bd561e 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -96,7 +96,7 @@ extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consu * \param systemhandle: The handle to the system. * \return The number of milliseconds. */ -extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle); +extern uint64_t GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle); /** * Installs a timer. @@ -110,8 +110,8 @@ extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle); * \return A timer task (0 if timer task installation failed). */ extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, - GHOST_TUns64 delay, - GHOST_TUns64 interval, + uint64_t delay, + uint64_t interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData); @@ -133,7 +133,7 @@ extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, * \param systemhandle: The handle to the system. * \return The number of displays. */ -extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle); +extern uint8_t GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle); /** * Returns the dimensions of the main display on this system. @@ -142,8 +142,8 @@ extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle); * \param height: A pointer the height gets put in. */ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, - GHOST_TUns32 *width, - GHOST_TUns32 *height); + uint32_t *width, + uint32_t *height); /** * Returns the dimensions of all displays combine @@ -154,8 +154,8 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, * \param height: A pointer the height gets put in. */ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, - GHOST_TUns32 *width, - GHOST_TUns32 *height); + uint32_t *width, + uint32_t *height); /** * Create a new window. @@ -178,10 +178,10 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle parent_windowhandle, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, bool is_dialog, GHOST_TDrawingContextType type, @@ -360,13 +360,13 @@ extern GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle, * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle, - GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, int hotY, - GHOST_TUns8 canInvertColor); + bool canInvertColor); /** * Returns the visibility state of the cursor. @@ -391,8 +391,8 @@ extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, * \return Indication of success. */ extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, - GHOST_TInt32 *x, - GHOST_TInt32 *y); + int32_t *x, + int32_t *y); /** * Updates the location of the cursor (location in screen coordinates). @@ -403,8 +403,8 @@ extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, - GHOST_TInt32 x, - GHOST_TInt32 y); + int32_t x, + int32_t y); /** * Grabs the cursor for a modal operation, to keep receiving @@ -467,7 +467,7 @@ extern void GHOST_setNDOFDeadZone(float deadzone); /** * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop */ -extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept); +extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool canAccept); /** * Returns the event type. @@ -481,7 +481,7 @@ extern GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle); * \param eventhandle: The handle to the event. * \return The event generation time. */ -extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle); +extern uint64_t GHOST_GetEventTime(GHOST_EventHandle eventhandle); /** * Returns the window this event was generated on, @@ -507,7 +507,7 @@ extern GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhand /** * Changes the timer callback. - * \param timertaskhandle: The handle to the timertask. + * \param timertaskhandle: The handle to the timer-task. * \param timerProc: The timer callback. */ extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle, @@ -515,14 +515,14 @@ extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle, /** * Returns the timer user data. - * \param timertaskhandle: The handle to the timertask. + * \param timertaskhandle: The handle to the timer-task. * \return The timer user data. */ extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle); /** * Changes the time user data. - * \param timertaskhandle: The handle to the timertask. + * \param timertaskhandle: The handle to the timer-task. * \param userdata: The timer user data. */ extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, @@ -595,7 +595,7 @@ void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle); * \param width: The new width of the client area of the window. * \return Indication of success. */ -extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOST_TUns32 width); +extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, uint32_t width); /** * Resizes client rectangle height. @@ -603,7 +603,7 @@ extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOS * \param height: The new height of the client area of the window. * \return Indication of success. */ -extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns32 height); +extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, uint32_t height); /** * Resizes client rectangle. @@ -613,8 +613,8 @@ extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHO * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, - GHOST_TUns32 width, - GHOST_TUns32 height); + uint32_t width, + uint32_t height); /** * Converts a point in screen coordinates to client rectangle coordinates @@ -624,11 +624,8 @@ extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, * \param outX: The x-coordinate in the client rectangle. * \param outY: The y-coordinate in the client rectangle. */ -extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, - GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 *outX, - GHOST_TInt32 *outY); +extern void GHOST_ScreenToClient( + GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY); /** * Converts a point in screen coordinates to client rectangle coordinates @@ -638,11 +635,8 @@ extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, * \param outX: The x-coordinate on the screen. * \param outY: The y-coordinate on the screen. */ -extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle, - GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 *outX, - GHOST_TInt32 *outY); +extern void GHOST_ClientToScreen( + GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY); /** * Returns the state of the window (normal, minimized, maximized). @@ -667,7 +661,7 @@ extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, - GHOST_TUns8 isUnsavedChanges); + bool isUnsavedChanges); /** * Sets the order of the window (bottom, top). @@ -758,14 +752,14 @@ extern void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI * \param rectanglehandle: The handle to the rectangle. * \return width of the rectangle */ -extern GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle); +extern int32_t GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle); /** * Access to rectangle height. * \param rectanglehandle: The handle to the rectangle. * \return height of the rectangle */ -extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle); +extern int32_t GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle); /** * Gets all members of the rectangle. @@ -775,11 +769,8 @@ extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehand * \param r: Pointer to return right coordinate in. * \param b: Pointer to return bottom coordinate in. */ -extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 *l, - GHOST_TInt32 *t, - GHOST_TInt32 *r, - GHOST_TInt32 *b); +extern void GHOST_GetRectangle( + GHOST_RectangleHandle rectanglehandle, int32_t *l, int32_t *t, int32_t *r, int32_t *b); /** * Sets all members of the rectangle. @@ -789,11 +780,8 @@ extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, * \param r: requested right coordinate of the rectangle. * \param b: requested bottom coordinate of the rectangle. */ -extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 l, - GHOST_TInt32 t, - GHOST_TInt32 r, - GHOST_TInt32 b); +extern void GHOST_SetRectangle( + GHOST_RectangleHandle rectanglehandle, int32_t l, int32_t t, int32_t r, int32_t b); /** * Returns whether this rectangle is empty. @@ -818,7 +806,7 @@ extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehand * \param rectanglehandle: The handle to the rectangle. * \param i: The amount of offset given to each extreme (negative values shrink the rectangle). */ -extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 i); +extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, int32_t i); /** * Does a union of the rectangle given and this rectangle. @@ -835,9 +823,7 @@ extern void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle, * \param x: The x-coordinate of the point. * \param y: The y-coordinate of the point. */ -extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 x, - GHOST_TInt32 y); +extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, int32_t x, int32_t y); /** * Returns whether the point is inside this rectangle. @@ -848,8 +834,8 @@ extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, * \return Success value (true if point is inside). */ extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 x, - GHOST_TInt32 y); + int32_t x, + int32_t y); /** * Returns whether the rectangle is inside this rectangle. @@ -868,8 +854,8 @@ extern GHOST_TVisibility GHOST_GetRectangleVisibility( * \param cy: Requested center y-coordinate of the rectangle. */ extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 cx, - GHOST_TInt32 cy); + int32_t cx, + int32_t cy); /** * Sets rectangle members. @@ -881,11 +867,8 @@ extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, * \param w: requested width of the rectangle. * \param h: requested height of the rectangle. */ -extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 cx, - GHOST_TInt32 cy, - GHOST_TInt32 w, - GHOST_TInt32 h); +extern void GHOST_SetRectangleCenter( + GHOST_RectangleHandle rectanglehandle, int32_t cx, int32_t cy, int32_t w, int32_t h); /** * Clips a rectangle. @@ -903,14 +886,14 @@ extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle, * \param selection: Boolean to return the selection instead, X11 only feature. * \return clipboard data */ -extern GHOST_TUns8 *GHOST_getClipboard(int selection); +extern char *GHOST_getClipboard(bool selection); /** * Put data to the Clipboard * \param buffer: the string buffer to set. * \param selection: Set the selection instead, X11 only feature. */ -extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection); +extern void GHOST_putClipboard(const char *buffer, bool selection); /** * Toggles console @@ -942,7 +925,7 @@ extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle); /** * Returns the suggested DPI for this window. */ -extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle); +extern uint16_t GHOST_GetDPIHint(GHOST_WindowHandle windowhandle); /** * Enable IME attached to the given window, i.e. allows user-input @@ -956,12 +939,8 @@ extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle); * - true: Start a new composition. * - false: Move the IME windows to the given position without finishing it. */ -extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle, - GHOST_TInt32 x, - GHOST_TInt32 y, - GHOST_TInt32 w, - GHOST_TInt32 h, - int complete); +extern void GHOST_BeginIME( + GHOST_WindowHandle windowhandle, int32_t x, int32_t y, int32_t w, int32_t h, bool complete); /** * Disable the IME attached to the given window, i.e. prohibits any user-input * events from being dispatched to the IME. @@ -1076,7 +1055,7 @@ void GHOST_XrDestroyActionSet(GHOST_XrContextHandle xr_context, const char *acti */ int GHOST_XrCreateActions(GHOST_XrContextHandle xr_context, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionInfo *infos); /** @@ -1084,7 +1063,7 @@ int GHOST_XrCreateActions(GHOST_XrContextHandle xr_context, */ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const char *const *action_names); /** @@ -1092,7 +1071,7 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context, */ int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionSpaceInfo *infos); /** @@ -1100,7 +1079,7 @@ int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context, */ void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionSpaceInfo *infos); /** @@ -1108,7 +1087,7 @@ void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context, */ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionProfileInfo *infos); /** @@ -1116,7 +1095,7 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context, */ void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_context, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionProfileInfo *infos); /** @@ -1138,7 +1117,7 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_context, const char *action_set int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context, const char *action_set_name, const char *action_name, - const GHOST_TInt64 *duration, + const int64_t *duration, const float *frequency, const float *amplitude); diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h index c63064c123a..bcccd536ebd 100644 --- a/intern/ghost/GHOST_IEvent.h +++ b/intern/ghost/GHOST_IEvent.h @@ -58,7 +58,7 @@ class GHOST_IEvent { * Returns the time this event was generated. * \return The event generation time. */ - virtual GHOST_TUns64 getTime() = 0; + virtual uint64_t getTime() = 0; /** * Returns the window this event was generated on, diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 81b54cf5a0d..4c395f720df 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -177,7 +177,7 @@ class GHOST_ISystem { * Based on ANSI clock() routine. * \return The number of milliseconds. */ - virtual GHOST_TUns64 getMilliSeconds() const = 0; + virtual uint64_t getMilliSeconds() const = 0; /** * Installs a timer. @@ -189,8 +189,8 @@ class GHOST_ISystem { * \param userData: Placeholder for user data. * \return A timer task (0 if timer task installation failed). */ - virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, - GHOST_TUns64 interval, + virtual GHOST_ITimerTask *installTimer(uint64_t delay, + uint64_t interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = NULL) = 0; @@ -209,19 +209,19 @@ class GHOST_ISystem { * Returns the number of displays on this system. * \return The number of displays. */ - virtual GHOST_TUns8 getNumDisplays() const = 0; + virtual uint8_t getNumDisplays() const = 0; /** * Returns the dimensions of the main display on this system. * \return The dimension of the main display. */ - virtual void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const = 0; + virtual void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const = 0; /** * Returns the combine dimensions of all monitors. * \return The dimension of the workspace. */ - virtual void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const = 0; + virtual void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const = 0; /** * Create a new window. @@ -242,10 +242,10 @@ class GHOST_ISystem { * \return The new window (or 0 if creation failed). */ virtual GHOST_IWindow *createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -365,7 +365,7 @@ class GHOST_ISystem { * \param y: The y-coordinate of the cursor. * \return Indication of success. */ - virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const = 0; + virtual GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const = 0; /** * Updates the location of the cursor (location in screen coordinates). @@ -374,7 +374,7 @@ class GHOST_ISystem { * \param y: The y-coordinate of the cursor. * \return Indication of success. */ - virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) = 0; + virtual GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) = 0; /*************************************************************************************** * Access to mouse button and keyboard states. @@ -431,12 +431,12 @@ class GHOST_ISystem { * \return "unsigned char" from X11 XA_CUT_BUFFER0 buffer * */ - virtual GHOST_TUns8 *getClipboard(bool selection) const = 0; + virtual char *getClipboard(bool selection) const = 0; /** * Put data to the Clipboard */ - virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0; + virtual void putClipboard(const char *buffer, bool selection) const = 0; /*************************************************************************************** * System Message Box. diff --git a/intern/ghost/GHOST_ISystemPaths.h b/intern/ghost/GHOST_ISystemPaths.h index 74285b7e0ce..8298f4b78e2 100644 --- a/intern/ghost/GHOST_ISystemPaths.h +++ b/intern/ghost/GHOST_ISystemPaths.h @@ -68,26 +68,26 @@ class GHOST_ISystemPaths { * "unpack and run" path, then look for properly installed path, including versioning. * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ - virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0; + virtual const char *getSystemDir(int version, const char *versionstr) const = 0; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ - virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0; + virtual const char *getUserDir(int version, const char *versionstr) const = 0; /** * Determine a special ("well known") and easy to reach user directory. * \return Unsigned char string pointing to user dir (eg `~/Documents/`). */ - virtual const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const = 0; + virtual const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const = 0; /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ - virtual const GHOST_TUns8 *getBinaryDir() const = 0; + virtual const char *getBinaryDir() const = 0; /** * Add the file to the operating system most recently used files diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 1650b230812..f870791b345 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -108,20 +108,20 @@ class GHOST_IWindow { * Resizes client rectangle width. * \param width: The new width of the client area of the window. */ - virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0; + virtual GHOST_TSuccess setClientWidth(uint32_t width) = 0; /** * Resizes client rectangle height. * \param height: The new height of the client area of the window. */ - virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0; + virtual GHOST_TSuccess setClientHeight(uint32_t height) = 0; /** * Resizes client rectangle. * \param width: The new width of the client area of the window. * \param height: The new height of the client area of the window. */ - virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; + virtual GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) = 0; /** * Converts a point in screen coordinates to client rectangle coordinates @@ -130,10 +130,7 @@ class GHOST_IWindow { * \param outX: The x-coordinate in the client rectangle. * \param outY: The y-coordinate in the client rectangle. */ - virtual void screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const = 0; + virtual void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const = 0; /** * Converts a point in screen coordinates to client rectangle coordinates @@ -142,10 +139,7 @@ class GHOST_IWindow { * \param outX: The x-coordinate on the screen. * \param outY: The y-coordinate on the screen. */ - virtual void clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const = 0; + virtual void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const = 0; /** * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop @@ -290,8 +284,8 @@ class GHOST_IWindow { * \param hotY: The Y coordinate of the cursor hot-spot. * \return Indication of success. */ - virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + virtual GHOST_TSuccess setCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -319,7 +313,7 @@ class GHOST_IWindow { virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode /*mode*/, GHOST_TAxisFlag /*wrap_axis*/, GHOST_Rect * /*bounds*/, - GHOST_TInt32 /*mouse_ungrab_xy*/[2]) + int32_t /*mouse_ungrab_xy*/[2]) { return GHOST_kSuccess; } @@ -334,7 +328,7 @@ class GHOST_IWindow { * Returns the recommended DPI for this window. * \return The recommended DPI for this window. */ - virtual GHOST_TUns16 getDPIHint() = 0; + virtual uint16_t getDPIHint() = 0; #ifdef WITH_INPUT_IME /** @@ -348,8 +342,7 @@ class GHOST_IWindow { * - true: Start a new composition * - false: Move the IME windows to the given position without finishing it. */ - virtual void beginIME( - GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed) = 0; + virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) = 0; /** * Disable the IME attached to the given window, i.e. prohibits any user-input diff --git a/intern/ghost/GHOST_Path-api.h b/intern/ghost/GHOST_Path-api.h index 36ea70838ca..81df2e607eb 100644 --- a/intern/ghost/GHOST_Path-api.h +++ b/intern/ghost/GHOST_Path-api.h @@ -48,25 +48,25 @@ extern GHOST_TSuccess GHOST_DisposeSystemPaths(void); * "unpack and run" path, then look for properly installed path, including versioning. * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ -extern const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr); +extern const char *GHOST_getSystemDir(int version, const char *versionstr); /** * Determine the base dir in which user configuration is stored, including versioning. * \return Unsigned char string pointing to user dir (eg ~). */ -extern const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr); +extern const char *GHOST_getUserDir(int version, const char *versionstr); /** * Determine a special ("well known") and easy to reach user directory. * \return Unsigned char string pointing to user dir (eg `~/Documents/`). */ -extern const GHOST_TUns8 *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type); +extern const char *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type); /** * Determine the dir in which the binary file is found. * \return Unsigned char string pointing to binary dir (eg ~/usr/local/bin/). */ -extern const GHOST_TUns8 *GHOST_getBinaryDir(void); +extern const char *GHOST_getBinaryDir(void); /** * Add the file to the operating system most recently used files diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index dae2a2a8cbb..1c67ca3d2e0 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -42,7 +42,7 @@ class GHOST_Rect { * \param r: requested right coordinate of the rectangle. * \param b: requested bottom coordinate of the rectangle. */ - GHOST_Rect(GHOST_TInt32 l = 0, GHOST_TInt32 t = 0, GHOST_TInt32 r = 0, GHOST_TInt32 b = 0) + GHOST_Rect(int32_t l = 0, int32_t t = 0, int32_t r = 0, int32_t b = 0) : m_l(l), m_t(t), m_r(r), m_b(b) { } @@ -58,13 +58,13 @@ class GHOST_Rect { * Access to rectangle width. * \return width of the rectangle. */ - virtual inline GHOST_TInt32 getWidth() const; + virtual inline int32_t getWidth() const; /** * Access to rectangle height. * \return height of the rectangle. */ - virtual inline GHOST_TInt32 getHeight() const; + virtual inline int32_t getHeight() const; /** * Sets all members of the rectangle. @@ -73,7 +73,7 @@ class GHOST_Rect { * \param r: requested right coordinate of the rectangle. * \param b: requested bottom coordinate of the rectangle. */ - virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b); + virtual inline void set(int32_t l, int32_t t, int32_t r, int32_t b); /** * Returns whether this rectangle is empty. @@ -95,7 +95,7 @@ class GHOST_Rect { * The method avoids negative insets making the rectangle invalid * \param i: The amount of offset given to each extreme (negative values shrink the rectangle). */ - virtual void inset(GHOST_TInt32 i); + virtual void inset(int32_t i); /** * Does a union of the rectangle given and this rectangle. @@ -109,17 +109,14 @@ class GHOST_Rect { * \param x: The x-coordinate of the point. * \param y: The y-coordinate of the point. */ - virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y); + virtual inline void unionPoint(int32_t x, int32_t y); /** * Grows the rectangle to included a point. * \param x: The x-coordinate of the point. * \param y: The y-coordinate of the point. */ - virtual inline void wrapPoint(GHOST_TInt32 &x, - GHOST_TInt32 &y, - GHOST_TInt32 ofs, - GHOST_TAxisFlag axis); + virtual inline void wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAxisFlag axis); /** * Returns whether the point is inside this rectangle. @@ -128,7 +125,7 @@ class GHOST_Rect { * \param y: y-coordinate of point to test. * \return boolean value (true if point is inside). */ - virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const; + virtual inline bool isInside(int32_t x, int32_t y) const; /** * Returns whether the rectangle is inside this rectangle. @@ -143,7 +140,7 @@ class GHOST_Rect { * \param cx: requested center x-coordinate of the rectangle. * \param cy: requested center y-coordinate of the rectangle. */ - virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy); + virtual void setCenter(int32_t cx, int32_t cy); /** * Sets rectangle members. @@ -154,7 +151,7 @@ class GHOST_Rect { * \param w: requested width of the rectangle. * \param h: requested height of the rectangle. */ - virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h); + virtual void setCenter(int32_t cx, int32_t cy, int32_t w, int32_t h); /** * Clips a rectangle. @@ -166,30 +163,30 @@ class GHOST_Rect { virtual bool clip(GHOST_Rect &r) const; /** Left coordinate of the rectangle */ - GHOST_TInt32 m_l; + int32_t m_l; /** Top coordinate of the rectangle */ - GHOST_TInt32 m_t; + int32_t m_t; /** Right coordinate of the rectangle */ - GHOST_TInt32 m_r; + int32_t m_r; /** Bottom coordinate of the rectangle */ - GHOST_TInt32 m_b; + int32_t m_b; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_Rect") #endif }; -inline GHOST_TInt32 GHOST_Rect::getWidth() const +inline int32_t GHOST_Rect::getWidth() const { return m_r - m_l; } -inline GHOST_TInt32 GHOST_Rect::getHeight() const +inline int32_t GHOST_Rect::getHeight() const { return m_b - m_t; } -inline void GHOST_Rect::set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b) +inline void GHOST_Rect::set(int32_t l, int32_t t, int32_t r, int32_t b) { m_l = l; m_t = t; @@ -219,7 +216,7 @@ inline void GHOST_Rect::unionRect(const GHOST_Rect &r) m_b = r.m_b; } -inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y) +inline void GHOST_Rect::unionPoint(int32_t x, int32_t y) { if (x < m_l) m_l = x; @@ -231,13 +228,10 @@ inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y) m_b = y; } -inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x, - GHOST_TInt32 &y, - GHOST_TInt32 ofs, - GHOST_TAxisFlag axis) +inline void GHOST_Rect::wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAxisFlag axis) { - GHOST_TInt32 w = getWidth(); - GHOST_TInt32 h = getHeight(); + int32_t w = getWidth(); + int32_t h = getHeight(); /* highly unlikely but avoid eternal loop */ if (w - ofs * 2 <= 0 || h - ofs * 2 <= 0) { @@ -258,7 +252,7 @@ inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x, } } -inline bool GHOST_Rect::isInside(GHOST_TInt32 x, GHOST_TInt32 y) const +inline bool GHOST_Rect::isInside(int32_t x, int32_t y) const { return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b); } diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 7efbd00c2eb..ff93de4f203 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -23,6 +23,8 @@ #pragma once +#include <stdint.h> + #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" #endif @@ -56,13 +58,6 @@ GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle); GHOST_DECLARE_HANDLE(GHOST_ContextHandle); GHOST_DECLARE_HANDLE(GHOST_XrContextHandle); -typedef char GHOST_TInt8; -typedef unsigned char GHOST_TUns8; -typedef short GHOST_TInt16; -typedef unsigned short GHOST_TUns16; -typedef int GHOST_TInt32; -typedef unsigned int GHOST_TUns32; - typedef struct { int flags; } GHOST_GLSettings; @@ -78,14 +73,6 @@ typedef enum GHOST_DialogOptions { GHOST_DialogError = (1 << 1), } GHOST_DialogOptions; -#ifdef _MSC_VER -typedef __int64 GHOST_TInt64; -typedef unsigned __int64 GHOST_TUns64; -#else -typedef long long GHOST_TInt64; -typedef unsigned long long GHOST_TUns64; -#endif - typedef void *GHOST_TUserDataPtr; typedef enum { GHOST_kFailure = 0, GHOST_kSuccess } GHOST_TSuccess; @@ -436,9 +423,9 @@ typedef void *GHOST_TEventDataPtr; typedef struct { /** The x-coordinate of the cursor position. */ - GHOST_TInt32 x; + int32_t x; /** The y-coordinate of the cursor position. */ - GHOST_TInt32 y; + int32_t y; /** Associated tablet data. */ GHOST_TabletData tablet; } GHOST_TEventCursorData; @@ -452,7 +439,7 @@ typedef struct { typedef struct { /** Displacement of a mouse wheel. */ - GHOST_TInt32 z; + int32_t z; } GHOST_TEventWheelData; typedef enum { @@ -468,13 +455,13 @@ typedef struct { /** The event subtype */ GHOST_TTrackpadEventSubTypes subtype; /** The x-location of the trackpad event */ - GHOST_TInt32 x; + int32_t x; /** The y-location of the trackpad event */ - GHOST_TInt32 y; + int32_t y; /** The x-delta or value of the trackpad event */ - GHOST_TInt32 deltaX; + int32_t deltaX; /** The y-delta (currently only for scroll subtype) of the trackpad event */ - GHOST_TInt32 deltaY; + int32_t deltaY; /** The delta is inverted from the device due to system preferences. */ char isDirectionInverted; } GHOST_TEventTrackpadData; @@ -488,9 +475,9 @@ typedef enum { typedef struct { /** The x-coordinate of the cursor position. */ - GHOST_TInt32 x; + int32_t x; /** The y-coordinate of the cursor position. */ - GHOST_TInt32 y; + int32_t y; /** The dropped item type */ GHOST_TDragnDropTypes dataType; /** The "dropped content" */ @@ -515,7 +502,7 @@ typedef struct { typedef struct { int count; - GHOST_TUns8 **strings; + uint8_t **strings; } GHOST_TStringArray; typedef enum { @@ -587,13 +574,13 @@ typedef enum { typedef struct { /** Number of pixels on a line. */ - GHOST_TUns32 xPixels; + uint32_t xPixels; /** Number of lines. */ - GHOST_TUns32 yPixels; + uint32_t yPixels; /** Number of bits per pixel. */ - GHOST_TUns32 bpp; + uint32_t bpp; /** Refresh rate (in Hertz). */ - GHOST_TUns32 frequency; + uint32_t frequency; } GHOST_DisplaySetting; #ifdef _WIN32 @@ -613,10 +600,10 @@ typedef int GHOST_TEmbedderWindowID; */ #ifdef __cplusplus class GHOST_ITimerTask; -typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask *task, GHOST_TUns64 time); +typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask *task, uint64_t time); #else struct GHOST_TimerTaskHandle__; -typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_TUns64 time); +typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, uint64_t time); #endif #ifdef WITH_XR_OPENXR @@ -724,7 +711,7 @@ typedef enum GHOST_XrActionType { typedef struct GHOST_XrActionInfo { const char *name; GHOST_XrActionType type; - GHOST_TUns32 count_subaction_paths; + uint32_t count_subaction_paths; const char **subaction_paths; /** States for each subaction path. */ void *states; @@ -735,7 +722,7 @@ typedef struct GHOST_XrActionInfo { typedef struct GHOST_XrActionSpaceInfo { const char *action_name; - GHOST_TUns32 count_subaction_paths; + uint32_t count_subaction_paths; const char **subaction_paths; /** Poses for each subaction path. */ const GHOST_XrPose *poses; @@ -743,14 +730,14 @@ typedef struct GHOST_XrActionSpaceInfo { typedef struct GHOST_XrActionBindingInfo { const char *action_name; - GHOST_TUns32 count_interaction_paths; + uint32_t count_interaction_paths; /** Interaction path: User (sub-action) path + component path. */ const char **interaction_paths; } GHOST_XrActionBindingInfo; typedef struct GHOST_XrActionProfileInfo { const char *profile_path; - GHOST_TUns32 count_bindings; + uint32_t count_bindings; const GHOST_XrActionBindingInfo *bindings; } GHOST_XrActionProfileInfo; diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h index e77bab4f2ec..b216d9f2839 100644 --- a/intern/ghost/intern/GHOST_Buttons.h +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -57,7 +57,7 @@ struct GHOST_Buttons { */ void clear(); - GHOST_TUns8 m_ButtonLeft : 1; - GHOST_TUns8 m_ButtonMiddle : 1; - GHOST_TUns8 m_ButtonRight : 1; + uint8_t m_ButtonLeft : 1; + uint8_t m_ButtonMiddle : 1; + uint8_t m_ButtonRight : 1; }; diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 955f35274ea..cb409595e50 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -84,7 +84,7 @@ GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhand return GHOST_kSuccess; } -GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle) +uint64_t GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; @@ -92,8 +92,8 @@ GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle) } GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, - GHOST_TUns64 delay, - GHOST_TUns64 interval, + uint64_t delay, + uint64_t interval, GHOST_TimerProcPtr timerproc, GHOST_TUserDataPtr userdata) { @@ -111,7 +111,7 @@ GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, return system->removeTimer(timertask); } -GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle) +uint8_t GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; @@ -119,8 +119,8 @@ GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle) } void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, - GHOST_TUns32 *width, - GHOST_TUns32 *height) + uint32_t *width, + uint32_t *height) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; @@ -128,8 +128,8 @@ void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, } void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, - GHOST_TUns32 *width, - GHOST_TUns32 *height) + uint32_t *width, + uint32_t *height) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; @@ -156,10 +156,10 @@ GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle, GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle parent_windowhandle, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, bool is_dialog, GHOST_TDrawingContextType type, @@ -317,13 +317,13 @@ GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle, } GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle, - GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, int hotY, - GHOST_TUns8 canInvertColor) + bool canInvertColor) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; @@ -344,18 +344,14 @@ GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, int vi return window->setCursorVisibility(visible ? true : false); } -GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, - GHOST_TInt32 *x, - GHOST_TInt32 *y) +GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, int32_t *x, int32_t *y) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; return system->getCursorPosition(*x, *y); } -GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, - GHOST_TInt32 x, - GHOST_TInt32 y) +GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, int32_t x, int32_t y) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; @@ -370,7 +366,7 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; GHOST_Rect bounds_rect; - GHOST_TInt32 mouse_xy[2]; + int32_t mouse_xy[2]; if (bounds) { bounds_rect = GHOST_Rect(bounds[0], bounds[1], bounds[2], bounds[3]); @@ -420,7 +416,7 @@ void GHOST_setNDOFDeadZone(float deadzone) } #endif -void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept) +void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool canAccept) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; @@ -434,7 +430,7 @@ GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle) return event->getType(); } -GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle) +uint64_t GHOST_GetEventTime(GHOST_EventHandle eventhandle) { GHOST_IEvent *event = (GHOST_IEvent *)eventhandle; @@ -555,14 +551,14 @@ void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle) delete (GHOST_Rect *)rectanglehandle; } -GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOST_TUns32 width) +GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, uint32_t width) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; return window->setClientWidth(width); } -GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns32 height) +GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, uint32_t height) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; @@ -570,30 +566,24 @@ GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns } GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, - GHOST_TUns32 width, - GHOST_TUns32 height) + uint32_t width, + uint32_t height) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; return window->setClientSize(width, height); } -void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, - GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 *outX, - GHOST_TInt32 *outY) +void GHOST_ScreenToClient( + GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; window->screenToClient(inX, inY, *outX, *outY); } -void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle, - GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 *outX, - GHOST_TInt32 *outY) +void GHOST_ClientToScreen( + GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; @@ -614,8 +604,7 @@ GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, GHOST_TWind return window->setState(state); } -GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, - GHOST_TUns8 isUnsavedChanges) +GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, bool isUnsavedChanges) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; @@ -703,21 +692,18 @@ void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI api) system->setTabletAPI(api); } -GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle) +int32_t GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle) { return ((GHOST_Rect *)rectanglehandle)->getWidth(); } -GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle) +int32_t GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle) { return ((GHOST_Rect *)rectanglehandle)->getHeight(); } -void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 *l, - GHOST_TInt32 *t, - GHOST_TInt32 *r, - GHOST_TInt32 *b) +void GHOST_GetRectangle( + GHOST_RectangleHandle rectanglehandle, int32_t *l, int32_t *t, int32_t *r, int32_t *b) { GHOST_Rect *rect = (GHOST_Rect *)rectanglehandle; @@ -727,11 +713,8 @@ void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, *b = rect->m_b; } -void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 l, - GHOST_TInt32 t, - GHOST_TInt32 r, - GHOST_TInt32 b) +void GHOST_SetRectangle( + GHOST_RectangleHandle rectanglehandle, int32_t l, int32_t t, int32_t r, int32_t b) { ((GHOST_Rect *)rectanglehandle)->set(l, t, r, b); } @@ -756,7 +739,7 @@ GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle) return result; } -void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 i) +void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, int32_t i) { ((GHOST_Rect *)rectanglehandle)->inset(i); } @@ -767,16 +750,12 @@ void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle, ((GHOST_Rect *)rectanglehandle)->unionRect(*(GHOST_Rect *)anotherrectanglehandle); } -void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 x, - GHOST_TInt32 y) +void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, int32_t x, int32_t y) { ((GHOST_Rect *)rectanglehandle)->unionPoint(x, y); } -GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 x, - GHOST_TInt32 y) +GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, int32_t x, int32_t y) { GHOST_TSuccess result = GHOST_kFailure; @@ -796,18 +775,13 @@ GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectangleha return visible; } -void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 cx, - GHOST_TInt32 cy) +void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, int32_t cx, int32_t cy) { ((GHOST_Rect *)rectanglehandle)->setCenter(cx, cy); } -void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle, - GHOST_TInt32 cx, - GHOST_TInt32 cy, - GHOST_TInt32 w, - GHOST_TInt32 h) +void GHOST_SetRectangleCenter( + GHOST_RectangleHandle rectanglehandle, int32_t cx, int32_t cy, int32_t w, int32_t h) { ((GHOST_Rect *)rectanglehandle)->setCenter(cx, cy, w, h); } @@ -823,13 +797,13 @@ GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle, return result; } -GHOST_TUns8 *GHOST_getClipboard(int selection) +char *GHOST_getClipboard(bool selection) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); return system->getClipboard(selection); } -void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection) +void GHOST_putClipboard(const char *buffer, bool selection) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); system->putClipboard(buffer, selection); @@ -861,7 +835,7 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle) return 1.0f; } -GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle) +uint16_t GHOST_GetDPIHint(GHOST_WindowHandle windowhandle) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; return window->getDPIHint(); @@ -869,12 +843,8 @@ GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle) #ifdef WITH_INPUT_IME -void GHOST_BeginIME(GHOST_WindowHandle windowhandle, - GHOST_TInt32 x, - GHOST_TInt32 y, - GHOST_TInt32 w, - GHOST_TInt32 h, - int complete) +void GHOST_BeginIME( + GHOST_WindowHandle windowhandle, int32_t x, int32_t y, int32_t w, int32_t h, bool complete) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; window->beginIME(x, y, w, h, complete); @@ -972,7 +942,7 @@ void GHOST_XrDestroyActionSet(GHOST_XrContextHandle xr_contexthandle, const char int GHOST_XrCreateActions(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionInfo *infos) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; @@ -983,7 +953,7 @@ int GHOST_XrCreateActions(GHOST_XrContextHandle xr_contexthandle, void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const char *const *action_names) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; @@ -993,7 +963,7 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_contexthandle, int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionSpaceInfo *infos) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; @@ -1005,7 +975,7 @@ int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_contexthandle, void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionSpaceInfo *infos) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; @@ -1015,7 +985,7 @@ void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_contexthandle, int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionProfileInfo *infos) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; @@ -1027,7 +997,7 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - GHOST_TUns32 count, + uint32_t count, const GHOST_XrActionProfileInfo *infos) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; @@ -1054,7 +1024,7 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_contexthandle, const char *acti int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, const char *action_name, - const GHOST_TInt64 *duration, + const int64_t *duration, const float *frequency, const float *amplitude) { diff --git a/intern/ghost/intern/GHOST_DisplayManager.cpp b/intern/ghost/intern/GHOST_DisplayManager.cpp index d8321bb1732..fe12a76753d 100644 --- a/intern/ghost/intern/GHOST_DisplayManager.cpp +++ b/intern/ghost/intern/GHOST_DisplayManager.cpp @@ -49,20 +49,20 @@ GHOST_TSuccess GHOST_DisplayManager::initialize(void) return success; } -GHOST_TSuccess GHOST_DisplayManager::getNumDisplays(GHOST_TUns8 & /*numDisplays*/) const +GHOST_TSuccess GHOST_DisplayManager::getNumDisplays(uint8_t & /*numDisplays*/) const { // Don't know if we have a display... return GHOST_kFailure; } -GHOST_TSuccess GHOST_DisplayManager::getNumDisplaySettings(GHOST_TUns8 display, - GHOST_TInt32 &numSettings) const +GHOST_TSuccess GHOST_DisplayManager::getNumDisplaySettings(uint8_t display, + int32_t &numSettings) const { GHOST_TSuccess success; GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false"); - GHOST_TUns8 numDisplays; + uint8_t numDisplays; success = getNumDisplays(numDisplays); if (success == GHOST_kSuccess) { if (display < numDisplays) { @@ -75,18 +75,18 @@ GHOST_TSuccess GHOST_DisplayManager::getNumDisplaySettings(GHOST_TUns8 display, return success; } -GHOST_TSuccess GHOST_DisplayManager::getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, +GHOST_TSuccess GHOST_DisplayManager::getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const { GHOST_TSuccess success; GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false"); - GHOST_TUns8 numDisplays; + uint8_t numDisplays; success = getNumDisplays(numDisplays); if (success == GHOST_kSuccess) { - if (display < numDisplays && ((GHOST_TUns8)index < m_settings[display].size())) { + if (display < numDisplays && ((uint8_t)index < m_settings[display].size())) { setting = m_settings[display][index]; } else { @@ -97,18 +97,18 @@ GHOST_TSuccess GHOST_DisplayManager::getDisplaySetting(GHOST_TUns8 display, } GHOST_TSuccess GHOST_DisplayManager::getCurrentDisplaySetting( - GHOST_TUns8 /*display*/, GHOST_DisplaySetting & /*setting*/) const + uint8_t /*display*/, GHOST_DisplaySetting & /*setting*/) const { return GHOST_kFailure; } GHOST_TSuccess GHOST_DisplayManager::setCurrentDisplaySetting( - GHOST_TUns8 /*display*/, const GHOST_DisplaySetting & /*setting*/) + uint8_t /*display*/, const GHOST_DisplaySetting & /*setting*/) { return GHOST_kFailure; } -GHOST_TSuccess GHOST_DisplayManager::findMatch(GHOST_TUns8 display, +GHOST_TSuccess GHOST_DisplayManager::findMatch(uint8_t display, const GHOST_DisplaySetting &setting, GHOST_DisplaySetting &match) const { @@ -157,17 +157,16 @@ GHOST_TSuccess GHOST_DisplayManager::findMatch(GHOST_TUns8 display, GHOST_TSuccess GHOST_DisplayManager::initializeSettings(void) { - GHOST_TUns8 numDisplays; + uint8_t numDisplays; GHOST_TSuccess success = getNumDisplays(numDisplays); if (success == GHOST_kSuccess) { - for (GHOST_TUns8 display = 0; (display < numDisplays) && (success == GHOST_kSuccess); - display++) { + for (uint8_t display = 0; (display < numDisplays) && (success == GHOST_kSuccess); display++) { GHOST_DisplaySettings displaySettings; m_settings.push_back(displaySettings); - GHOST_TInt32 numSettings; + int32_t numSettings; success = getNumDisplaySettings(display, numSettings); if (success == GHOST_kSuccess) { - GHOST_TInt32 index; + int32_t index; GHOST_DisplaySetting setting; for (index = 0; (index < numSettings) && (success == GHOST_kSuccess); index++) { success = getDisplaySetting(display, index, setting); diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h index 26bc687a179..609dfa72dc6 100644 --- a/intern/ghost/intern/GHOST_DisplayManager.h +++ b/intern/ghost/intern/GHOST_DisplayManager.h @@ -55,7 +55,7 @@ class GHOST_DisplayManager { * \param numDisplays: The number of displays on this system. * \return Indication of success. */ - virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; + virtual GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const; /** * Returns the number of display settings for this display device. @@ -63,8 +63,7 @@ class GHOST_DisplayManager { * \param numSettings: The number of settings of the display device with this index. * \return Indication of success. */ - virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, - GHOST_TInt32 &numSettings) const; + virtual GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const; /** * Returns the current setting for this display device. @@ -73,8 +72,8 @@ class GHOST_DisplayManager { * \param setting: The setting of the display device with this index. * \return Indication of success. */ - virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, + virtual GHOST_TSuccess getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const; /** @@ -83,7 +82,7 @@ class GHOST_DisplayManager { * \param setting: The current setting of the display device with this index. * \return Indication of success. */ - virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, + virtual GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const; /** @@ -94,7 +93,7 @@ class GHOST_DisplayManager { * \param setting: The setting of the display device to be matched and activated. * \return Indication of success. */ - virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, + virtual GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting); protected: @@ -107,7 +106,7 @@ class GHOST_DisplayManager { * \param match: The optimal display setting. * \return Indication of success. */ - GHOST_TSuccess findMatch(GHOST_TUns8 display, + GHOST_TSuccess findMatch(uint8_t display, const GHOST_DisplaySetting &setting, GHOST_DisplaySetting &match) const; diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h index 745ad457796..cea124a601d 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h @@ -46,7 +46,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { * \param numDisplays: The number of displays on this system. * \return Indication of success. */ - GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; + GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const; /** * Returns the number of display settings for this display device. @@ -54,7 +54,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { * \param numSetting: The number of settings of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const; + GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const; /** * Returns the current setting for this display device. @@ -63,8 +63,8 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { * \param setting: The setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, + GHOST_TSuccess getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const; /** @@ -73,8 +73,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { * \param setting: The current setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, - GHOST_DisplaySetting &setting) const; + GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const; /** * Changes the current setting for this display device. @@ -82,8 +81,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { * \param setting: The current setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, - const GHOST_DisplaySetting &setting); + GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting); protected: // Do not cache values as OS X supports screen hot plug diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm index d899bb1c3c7..b983f5a9a4d 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm @@ -29,26 +29,26 @@ GHOST_DisplayManagerCocoa::GHOST_DisplayManagerCocoa(void) { } -GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(GHOST_TUns8 &numDisplays) const +GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(uint8_t &numDisplays) const { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - numDisplays = (GHOST_TUns8)[[NSScreen screens] count]; + numDisplays = (uint8_t)[[NSScreen screens] count]; [pool drain]; return GHOST_kSuccess; } -GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(GHOST_TUns8 display, - GHOST_TInt32 &numSettings) const +GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(uint8_t display, + int32_t &numSettings) const { - numSettings = (GHOST_TInt32)3; // Width, Height, BitsPerPixel + numSettings = (int32_t)3; // Width, Height, BitsPerPixel return GHOST_kSuccess; } -GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, +GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const { NSScreen *askedDisplay; @@ -86,7 +86,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display, } GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting( - GHOST_TUns8 display, GHOST_DisplaySetting &setting) const + uint8_t display, GHOST_DisplaySetting &setting) const { NSScreen *askedDisplay; @@ -127,7 +127,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting( } GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting( - GHOST_TUns8 display, const GHOST_DisplaySetting &setting) + uint8_t display, const GHOST_DisplaySetting &setting) { GHOST_ASSERT( (display == kMainDisplay), diff --git a/intern/ghost/intern/GHOST_DisplayManagerNULL.h b/intern/ghost/intern/GHOST_DisplayManagerNULL.h index 4ca06faec12..6b9e9a5a30e 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerNULL.h +++ b/intern/ghost/intern/GHOST_DisplayManagerNULL.h @@ -31,25 +31,25 @@ class GHOST_DisplayManagerNULL : public GHOST_DisplayManager { GHOST_DisplayManagerNULL(GHOST_SystemNULL *system) : GHOST_DisplayManager(), m_system(system) { /* nop */ } - GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const + GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const { return GHOST_kFailure; } - GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const + GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const { return GHOST_kFailure; } - GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, + GHOST_TSuccess getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const { return GHOST_kFailure; } - GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting &setting) const + GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const { - return getDisplaySetting(display, GHOST_TInt32(0), setting); + return getDisplaySetting(display, int32_t(0), setting); } - GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting &setting) + GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting) { return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp index 11134ad1054..18adf948e3b 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp @@ -33,14 +33,14 @@ GHOST_DisplayManagerSDL::GHOST_DisplayManagerSDL(GHOST_SystemSDL *system) memset(&m_mode, 0, sizeof(m_mode)); } -GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplays(GHOST_TUns8 &numDisplays) const +GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplays(uint8_t &numDisplays) const { numDisplays = SDL_GetNumVideoDisplays(); return GHOST_kSuccess; } -GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(GHOST_TUns8 display, - GHOST_TInt32 &numSettings) const +GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(uint8_t display, + int32_t &numSettings) const { GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); @@ -66,8 +66,8 @@ static void ghost_mode_to_sdl(const GHOST_DisplaySetting &setting, SDL_DisplayMo mode->refresh_rate = setting.frequency; } -GHOST_TSuccess GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, +GHOST_TSuccess GHOST_DisplayManagerSDL::getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const { GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); @@ -81,7 +81,7 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display, } GHOST_TSuccess GHOST_DisplayManagerSDL::getCurrentDisplaySetting( - GHOST_TUns8 display, GHOST_DisplaySetting &setting) const + uint8_t display, GHOST_DisplaySetting &setting) const { SDL_DisplayMode mode; SDL_GetCurrentDisplayMode(display, &mode); @@ -98,7 +98,7 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::getCurrentDisplayModeSDL(SDL_DisplayMode } GHOST_TSuccess GHOST_DisplayManagerSDL::setCurrentDisplaySetting( - GHOST_TUns8 display, const GHOST_DisplaySetting &setting) + uint8_t display, const GHOST_DisplaySetting &setting) { /* * Mode switching code ported from Quake 2 version 3.21 and bzflag version diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.h b/intern/ghost/intern/GHOST_DisplayManagerSDL.h index 9a79a842057..a719368275c 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerSDL.h +++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.h @@ -37,21 +37,19 @@ class GHOST_DisplayManagerSDL : public GHOST_DisplayManager { public: GHOST_DisplayManagerSDL(GHOST_SystemSDL *system); - GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; + GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const; - GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const; + GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const; - GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, + GHOST_TSuccess getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const; - GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, - GHOST_DisplaySetting &setting) const; + GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const; GHOST_TSuccess getCurrentDisplayModeSDL(SDL_DisplayMode &mode) const; - GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, - const GHOST_DisplaySetting &setting); + GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting); private: GHOST_SystemSDL *m_system; diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index 3557c4cd0c5..2895ddd68a9 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -35,7 +35,7 @@ GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void) { } -GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8 &numDisplays) const +GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(uint8_t &numDisplays) const { numDisplays = ::GetSystemMetrics(SM_CMONITORS); return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure; @@ -54,8 +54,8 @@ static BOOL get_dd(DWORD d, DISPLAY_DEVICE *dd) * the information that was cached the last time the function was called with iModeNum * set to zero. */ -GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display, - GHOST_TInt32 &numSettings) const +GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(uint8_t display, + int32_t &numSettings) const { DISPLAY_DEVICE display_device; if (!get_dd(display, &display_device)) @@ -69,8 +69,8 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 disp return GHOST_kSuccess; } -GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, +GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const { DISPLAY_DEVICE display_device; @@ -111,13 +111,13 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, } GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting( - GHOST_TUns8 display, GHOST_DisplaySetting &setting) const + uint8_t display, GHOST_DisplaySetting &setting) const { return getDisplaySetting(display, ENUM_CURRENT_SETTINGS, setting); } GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting( - GHOST_TUns8 display, const GHOST_DisplaySetting &setting) + uint8_t display, const GHOST_DisplaySetting &setting) { DISPLAY_DEVICE display_device; if (!get_dd(display, &display_device)) diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h index 2de866b04ec..31cde2fc63d 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h @@ -45,7 +45,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { * \param numDisplays: The number of displays on this system. * \return Indication of success. */ - GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; + GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const; /** * Returns the number of display settings for this display device. @@ -53,7 +53,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { * \param numSetting: The number of settings of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const; + GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const; /** * Returns the current setting for this display device. @@ -62,8 +62,8 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { * \param setting: The setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, + GHOST_TSuccess getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const; /** @@ -72,8 +72,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { * \param setting: The current setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, - GHOST_DisplaySetting &setting) const; + GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const; /** * Changes the current setting for this display device. @@ -81,8 +80,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { * \param setting: The current setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, - const GHOST_DisplaySetting &setting); + GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting); protected: }; diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp index f1acf74ca41..2ebdf8b3f2a 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp @@ -40,14 +40,14 @@ GHOST_DisplayManagerX11::GHOST_DisplayManagerX11(GHOST_SystemX11 *system) /* nothing to do. */ } -GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplays(GHOST_TUns8 &numDisplays) const +GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplays(uint8_t &numDisplays) const { numDisplays = m_system->getNumDisplays(); return GHOST_kSuccess; } -GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplaySettings(GHOST_TUns8 display, - GHOST_TInt32 &numSettings) const +GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplaySettings(uint8_t display, + int32_t &numSettings) const { #ifdef WITH_X11_XF86VMODE int majorVersion, minorVersion; @@ -88,8 +88,8 @@ static int calculate_rate(XF86VidModeModeInfo *info) } #endif -GHOST_TSuccess GHOST_DisplayManagerX11::getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, +GHOST_TSuccess GHOST_DisplayManagerX11::getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const { Display *dpy = m_system->getXDisplay(); @@ -140,7 +140,7 @@ GHOST_TSuccess GHOST_DisplayManagerX11::getDisplaySetting(GHOST_TUns8 display, } GHOST_TSuccess GHOST_DisplayManagerX11::getCurrentDisplaySetting( - GHOST_TUns8 display, GHOST_DisplaySetting &setting) const + uint8_t display, GHOST_DisplaySetting &setting) const { /* According to the xf86vidmodegetallmodelines man page, * "The first element of the array corresponds to the current video mode." @@ -149,7 +149,7 @@ GHOST_TSuccess GHOST_DisplayManagerX11::getCurrentDisplaySetting( } GHOST_TSuccess GHOST_DisplayManagerX11::setCurrentDisplaySetting( - GHOST_TUns8 /*display*/, const GHOST_DisplaySetting &setting) + uint8_t /*display*/, const GHOST_DisplaySetting &setting) { #ifdef WITH_X11_XF86VMODE /* Mode switching code ported from SDL: diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h index e0fc1cc1210..52702a397d7 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.h +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h @@ -43,7 +43,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { * \param numDisplays: The number of displays on this system. * \return Indication of success. */ - GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const; + GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const; /** * Returns the number of display settings for this display device. @@ -51,7 +51,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { * \param numSetting: The number of settings of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const; + GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const; /** * Returns the current setting for this display device. @@ -60,8 +60,8 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { * \param setting: The setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, - GHOST_TInt32 index, + GHOST_TSuccess getDisplaySetting(uint8_t display, + int32_t index, GHOST_DisplaySetting &setting) const; /** @@ -70,8 +70,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { * \param setting: The current setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, - GHOST_DisplaySetting &setting) const; + GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const; /** * Changes the current setting for this display device. @@ -79,8 +78,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { * \param setting: The current setting of the display device with this index. * \return Indication of success. */ - GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, - const GHOST_DisplaySetting &setting); + GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting); private: GHOST_SystemX11 *m_system; diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index ab4b48da9b4..c51bd58898b 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -242,7 +242,7 @@ void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *pDataObject) strArray = (GHOST_TStringArray *)::malloc(sizeof(GHOST_TStringArray)); strArray->count = 0; - strArray->strings = (GHOST_TUns8 **)::malloc(totfiles * sizeof(GHOST_TUns8 *)); + strArray->strings = (uint8_t **)::malloc(totfiles * sizeof(uint8_t *)); for (UINT nfile = 0; nfile < totfiles; nfile++) { if (::DragQueryFileW(hdrop, nfile, fpath, MAX_PATH) > 0) { @@ -251,7 +251,7 @@ void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *pDataObject) } // Just ignore paths that could not be converted verbatim. - strArray->strings[nvalid] = (GHOST_TUns8 *)temp_path; + strArray->strings[nvalid] = (uint8_t *)temp_path; strArray->count = nvalid + 1; nvalid++; } diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp index a62db31c952..8758a27930e 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.cpp +++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp @@ -216,7 +216,7 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr strArray = (GHOST_TStringArray *)malloc(sizeof(GHOST_TStringArray)); strArray->count = 0; - strArray->strings = (GHOST_TUns8 **)malloc(totPaths * sizeof(GHOST_TUns8 *)); + strArray->strings = (uint8_t **)malloc(totPaths * sizeof(uint8_t *)); curLength = 0; for (int i = 0; i <= dropBufferSize; i++) { @@ -230,7 +230,7 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr decodedPath = FileUrlDecode(curPath); if (decodedPath) { - strArray->strings[strArray->count] = (GHOST_TUns8 *)decodedPath; + strArray->strings[strArray->count] = (uint8_t *)decodedPath; strArray->count++; } diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h index 5016ca0e117..0194afd559c 100644 --- a/intern/ghost/intern/GHOST_Event.h +++ b/intern/ghost/intern/GHOST_Event.h @@ -37,7 +37,7 @@ class GHOST_Event : public GHOST_IEvent { * \param type: The type of this event. * \param window: The generating window (or NULL if system event). */ - GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window) + GHOST_Event(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window) : m_type(type), m_time(msec), m_window(window), m_data(NULL) { } @@ -55,7 +55,7 @@ class GHOST_Event : public GHOST_IEvent { * Returns the time this event was generated. * \return The event generation time. */ - GHOST_TUns64 getTime() + uint64_t getTime() { return m_time; } @@ -83,7 +83,7 @@ class GHOST_Event : public GHOST_IEvent { /** Type of this event. */ GHOST_TEventType m_type; /** The time this event was generated. */ - GHOST_TUns64 m_time; + uint64_t m_time; /** Pointer to the generating window. */ GHOST_IWindow *m_window; /** Pointer to the event data. */ diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h index 02804efdcba..02563254a82 100644 --- a/intern/ghost/intern/GHOST_EventButton.h +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -40,7 +40,7 @@ class GHOST_EventButton : public GHOST_Event { * \param button: The state of the buttons were at the time of the event. * \param tablet: The tablet data associated with this event. */ - GHOST_EventButton(GHOST_TUns64 time, + GHOST_EventButton(uint64_t time, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask button, diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h index d83ff6af6ce..facbab0855d 100644 --- a/intern/ghost/intern/GHOST_EventCursor.h +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -39,11 +39,11 @@ class GHOST_EventCursor : public GHOST_Event { * \param y: The y-coordinate of the location the cursor was at the time of the event. * \param tablet: The tablet data associated with this event. */ - GHOST_EventCursor(GHOST_TUns64 msec, + GHOST_EventCursor(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, - GHOST_TInt32 x, - GHOST_TInt32 y, + int32_t x, + int32_t y, const GHOST_TabletData &tablet) : GHOST_Event(msec, type, window), m_cursorEventData({x, y, tablet}) { diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h index a86b8302bf5..537717b1717 100644 --- a/intern/ghost/intern/GHOST_EventDragnDrop.h +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -72,7 +72,7 @@ class GHOST_EventDragnDrop : public GHOST_Event { * \param y: The y-coordinate of the location the cursor was at the time of the event. * \param data: The "content" dropped in the window. */ - GHOST_EventDragnDrop(GHOST_TUns64 time, + GHOST_EventDragnDrop(uint64_t time, GHOST_TEventType type, GHOST_TDragnDropTypes dataType, GHOST_IWindow *window, diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h index 1e6a3284a51..93e6f0380da 100644 --- a/intern/ghost/intern/GHOST_EventKey.h +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -39,11 +39,8 @@ class GHOST_EventKey : public GHOST_Event { * \param type: The type of key event. * \param key: The key code of the key. */ - GHOST_EventKey(GHOST_TUns64 msec, - GHOST_TEventType type, - GHOST_IWindow *window, - GHOST_TKey key, - bool is_repeat) + GHOST_EventKey( + uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TKey key, bool is_repeat) : GHOST_Event(msec, type, window) { m_keyEventData.key = key; @@ -60,7 +57,7 @@ class GHOST_EventKey : public GHOST_Event { * \param key: The key code of the key. * \param ascii: The ascii code for the key event. */ - GHOST_EventKey(GHOST_TUns64 msec, + GHOST_EventKey(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TKey key, diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index f16d90899b9..15befb9afcb 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -28,7 +28,6 @@ #include "GHOST_EventManager.h" #include "GHOST_Debug.h" #include <algorithm> -#include <stdio.h> // [mce] temp debug GHOST_EventManager::GHOST_EventManager() { @@ -46,14 +45,14 @@ GHOST_EventManager::~GHOST_EventManager() } } -GHOST_TUns32 GHOST_EventManager::getNumEvents() +uint32_t GHOST_EventManager::getNumEvents() { - return (GHOST_TUns32)m_events.size(); + return (uint32_t)m_events.size(); } -GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type) +uint32_t GHOST_EventManager::getNumEvents(GHOST_TEventType type) { - GHOST_TUns32 numEvents = 0; + uint32_t numEvents = 0; TEventStack::iterator p; for (p = m_events.begin(); p != m_events.end(); ++p) { if ((*p)->getType() == type) { diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index a372eb96a99..ba936e449f5 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -53,14 +53,14 @@ class GHOST_EventManager { * Returns the number of events currently on the stack. * \return The number of events on the stack. */ - GHOST_TUns32 getNumEvents(); + uint32_t getNumEvents(); /** * Returns the number of events of a certain type currently on the stack. * \param type: The type of events to be counted. * \return The number of events on the stack of this type. */ - GHOST_TUns32 getNumEvents(GHOST_TEventType type); + uint32_t getNumEvents(GHOST_TEventType type); /** * Pushes an event on the stack. diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index 64e67434b74..10f39f4be66 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -31,7 +31,7 @@ class GHOST_EventNDOFMotion : public GHOST_Event { GHOST_TEventNDOFMotionData m_axisData; public: - GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow *window) + GHOST_EventNDOFMotion(uint64_t time, GHOST_IWindow *window) : GHOST_Event(time, GHOST_kEventNDOFMotion, window) { m_data = &m_axisData; @@ -43,7 +43,7 @@ class GHOST_EventNDOFButton : public GHOST_Event { GHOST_TEventNDOFButtonData m_buttonData; public: - GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_IWindow *window) + GHOST_EventNDOFButton(uint64_t time, GHOST_IWindow *window) : GHOST_Event(time, GHOST_kEventNDOFButton, window) { m_data = &m_buttonData; diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp index fb34b1d3b1a..48043fa709b 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.cpp +++ b/intern/ghost/intern/GHOST_EventPrinter.cpp @@ -39,7 +39,7 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event) if (event->getType() == GHOST_kEventWindowUpdate) return false; - std::cout << "GHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() + std::cout << "GHOST_EventPrinter::processEvent, time: " << (int32_t)event->getTime() << ", type: "; switch (event->getType()) { case GHOST_kEventUnknown: diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h index 6dd2ffb2e86..a457c2e058a 100644 --- a/intern/ghost/intern/GHOST_EventString.h +++ b/intern/ghost/intern/GHOST_EventString.h @@ -38,7 +38,7 @@ class GHOST_EventString : public GHOST_Event { * \param window: The generating window (or NULL if system event). * \param data_ptr: Pointer to the (un-formatted) data associated with the event. */ - GHOST_EventString(GHOST_TUns64 msec, + GHOST_EventString(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TEventDataPtr data_ptr) diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h index d4f9d0f2b55..58420f6d713 100644 --- a/intern/ghost/intern/GHOST_EventTrackpad.h +++ b/intern/ghost/intern/GHOST_EventTrackpad.h @@ -39,13 +39,13 @@ class GHOST_EventTrackpad : public GHOST_Event { * \param x: The x-delta of the pan event. * \param y: The y-delta of the pan event. */ - GHOST_EventTrackpad(GHOST_TUns64 msec, + GHOST_EventTrackpad(uint64_t msec, GHOST_IWindow *window, GHOST_TTrackpadEventSubTypes subtype, - GHOST_TInt32 x, - GHOST_TInt32 y, - GHOST_TInt32 deltaX, - GHOST_TInt32 deltaY, + int32_t x, + int32_t y, + int32_t deltaX, + int32_t deltaY, bool isDirectionInverted) : GHOST_Event(msec, GHOST_kEventTrackpad, window) { diff --git a/intern/ghost/intern/GHOST_EventWheel.h b/intern/ghost/intern/GHOST_EventWheel.h index ea62e02d08d..666b3c7aba6 100644 --- a/intern/ghost/intern/GHOST_EventWheel.h +++ b/intern/ghost/intern/GHOST_EventWheel.h @@ -39,7 +39,7 @@ class GHOST_EventWheel : public GHOST_Event { * \param window: The window of this event. * \param z: The displacement of the mouse wheel. */ - GHOST_EventWheel(GHOST_TUns64 msec, GHOST_IWindow *window, GHOST_TInt32 z) + GHOST_EventWheel(uint64_t msec, GHOST_IWindow *window, int32_t z) : GHOST_Event(msec, GHOST_kEventWheel, window) { m_wheelEventData.z = z; diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index 0c851e067e8..4af988aef6e 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -44,7 +44,7 @@ class GHOST_EventIME : public GHOST_Event { * \param type: The type of key event. * \param key: The key code of the key. */ - GHOST_EventIME(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata) + GHOST_EventIME(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata) : GHOST_Event(msec, type, window) { this->m_data = customdata; diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h index e94ccef08c0..f951cae3a41 100644 --- a/intern/ghost/intern/GHOST_ModifierKeys.h +++ b/intern/ghost/intern/GHOST_ModifierKeys.h @@ -72,17 +72,17 @@ struct GHOST_ModifierKeys { bool equals(const GHOST_ModifierKeys &keys) const; /** Bitfield that stores the appropriate key state. */ - GHOST_TUns8 m_LeftShift : 1; + uint8_t m_LeftShift : 1; /** Bitfield that stores the appropriate key state. */ - GHOST_TUns8 m_RightShift : 1; + uint8_t m_RightShift : 1; /** Bitfield that stores the appropriate key state. */ - GHOST_TUns8 m_LeftAlt : 1; + uint8_t m_LeftAlt : 1; /** Bitfield that stores the appropriate key state. */ - GHOST_TUns8 m_RightAlt : 1; + uint8_t m_RightAlt : 1; /** Bitfield that stores the appropriate key state. */ - GHOST_TUns8 m_LeftControl : 1; + uint8_t m_LeftControl : 1; /** Bitfield that stores the appropriate key state. */ - GHOST_TUns8 m_RightControl : 1; + uint8_t m_RightControl : 1; /** Bitfield that stores the appropriate key state. */ - GHOST_TUns8 m_OS : 1; + uint8_t m_OS : 1; }; diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index dda78c0ac5b..079ad67f737 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -279,14 +279,14 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ return m_deviceType != NDOF_UnknownDevice; } -void GHOST_NDOFManager::updateTranslation(const int t[3], GHOST_TUns64 time) +void GHOST_NDOFManager::updateTranslation(const int t[3], uint64_t time) { memcpy(m_translation, t, sizeof(m_translation)); m_motionTime = time; m_motionEventPending = true; } -void GHOST_NDOFManager::updateRotation(const int r[3], GHOST_TUns64 time) +void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time) { memcpy(m_rotation, r, sizeof(m_rotation)); m_motionTime = time; @@ -295,7 +295,7 @@ void GHOST_NDOFManager::updateRotation(const int r[3], GHOST_TUns64 time) void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, - GHOST_TUns64 time, + uint64_t time, GHOST_IWindow *window) { GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_LAST, @@ -316,7 +316,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, bool press, - GHOST_TUns64 time, + uint64_t time, GHOST_IWindow *window) { GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; @@ -329,7 +329,7 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, m_system.pushEvent(event); } -void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time) +void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time) { GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); @@ -371,7 +371,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 } } -void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) +void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time) { button_bits &= m_buttonMask; // discard any "garbage" bits diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index d0b49bc13c2..7be129c327c 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -130,13 +130,13 @@ class GHOST_NDOFManager { // rotations are + when CCW, - when CW // each platform is responsible for getting axis data into this form // these values should not be scaled (just shuffled or flipped) - void updateTranslation(const int t[3], GHOST_TUns64 time); - void updateRotation(const int r[3], GHOST_TUns64 time); + void updateTranslation(const int t[3], uint64_t time); + void updateRotation(const int r[3], uint64_t time); // the latest raw button data from the device // use HID button encoding (not NDOF_ButtonT) - void updateButton(int button_number, bool press, GHOST_TUns64 time); - void updateButtons(int button_bits, GHOST_TUns64 time); + void updateButton(int button_number, bool press, uint64_t time); + void updateButtons(int button_bits, uint64_t time); // NDOFButton events are sent immediately // processes and sends most recent raw data as an NDOFMotion event @@ -147,8 +147,8 @@ class GHOST_NDOFManager { GHOST_System &m_system; private: - void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow *); - void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow *); + void sendButtonEvent(NDOF_ButtonT, bool press, uint64_t time, GHOST_IWindow *); + void sendKeyEvent(GHOST_TKey, bool press, uint64_t time, GHOST_IWindow *); NDOF_DeviceT m_deviceType; int m_buttonCount; @@ -159,8 +159,8 @@ class GHOST_NDOFManager { int m_rotation[3]; int m_buttons; // bit field - GHOST_TUns64 m_motionTime; // in milliseconds - GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent + uint64_t m_motionTime; // in milliseconds + uint64_t m_prevMotionTime; // time of most recent Motion event sent GHOST_TProgress m_motionState; bool m_motionEventPending; diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 5274b2d1ba9..63a38fd9297 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -195,7 +195,7 @@ static void DeviceEvent(uint32_t unused, uint32_t msg_type, void *msg_arg) // device state is broadcast to all clients; only react if sent to us if (s->client == clientID) { // TODO: is s->time compatible with GHOST timestamps? if so use that instead. - GHOST_TUns64 now = ghost_system->getMilliSeconds(); + uint64_t now = ghost_system->getMilliSeconds(); switch (s->command) { case kConnexionCmdHandleAxis: { diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp index 8ed0af1fc29..983bb38307e 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp @@ -97,7 +97,7 @@ bool GHOST_NDOFManagerUnix::processEvents() switch (e.type) { case SPNAV_EVENT_MOTION: { /* convert to blender view coords */ - GHOST_TUns64 now = m_system.getMilliSeconds(); + uint64_t now = m_system.getMilliSeconds(); const int t[3] = {(int)e.motion.x, (int)e.motion.y, (int)-e.motion.z}; const int r[3] = {(int)-e.motion.rx, (int)-e.motion.ry, (int)e.motion.rz}; @@ -109,7 +109,7 @@ bool GHOST_NDOFManagerUnix::processEvents() break; } case SPNAV_EVENT_BUTTON: - GHOST_TUns64 now = m_system.getMilliSeconds(); + uint64_t now = m_system.getMilliSeconds(); updateButton(e.button.bnum, e.button.press, now); break; } @@ -118,7 +118,7 @@ bool GHOST_NDOFManagerUnix::processEvents() #ifdef USE_FINISH_GLITCH_WORKAROUND if (motion_test_prev == true && motion_test == false) { - GHOST_TUns64 now = m_system.getMilliSeconds(); + uint64_t now = m_system.getMilliSeconds(); const int v[3] = {0, 0, 0}; updateTranslation(v, now); diff --git a/intern/ghost/intern/GHOST_Path-api.cpp b/intern/ghost/intern/GHOST_Path-api.cpp index c82e9819f3c..4f4d1d5a1c8 100644 --- a/intern/ghost/intern/GHOST_Path-api.cpp +++ b/intern/ghost/intern/GHOST_Path-api.cpp @@ -38,25 +38,25 @@ GHOST_TSuccess GHOST_DisposeSystemPaths(void) return GHOST_ISystemPaths::dispose(); } -const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr) +const char *GHOST_getSystemDir(int version, const char *versionstr) { GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get(); return systemPaths ? systemPaths->getSystemDir(version, versionstr) : NULL; } -const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr) +const char *GHOST_getUserDir(int version, const char *versionstr) { GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get(); return systemPaths ? systemPaths->getUserDir(version, versionstr) : NULL; /* shouldn't be NULL */ } -const GHOST_TUns8 *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type) +const char *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type) { GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get(); return systemPaths ? systemPaths->getUserSpecialDir(type) : NULL; /* shouldn't be NULL */ } -const GHOST_TUns8 *GHOST_getBinaryDir() +const char *GHOST_getBinaryDir() { GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get(); return systemPaths ? systemPaths->getBinaryDir() : NULL; /* shouldn't be NULL */ diff --git a/intern/ghost/intern/GHOST_Rect.cpp b/intern/ghost/intern/GHOST_Rect.cpp index c5b9bc44468..8ef9486f35a 100644 --- a/intern/ghost/intern/GHOST_Rect.cpp +++ b/intern/ghost/intern/GHOST_Rect.cpp @@ -23,7 +23,7 @@ #include "GHOST_Rect.h" -void GHOST_Rect::inset(GHOST_TInt32 i) +void GHOST_Rect::inset(int32_t i) { if (i > 0) { // Grow the rectangle @@ -34,7 +34,7 @@ void GHOST_Rect::inset(GHOST_TInt32 i) } else if (i < 0) { // Shrink the rectangle, check for insets larger than half the size - GHOST_TInt32 i2 = i * 2; + int32_t i2 = i * 2; if (getWidth() > i2) { m_l += i; m_r -= i; @@ -82,9 +82,9 @@ GHOST_TVisibility GHOST_Rect::getVisibility(GHOST_Rect &r) const return v; } -void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy) +void GHOST_Rect::setCenter(int32_t cx, int32_t cy) { - GHOST_TInt32 offset = cx - (m_l + (m_r - m_l) / 2); + int32_t offset = cx - (m_l + (m_r - m_l) / 2); m_l += offset; m_r += offset; offset = cy - (m_t + (m_b - m_t) / 2); @@ -92,7 +92,7 @@ void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy) m_b += offset; } -void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h) +void GHOST_Rect::setCenter(int32_t cx, int32_t cy, int32_t w, int32_t h) { long w_2, h_2; diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 46c50045b80..f6659cf50dc 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -56,19 +56,19 @@ GHOST_System::~GHOST_System() exit(); } -GHOST_TUns64 GHOST_System::getMilliSeconds() const +uint64_t GHOST_System::getMilliSeconds() const { return std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::steady_clock::now().time_since_epoch()) .count(); } -GHOST_ITimerTask *GHOST_System::installTimer(GHOST_TUns64 delay, - GHOST_TUns64 interval, +GHOST_ITimerTask *GHOST_System::installTimer(uint64_t delay, + uint64_t interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData) { - GHOST_TUns64 millis = getMilliSeconds(); + uint64_t millis = getMilliSeconds(); GHOST_TimerTask *timer = new GHOST_TimerTask(millis + delay, interval, timerProc, userData); if (timer) { if (m_timerManager->addTimer(timer) == GHOST_kSuccess) { diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 87ba0ae9c8c..9164687c5b5 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -75,7 +75,7 @@ class GHOST_System : public GHOST_ISystem { * Based on ANSI clock() routine. * \return The number of milliseconds. */ - virtual GHOST_TUns64 getMilliSeconds() const; + virtual uint64_t getMilliSeconds() const; /** * Installs a timer. @@ -89,8 +89,8 @@ class GHOST_System : public GHOST_ISystem { * \param userData: Placeholder for user data. * \return A timer task (0 if timer task installation failed). */ - GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, - GHOST_TUns64 interval, + GHOST_ITimerTask *installTimer(uint64_t delay, + uint64_t interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = NULL); @@ -210,8 +210,8 @@ class GHOST_System : public GHOST_ISystem { /** * Inherited from GHOST_ISystem but left pure virtual * <pre> - * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; - * GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) + * GHOST_TSuccess getCursorPosition(int32_t& x, int32_t& y) const = 0; + * GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) * </pre> */ @@ -308,14 +308,14 @@ class GHOST_System : public GHOST_ISystem { * \return Returns the clipboard data * */ - virtual GHOST_TUns8 *getClipboard(bool selection) const = 0; + virtual char *getClipboard(bool selection) const = 0; /** * Put data to the Clipboard * \param buffer: The buffer to copy to the clipboard. * \param selection: The clipboard to copy too only used on X11. */ - virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0; + virtual void putClipboard(const char *buffer, bool selection) const = 0; /** * Show a system message box diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index cee6398b5a6..48a64b155fc 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -59,7 +59,7 @@ class GHOST_SystemCocoa : public GHOST_System { * Based on ANSI clock() routine. * \return The number of milliseconds. */ - GHOST_TUns64 getMilliSeconds() const; + uint64_t getMilliSeconds() const; /*************************************************************************************** * Display/window management functionality @@ -69,18 +69,18 @@ class GHOST_SystemCocoa : public GHOST_System { * Returns the number of displays on this system. * \return The number of displays. */ - GHOST_TUns8 getNumDisplays() const; + uint8_t getNumDisplays() const; /** * Returns the dimensions of the main display on this system. * \return The dimension of the main display. */ - void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const; /** Returns the combine dimensions of all monitors. * \return The dimension of the workspace. */ - void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const; /** * Create a new window. @@ -100,10 +100,10 @@ class GHOST_SystemCocoa : public GHOST_System { * \return The new window (or 0 if creation failed). */ GHOST_IWindow *createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -137,7 +137,7 @@ class GHOST_SystemCocoa : public GHOST_System { bool processEvents(bool waitForEvent); /** - * Handle User request to quit, from Menu bar Quit, and Cmd+Q + * Handle User request to quit, from Menu bar Quit, and Command+Q * Display alert panel if changes performed since last save */ void handleQuitRequest(); @@ -175,7 +175,7 @@ class GHOST_SystemCocoa : public GHOST_System { * \param y: The y-coordinate of the cursor. * \return Indication of success. */ - GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const; + GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const; /** * Updates the location of the cursor (location in screen coordinates). @@ -183,7 +183,7 @@ class GHOST_SystemCocoa : public GHOST_System { * \param y: The y-coordinate of the cursor. * \return Indication of success. */ - GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + GHOST_TSuccess setCursorPosition(int32_t x, int32_t y); /*************************************************************************************** * Access to mouse button and keyboard states. @@ -208,14 +208,14 @@ class GHOST_SystemCocoa : public GHOST_System { * \param selection: Indicate which buffer to return. * \return Returns the selected buffer */ - GHOST_TUns8 *getClipboard(bool selection) const; + char *getClipboard(bool selection) const; /** * Puts buffer to system clipboard * \param buffer: The buffer to be copied. * \param selection: Indicates which buffer to copy too, only used on X11. */ - void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + void putClipboard(const char *buffer, bool selection) const; /** * Handles a window event. Called by GHOST_WindowCocoa window delegate @@ -288,10 +288,10 @@ class GHOST_SystemCocoa : public GHOST_System { * \param y: The y-coordinate of the cursor. * \return Indication of success. */ - GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + GHOST_TSuccess setMouseCursorPosition(int32_t x, int32_t y); /** Start time at initialization. */ - GHOST_TUns64 m_start_time; + uint64_t m_start_time; /** Event has been processed directly by Cocoa (or NDOF manager) * and has sent a ghost event to be dispatched */ @@ -302,14 +302,14 @@ class GHOST_SystemCocoa : public GHOST_System { bool m_needDelayedApplicationBecomeActiveEventProcessing; /** State of the modifiers. */ - GHOST_TUns32 m_modifierMask; + uint32_t m_modifierMask; /** Ignores window size messages (when window is dragged). */ bool m_ignoreWindowSizedMessages; /** Temporarily ignore momentum scroll events */ bool m_ignoreMomentumScroll; - /** Is the scroll wheel event generated by a multitouch trackpad or mouse? */ + /** Is the scroll wheel event generated by a multi-touch track-pad or mouse? */ bool m_multiTouchScroll; /** To prevent multiple warp, we store the time of the last warp event * and ignore mouse moved events generated before that. */ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 97c5652f112..0f10d5815f4 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -520,7 +520,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() sysctl(mib, 2, &boottime, &len, NULL, 0); m_start_time = ((boottime.tv_sec * 1000) + (boottime.tv_usec / 1000)); - // Detect multitouch trackpad + /* Detect multi-touch track-pad. */ mib[0] = CTL_HW; mib[1] = HW_MODEL; sysctl(mib, 2, NULL, &len, NULL, 0); @@ -655,7 +655,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init() #pragma mark window management -GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const +uint64_t GHOST_SystemCocoa::getMilliSeconds() const { // Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime]) struct timeval currentTime; @@ -667,7 +667,7 @@ GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const return ((currentTime.tv_sec * 1000) + (currentTime.tv_usec / 1000) - m_start_time); } -GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const +uint8_t GHOST_SystemCocoa::getNumDisplays() const { // Note that OS X supports monitor hot plug // We do not support multiple monitors at the moment @@ -676,7 +676,7 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const } } -void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemCocoa::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { @autoreleasepool { // Get visible frame, that is frame excluding dock and top menu bar @@ -693,17 +693,17 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns } } -void GHOST_SystemCocoa::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemCocoa::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const { /* TODO! */ getMainDisplayDimensions(width, height); } GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -721,7 +721,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable)]; - GHOST_TInt32 bottom = (contentRect.size.height - 1) - height - top; + int32_t bottom = (contentRect.size.height - 1) - height - top; // Ensures window top left is inside this available rect left = left > contentRect.origin.x ? left : contentRect.origin.x; @@ -791,20 +791,20 @@ GHOST_TSuccess GHOST_SystemCocoa::disposeContext(GHOST_IContext *context) /** * \note : returns coordinates in Cocoa screen coordinates */ -GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const +GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(int32_t &x, int32_t &y) const { NSPoint mouseLoc = [NSEvent mouseLocation]; // Returns the mouse location in screen coordinates - x = (GHOST_TInt32)mouseLoc.x; - y = (GHOST_TInt32)mouseLoc.y; + x = (int32_t)mouseLoc.x; + y = (int32_t)mouseLoc.y; return GHOST_kSuccess; } /** * \note : expect Cocoa screen coordinates */ -GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) +GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(int32_t x, int32_t y) { GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)m_windowManager->getActiveWindow(); if (!window) @@ -824,7 +824,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 return GHOST_kSuccess; } -GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) +GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(int32_t x, int32_t y) { float xf = (float)x, yf = (float)y; GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)m_windowManager->getActiveWindow(); @@ -897,7 +897,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) GHOST_TimerManager* timerMgr = getTimerManager(); if (waitForEvent) { - GHOST_TUns64 next = timerMgr->nextFireTime(); + uint64_t next = timerMgr->nextFireTime(); double timeOut; if (next == GHOST_kFireTimeNever) { @@ -1132,7 +1132,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType break; case GHOST_kEventDraggingDropDone: { - GHOST_TUns8 *temp_buff; + uint8_t *temp_buff; GHOST_TStringArray *strArray; NSArray *droppedArray; size_t pastedTextSize; @@ -1157,13 +1157,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType return GHOST_kFailure; } - strArray->strings = (GHOST_TUns8 **)malloc(strArray->count * sizeof(GHOST_TUns8 *)); + strArray->strings = (uint8_t **)malloc(strArray->count * sizeof(uint8_t *)); for (i = 0; i < strArray->count; i++) { droppedStr = [droppedArray objectAtIndex:i]; pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - temp_buff = (GHOST_TUns8 *)malloc(pastedTextSize + 1); + temp_buff = (uint8_t *)malloc(pastedTextSize + 1); if (!temp_buff) { strArray->count = i; @@ -1185,7 +1185,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType droppedStr = (NSString *)data; pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - temp_buff = (GHOST_TUns8 *)malloc(pastedTextSize + 1); + temp_buff = (uint8_t *)malloc(pastedTextSize + 1); if (temp_buff == NULL) { return GHOST_kFailure; @@ -1204,9 +1204,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType NSImage *droppedImg = (NSImage *)data; NSSize imgSize = [droppedImg size]; ImBuf *ibuf = NULL; - GHOST_TUns8 *rasterRGB = NULL; - GHOST_TUns8 *rasterRGBA = NULL; - GHOST_TUns8 *toIBuf = NULL; + uint8_t *rasterRGB = NULL; + uint8_t *rasterRGBA = NULL; + uint8_t *toIBuf = NULL; int x, y, to_i, from_i; NSBitmapImageRep *blBitmapFormatImageRGB, *blBitmapFormatImageRGBA, *bitmapImage = nil; NSEnumerator *enumerator; @@ -1232,8 +1232,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0) && ![bitmapImage isPlanar]) { /* Try a fast copy if the image is a meshed RGBA 32bit bitmap. */ - toIBuf = (GHOST_TUns8 *)ibuf->rect; - rasterRGB = (GHOST_TUns8 *)[bitmapImage bitmapData]; + toIBuf = (uint8_t *)ibuf->rect; + rasterRGB = (uint8_t *)[bitmapImage bitmapData]; for (y = 0; y < imgSize.height; y++) { to_i = (imgSize.height - y - 1) * imgSize.width; from_i = y * imgSize.width; @@ -1270,7 +1270,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - rasterRGB = (GHOST_TUns8 *)[blBitmapFormatImageRGB bitmapData]; + rasterRGB = (uint8_t *)[blBitmapFormatImageRGB bitmapData]; if (rasterRGB == NULL) { [bitmapImage release]; [blBitmapFormatImageRGB release]; @@ -1299,7 +1299,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - rasterRGBA = (GHOST_TUns8 *)[blBitmapFormatImageRGBA bitmapData]; + rasterRGBA = (uint8_t *)[blBitmapFormatImageRGBA bitmapData]; if (rasterRGBA == NULL) { [bitmapImage release]; [blBitmapFormatImageRGB release]; @@ -1309,7 +1309,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType } /* Copy the image to ibuf, flipping it vertically. */ - toIBuf = (GHOST_TUns8 *)ibuf->rect; + toIBuf = (uint8_t *)ibuf->rect; for (y = 0; y < imgSize.height; y++) { for (x = 0; x < imgSize.width; x++) { to_i = (imgSize.height - y - 1) * imgSize.width + x; @@ -1563,7 +1563,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) switch (grab_mode) { case GHOST_kGrabHide: // Cursor hidden grab operation : no cursor move { - GHOST_TInt32 x_warp, y_warp, x_accum, y_accum, x, y; + int32_t x_warp, y_warp, x_accum, y_accum, x, y; window->getCursorGrabInitPos(x_warp, y_warp); window->screenToClientIntern(x_warp, y_warp, x_warp, y_warp); @@ -1593,8 +1593,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } NSPoint mousePos = [event locationInWindow]; - GHOST_TInt32 x_mouse = mousePos.x; - GHOST_TInt32 y_mouse = mousePos.y; + int32_t x_mouse = mousePos.x; + int32_t y_mouse = mousePos.y; GHOST_Rect bounds, windowBounds, correctedBounds; /* fallback to window bounds */ @@ -1610,19 +1610,19 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t; // Get accumulation from previous mouse warps - GHOST_TInt32 x_accum, y_accum; + int32_t x_accum, y_accum; window->getCursorGrabAccum(x_accum, y_accum); // Warp mouse cursor if needed - GHOST_TInt32 warped_x_mouse = x_mouse; - GHOST_TInt32 warped_y_mouse = y_mouse; + int32_t warped_x_mouse = x_mouse; + int32_t warped_y_mouse = y_mouse; correctedBounds.wrapPoint( warped_x_mouse, warped_y_mouse, 4, window->getCursorGrabAxis()); // Set new cursor position if (x_mouse != warped_x_mouse || y_mouse != warped_y_mouse) { - GHOST_TInt32 warped_x, warped_y; + int32_t warped_x, warped_y; window->clientToScreenIntern(warped_x_mouse, warped_y_mouse, warped_x, warped_y); setMouseCursorPosition(warped_x, warped_y); /* wrap */ window->setCursorGrabAccum(x_accum + (x_mouse - warped_x_mouse), @@ -1633,7 +1633,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } // Generate event - GHOST_TInt32 x, y; + int32_t x, y; window->clientToScreenIntern(x_mouse + x_accum, y_mouse + y_accum, x, y); pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, @@ -1646,7 +1646,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) default: { // Normal cursor operation: send mouse position in window NSPoint mousePos = [event locationInWindow]; - GHOST_TInt32 x, y; + int32_t x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); pushEvent(new GHOST_EventCursor([event timestamp] * 1000, @@ -1690,7 +1690,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) /* Standard scroll-wheel case, if no swiping happened, * and no momentum (kinetic scroll) works. */ if (!m_multiTouchScroll && momentumPhase == NSEventPhaseNone) { - GHOST_TInt32 delta; + int32_t delta; double deltaF = [event deltaY]; @@ -1704,7 +1704,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } else { NSPoint mousePos = [event locationInWindow]; - GHOST_TInt32 x, y; + int32_t x, y; double dx; double dy; @@ -1734,7 +1734,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSEventTypeMagnify: { NSPoint mousePos = [event locationInWindow]; - GHOST_TInt32 x, y; + int32_t x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, @@ -1748,7 +1748,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSEventTypeSmartMagnify: { NSPoint mousePos = [event locationInWindow]; - GHOST_TInt32 x, y; + int32_t x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); pushEvent(new GHOST_EventTrackpad( [event timestamp] * 1000, window, GHOST_kTrackpadEventSmartMagnify, x, y, 0, 0, false)); @@ -1756,7 +1756,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSEventTypeRotate: { NSPoint mousePos = [event locationInWindow]; - GHOST_TInt32 x, y; + int32_t x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, @@ -1933,9 +1933,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) #pragma mark Clipboard get/set -GHOST_TUns8 *GHOST_SystemCocoa::getClipboard(bool selection) const +char *GHOST_SystemCocoa::getClipboard(bool selection) const { - GHOST_TUns8 *temp_buff; + char *temp_buff; size_t pastedTextSize; @autoreleasepool { @@ -1950,14 +1950,13 @@ GHOST_TUns8 *GHOST_SystemCocoa::getClipboard(bool selection) const pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - temp_buff = (GHOST_TUns8 *)malloc(pastedTextSize + 1); + temp_buff = (char *)malloc(pastedTextSize + 1); if (temp_buff == NULL) { return NULL; } - strncpy( - (char *)temp_buff, [textPasted cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize); + strncpy(temp_buff, [textPasted cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize); temp_buff[pastedTextSize] = '\0'; @@ -1970,7 +1969,7 @@ GHOST_TUns8 *GHOST_SystemCocoa::getClipboard(bool selection) const } } -void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const +void GHOST_SystemCocoa::putClipboard(const char *buffer, bool selection) const { if (selection) return; // for copying the selection, used on X11 diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h index faeffffed9e..5dbc42b53a2 100644 --- a/intern/ghost/intern/GHOST_SystemNULL.h +++ b/intern/ghost/intern/GHOST_SystemNULL.h @@ -52,33 +52,33 @@ class GHOST_SystemNULL : public GHOST_System { { return GHOST_kSuccess; } - GHOST_TUns8 *getClipboard(bool selection) const + char *getClipboard(bool selection) const { return NULL; } - void putClipboard(GHOST_TInt8 *buffer, bool selection) const + void putClipboard(const char *buffer, bool selection) const { /* nop */ } - GHOST_TUns64 getMilliSeconds() const + uint64_t getMilliSeconds() const { return 0; } - GHOST_TUns8 getNumDisplays() const + uint8_t getNumDisplays() const { - return GHOST_TUns8(1); + return uint8_t(1); } - GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const + GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const { return GHOST_kFailure; } - GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) + GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) { return GHOST_kFailure; } - void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const + void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { /* nop */ } - void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const + void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const { /* nop */ } GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) @@ -106,10 +106,10 @@ class GHOST_SystemNULL : public GHOST_System { } GHOST_IWindow *createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, diff --git a/intern/ghost/intern/GHOST_SystemPaths.h b/intern/ghost/intern/GHOST_SystemPaths.h index ab53b2813cd..5bd52d44b42 100644 --- a/intern/ghost/intern/GHOST_SystemPaths.h +++ b/intern/ghost/intern/GHOST_SystemPaths.h @@ -49,20 +49,20 @@ class GHOST_SystemPaths : public GHOST_ISystemPaths { * "unpack and run" path, then look for properly installed path, including versioning. * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ - virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0; + virtual const char *getSystemDir(int version, const char *versionstr) const = 0; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ - virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0; + virtual const char *getUserDir(int version, const char *versionstr) const = 0; /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ - virtual const GHOST_TUns8 *getBinaryDir() const = 0; + virtual const char *getBinaryDir() const = 0; /** * Add the file to the operating system most recently used files diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h index 14633d46f03..1af63fc9b56 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h +++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h @@ -46,26 +46,26 @@ class GHOST_SystemPathsCocoa : public GHOST_SystemPaths { * "unpack and run" path, then look for properly installed path, including versioning. * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ - const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const; + const char *getSystemDir(int version, const char *versionstr) const; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ - const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; + const char *getUserDir(int version, const char *versionstr) const; /** * Determine a special ("well known") and easy to reach user directory. * \return Unsigned char string pointing to user dir (eg `~/Documents/`). */ - const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; + const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ - const GHOST_TUns8 *getBinaryDir() const; + const char *getBinaryDir() const; /** * Add the file to the operating system most recently used files diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm index 7c6184837bf..3b29d5106f6 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm @@ -36,7 +36,7 @@ GHOST_SystemPathsCocoa::~GHOST_SystemPathsCocoa() #pragma mark Base directories retrieval -const GHOST_TUns8 *GHOST_SystemPathsCocoa::getSystemDir(int, const char *versionstr) const +const char *GHOST_SystemPathsCocoa::getSystemDir(int, const char *versionstr) const { static char tempPath[512] = ""; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -60,10 +60,10 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getSystemDir(int, const char *version versionstr); [pool drain]; - return (GHOST_TUns8 *)tempPath; + return tempPath; } -const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionstr) const +const char *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionstr) const { static char tempPath[512] = ""; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -87,10 +87,10 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionst versionstr); [pool drain]; - return (GHOST_TUns8 *)tempPath; + return tempPath; } -const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const +const char *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const { static char tempPath[512] = ""; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -138,12 +138,12 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialD (char *)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding], sizeof(tempPath)); [pool drain]; - return (GHOST_TUns8 *)tempPath; + return tempPath; } -const GHOST_TUns8 *GHOST_SystemPathsCocoa::getBinaryDir() const +const char *GHOST_SystemPathsCocoa::getBinaryDir() const { - static GHOST_TUns8 tempPath[512] = ""; + static char tempPath[512] = ""; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *basePath; diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp index 86f3a0a31fb..b58799e9c2a 100644 --- a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp @@ -55,18 +55,18 @@ GHOST_SystemPathsUnix::~GHOST_SystemPathsUnix() { } -const GHOST_TUns8 *GHOST_SystemPathsUnix::getSystemDir(int, const char *versionstr) const +const char *GHOST_SystemPathsUnix::getSystemDir(int, const char *versionstr) const { /* no prefix assumes a portable build which only uses bundled scripts */ if (static_path) { static string system_path = string(static_path) + "/blender/" + versionstr; - return (GHOST_TUns8 *)system_path.c_str(); + return system_path.c_str(); } return NULL; } -const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionstr) const +const char *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionstr) const { static string user_path = ""; static int last_version = 0; @@ -86,7 +86,7 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *ve return NULL; } } - return (GHOST_TUns8 *)user_path.c_str(); + return user_path.c_str(); } else { if (user_path.empty() || last_version != version) { @@ -107,11 +107,11 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *ve } } - return (const GHOST_TUns8 *)user_path.c_str(); + return user_path.c_str(); } } -const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const +const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const { const char *type_str; @@ -164,10 +164,10 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDi } path = path_stream.str(); - return path[0] ? (const GHOST_TUns8 *)path.c_str() : NULL; + return path[0] ? path.c_str() : NULL; } -const GHOST_TUns8 *GHOST_SystemPathsUnix::getBinaryDir() const +const char *GHOST_SystemPathsUnix::getBinaryDir() const { return NULL; } diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.h b/intern/ghost/intern/GHOST_SystemPathsUnix.h index bc9272ecd8f..37fb432e9e8 100644 --- a/intern/ghost/intern/GHOST_SystemPathsUnix.h +++ b/intern/ghost/intern/GHOST_SystemPathsUnix.h @@ -44,26 +44,26 @@ class GHOST_SystemPathsUnix : public GHOST_SystemPaths { * "unpack and run" path, then look for properly installed path, including versioning. * \return Unsigned char string pointing to system dir (eg `/usr/share/blender/`). */ - const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const; + const char *getSystemDir(int version, const char *versionstr) const; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. * \return Unsigned char string pointing to user dir (eg `~/.config/.blender/`). */ - const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; + const char *getUserDir(int version, const char *versionstr) const; /** * Determine a special ("well known") and easy to reach user directory. * \return Unsigned char string pointing to user dir (eg `~/Documents/`). */ - const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; + const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ - const GHOST_TUns8 *getBinaryDir() const; + const char *getBinaryDir() const; /** * Add the file to the operating system most recently used files diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp index 47e71b0d733..580cfcac7ba 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp @@ -38,7 +38,7 @@ GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32() { } -const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) const +const char *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) const { /* 1 utf-16 might translate into 3 utf-8. 2 utf-16 translates into 4 utf-8. */ static char knownpath[MAX_PATH * 3 + 128] = {0}; @@ -52,13 +52,13 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *version CoTaskMemFree(knownpath_16); strcat(knownpath, "\\Blender Foundation\\Blender\\"); strcat(knownpath, versionstr); - return (GHOST_TUns8 *)knownpath; + return knownpath; } return NULL; } -const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) const +const char *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) const { static char knownpath[MAX_PATH * 3 + 128] = {0}; PWSTR knownpath_16 = NULL; @@ -71,13 +71,13 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionst CoTaskMemFree(knownpath_16); strcat(knownpath, "\\Blender Foundation\\Blender\\"); strcat(knownpath, versionstr); - return (GHOST_TUns8 *)knownpath; + return knownpath; } return NULL; } -const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const +const char *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const { GUID folderid; @@ -114,21 +114,21 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialD if (hResult == S_OK) { conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3); CoTaskMemFree(knownpath_16); - return (GHOST_TUns8 *)knownpath; + return knownpath; } CoTaskMemFree(knownpath_16); return NULL; } -const GHOST_TUns8 *GHOST_SystemPathsWin32::getBinaryDir() const +const char *GHOST_SystemPathsWin32::getBinaryDir() const { static char fullname[MAX_PATH * 3] = {0}; wchar_t fullname_16[MAX_PATH * 3]; if (GetModuleFileNameW(0, fullname_16, MAX_PATH)) { conv_utf_16_to_8(fullname_16, fullname, MAX_PATH * 3); - return (GHOST_TUns8 *)fullname; + return fullname; } return NULL; diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h index 45e03e744a5..c9f7f6b987f 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.h +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h @@ -53,26 +53,26 @@ class GHOST_SystemPathsWin32 : public GHOST_SystemPaths { * "unpack and run" path, then look for properly installed path, including versioning. * \return Unsigned char string pointing to system dir (eg /usr/share/). */ - const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const; + const char *getSystemDir(int version, const char *versionstr) const; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. * \return Unsigned char string pointing to user dir (eg ~/). */ - const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; + const char *getUserDir(int version, const char *versionstr) const; /** * Determine a special ("well known") and easy to reach user directory. * \return Unsigned char string pointing to user dir (eg `~/Documents/`). */ - const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; + const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ - const GHOST_TUns8 *getBinaryDir() const; + const char *getBinaryDir() const; /** * Add the file to the operating system most recently used files diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index eccef18bee2..f2f1b26b8e5 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -50,10 +50,10 @@ GHOST_SystemSDL::~GHOST_SystemSDL() } GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -118,23 +118,23 @@ GHOST_TSuccess GHOST_SystemSDL::init() * Returns the dimensions of the main display on this system. * \return The dimension of the main display. */ -void GHOST_SystemSDL::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemSDL::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const { SDL_DisplayMode mode; - SDL_GetDesktopDisplayMode(0, &mode); /* note, always 0 display */ + SDL_GetDesktopDisplayMode(0, &mode); /* NOTE: always 0 display. */ width = mode.w; height = mode.h; } -void GHOST_SystemSDL::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemSDL::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { SDL_DisplayMode mode; - SDL_GetCurrentDisplayMode(0, &mode); /* note, always 0 display */ + SDL_GetCurrentDisplayMode(0, &mode); /* NOTE: always 0 display. */ width = mode.w; height = mode.h; } -GHOST_TUns8 GHOST_SystemSDL::getNumDisplays() const +uint8_t GHOST_SystemSDL::getNumDisplays() const { return SDL_GetNumVideoDisplays(); } @@ -356,15 +356,15 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event) int x_win, y_win; SDL_GetWindowPosition(sdl_win, &x_win, &y_win); - GHOST_TInt32 x_root = sdl_sub_evt.x + x_win; - GHOST_TInt32 y_root = sdl_sub_evt.y + y_win; + int32_t x_root = sdl_sub_evt.x + x_win; + int32_t y_root = sdl_sub_evt.y + y_win; #if 0 if (window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) { - GHOST_TInt32 x_new = x_root; - GHOST_TInt32 y_new = y_root; - GHOST_TInt32 x_accum, y_accum; + int32_t x_new = x_root; + int32_t y_new = y_root; + int32_t x_accum, y_accum; GHOST_Rect bounds; /* fallback to window bounds */ @@ -468,8 +468,8 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event) assert(window != NULL); GHOST_TKey gkey = convertSDLKey(sdl_sub_evt.keysym.scancode); - /* note, the sdl_sub_evt.keysym.sym is truncated, - * for unicode support ghost has to be modified */ + /* NOTE: the `sdl_sub_evt.keysym.sym` is truncated, + * for unicode support ghost has to be modified. */ /* printf("%d\n", sym); */ if (sym > 127) { switch (sym) { @@ -611,7 +611,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event) } } -GHOST_TSuccess GHOST_SystemSDL::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const +GHOST_TSuccess GHOST_SystemSDL::getCursorPosition(int32_t &x, int32_t &y) const { int x_win, y_win; SDL_Window *win = SDL_GetMouseFocus(); @@ -625,7 +625,7 @@ GHOST_TSuccess GHOST_SystemSDL::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 return GHOST_kSuccess; } -GHOST_TSuccess GHOST_SystemSDL::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) +GHOST_TSuccess GHOST_SystemSDL::setCursorPosition(int32_t x, int32_t y) { int x_win, y_win; SDL_Window *win = SDL_GetMouseFocus(); @@ -668,14 +668,14 @@ bool GHOST_SystemSDL::processEvents(bool waitForEvent) GHOST_TimerManager *timerMgr = getTimerManager(); if (waitForEvent && m_dirty_windows.empty() && !SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT)) { - GHOST_TUns64 next = timerMgr->nextFireTime(); + uint64_t next = timerMgr->nextFireTime(); if (next == GHOST_kFireTimeNever) { SDL_WaitEventTimeout(NULL, -1); // SleepTillEvent(m_display, -1); } else { - GHOST_TInt64 maxSleep = next - getMilliSeconds(); + int64_t maxSleep = next - getMilliSeconds(); if (maxSleep >= 0) { SDL_WaitEventTimeout(NULL, next - getMilliSeconds()); @@ -743,17 +743,17 @@ GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons &buttons) const return GHOST_kSuccess; } -GHOST_TUns8 *GHOST_SystemSDL::getClipboard(bool selection) const +char *GHOST_SystemSDL::getClipboard(bool selection) const { - return (GHOST_TUns8 *)SDL_GetClipboardText(); + return (char *)SDL_GetClipboardText(); } -void GHOST_SystemSDL::putClipboard(GHOST_TInt8 *buffer, bool selection) const +void GHOST_SystemSDL::putClipboard(const char *buffer, bool selection) const { SDL_SetClipboardText(buffer); } -GHOST_TUns64 GHOST_SystemSDL::getMilliSeconds() +uint64_t GHOST_SystemSDL::getMilliSeconds() { - return GHOST_TUns64(SDL_GetTicks()); /* note, 32 -> 64bits */ + return uint64_t(SDL_GetTicks()); /* NOTE: 32 -> 64bits. */ } diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index 1c92762ea01..051bb6777b1 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -56,21 +56,21 @@ class GHOST_SystemSDL : public GHOST_System { GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const; - GHOST_TUns8 *getClipboard(bool selection) const; + char *getClipboard(bool selection) const; - void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + void putClipboard(const char *buffer, bool selection) const; - GHOST_TUns64 getMilliSeconds(); + uint64_t getMilliSeconds(); - GHOST_TUns8 getNumDisplays() const; + uint8_t getNumDisplays() const; - GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const; + GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const; - GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + GHOST_TSuccess setCursorPosition(int32_t x, int32_t y); - void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const; - void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const; GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings); @@ -80,10 +80,10 @@ class GHOST_SystemSDL : public GHOST_System { GHOST_TSuccess init(); GHOST_IWindow *createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index f54a022f249..38700845405 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -47,12 +47,20 @@ #include <xkbcommon/xkbcommon.h> #include <fcntl.h> -#include <linux/input-event-codes.h> #include <sys/mman.h> #include <unistd.h> #include <cstring> +/* selected input event code defines from 'linux/input-event-codes.h' + * We include some of the button input event codes here, since the header is + * only available in more recent kernel versions. The event codes are used to + * to differentiate from which mouse button an event comes from. + */ +#define BTN_LEFT 0x110 +#define BTN_RIGHT 0x111 +#define BTN_MIDDLE 0x112 + struct buffer_t { void *data; size_t size; @@ -468,7 +476,7 @@ static const zwp_relative_pointer_v1_listener relative_pointer_listener = { static void dnd_events(const input_t *const input, const GHOST_TEventType event) { - const GHOST_TUns64 time = input->system->getMilliSeconds(); + const uint64_t time = input->system->getMilliSeconds(); GHOST_IWindow *const window = static_cast<GHOST_WindowWayland *>( wl_surface_get_user_data(input->focus_pointer)); for (const std::string &type : mime_preference_order) { @@ -718,10 +726,9 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>( malloc(sizeof(GHOST_TStringArray))); flist->count = int(uris.size()); - flist->strings = static_cast<GHOST_TUns8 **>(malloc(uris.size() * sizeof(GHOST_TUns8 *))); + flist->strings = static_cast<uint8_t **>(malloc(uris.size() * sizeof(uint8_t *))); for (size_t i = 0; i < uris.size(); i++) { - flist->strings[i] = static_cast<GHOST_TUns8 *>( - malloc((uris[i].size() + 1) * sizeof(GHOST_TUns8))); + flist->strings[i] = static_cast<uint8_t *>(malloc((uris[i].size() + 1) * sizeof(uint8_t))); memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1); } GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>( @@ -1171,7 +1178,7 @@ static void keyboard_key(void *data, .key_data = key_data, }); - auto cb = [](GHOST_ITimerTask *task, GHOST_TUns64 /*time*/) { + auto cb = [](GHOST_ITimerTask *task, uint64_t /*time*/) { struct key_repeat_payload_t *payload = static_cast<key_repeat_payload_t *>( task->getUserData()); payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(), @@ -1511,14 +1518,14 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const return GHOST_kFailure; } -GHOST_TUns8 *GHOST_SystemWayland::getClipboard(bool /*selection*/) const +char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const { - GHOST_TUns8 *clipboard = static_cast<GHOST_TUns8 *>(malloc((selection.size() + 1))); + char *clipboard = static_cast<char *>(malloc((selection.size() + 1))); memcpy(clipboard, selection.data(), selection.size() + 1); return clipboard; } -void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/) const +void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const { if (!d->data_device_manager || d->inputs.empty()) { return; @@ -1545,12 +1552,12 @@ void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/) } } -GHOST_TUns8 GHOST_SystemWayland::getNumDisplays() const +uint8_t GHOST_SystemWayland::getNumDisplays() const { - return d ? GHOST_TUns8(d->outputs.size()) : 0; + return d ? uint8_t(d->outputs.size()) : 0; } -GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const +GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const { if (!d->inputs.empty() && (d->inputs[0]->focus_pointer != nullptr)) { x = d->inputs[0]->x; @@ -1562,12 +1569,12 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TIn } } -GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(GHOST_TInt32 /*x*/, GHOST_TInt32 /*y*/) +GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(int32_t /*x*/, int32_t /*y*/) { return GHOST_kFailure; } -void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemWayland::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { if (getNumDisplays() > 0) { /* We assume first output as main. */ @@ -1576,7 +1583,7 @@ void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TU } } -void GHOST_SystemWayland::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const { getMainDisplayDimensions(width, height); } @@ -1640,10 +1647,10 @@ GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context) } GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -1780,8 +1787,8 @@ GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(GHOST_TStandardCursor cursorS return GHOST_TSuccess(cursors.count(cursorShape) && !cursors.at(cursorShape).empty()); } -GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, +GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -1797,13 +1804,43 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(GHOST_TUns8 *bitmap, static const int32_t stride = sizex * 4; /* ARGB */ cursor->file_buffer->size = size_t(stride * sizey); +#ifdef HAVE_MEMFD_CREATE const int fd = memfd_create("blender-cursor-custom", MFD_CLOEXEC | MFD_ALLOW_SEALING); - fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK); - posix_fallocate(fd, 0, int32_t(cursor->file_buffer->size)); + if (fd >= 0) { + fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL); + } +#else + char *path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return GHOST_kFailure; + } + + char *tmpname; + asprintf(&tmpname, "%s/%s", path, "blender-XXXXXX"); + const int fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) { + unlink(tmpname); + } + free(tmpname); +#endif + + if (fd < 0) { + return GHOST_kFailure; + } + + if (posix_fallocate(fd, 0, int32_t(cursor->file_buffer->size)) != 0) { + return GHOST_kFailure; + } cursor->file_buffer->data = mmap( nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cursor->file_buffer->data == MAP_FAILED) { + close(fd); + return GHOST_kFailure; + } + struct wl_shm_pool *pool = wl_shm_create_pool(d->shm, fd, int32_t(cursor->file_buffer->size)); wl_buffer *buffer = wl_shm_pool_create_buffer( diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 3a08a0d3b16..9f02afb9d5a 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -59,29 +59,29 @@ class GHOST_SystemWayland : public GHOST_System { GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override; - GHOST_TUns8 *getClipboard(bool selection) const override; + char *getClipboard(bool selection) const override; - void putClipboard(GHOST_TInt8 *buffer, bool selection) const override; + void putClipboard(const char *buffer, bool selection) const override; - GHOST_TUns8 getNumDisplays() const override; + uint8_t getNumDisplays() const override; - GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const override; + GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const override; - GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) override; + GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) override; - void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override; + void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const override; - void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override; + void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override; GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override; GHOST_TSuccess disposeContext(GHOST_IContext *context) override; GHOST_IWindow *createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -107,8 +107,8 @@ class GHOST_SystemWayland : public GHOST_System { GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape); - GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index a7cb4aee837..4f5e957077d 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -169,21 +169,21 @@ GHOST_SystemWin32::~GHOST_SystemWin32() toggleConsole(1); } -GHOST_TUns64 GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const +uint64_t GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const { // Calculate the time passed since system initialization. __int64 delta = (perf_ticks - m_start) * 1000; - GHOST_TUns64 t = (GHOST_TUns64)(delta / m_freq); + uint64_t t = (uint64_t)(delta / m_freq); return t; } -GHOST_TUns64 GHOST_SystemWin32::tickCountToMillis(__int64 ticks) const +uint64_t GHOST_SystemWin32::tickCountToMillis(__int64 ticks) const { return ticks - m_lfstart; } -GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const +uint64_t GHOST_SystemWin32::getMilliSeconds() const { // Hardware does not support high resolution timers. We will use GetTickCount instead then. if (!m_hasPerformanceCounter) { @@ -197,31 +197,31 @@ GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const return performanceCounterToMillis(count); } -GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const +uint8_t GHOST_SystemWin32::getNumDisplays() const { GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n"); - GHOST_TUns8 numDisplays; + uint8_t numDisplays; m_displayManager->getNumDisplays(numDisplays); return numDisplays; } -void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemWin32::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { width = ::GetSystemMetrics(SM_CXSCREEN); height = ::GetSystemMetrics(SM_CYSCREEN); } -void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemWin32::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const { width = ::GetSystemMetrics(SM_CXVIRTUALSCREEN); height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); } GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -410,8 +410,8 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) #if 1 ::Sleep(1); #else - GHOST_TUns64 next = timerMgr->nextFireTime(); - GHOST_TInt64 maxSleep = next - getMilliSeconds(); + uint64_t next = timerMgr->nextFireTime(); + int64_t maxSleep = next - getMilliSeconds(); if (next == GHOST_kFireTimeNever) { ::WaitMessage(); @@ -448,7 +448,7 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) return hasEventHandled; } -GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const +GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(int32_t &x, int32_t &y) const { POINT point; if (::GetCursorPos(&point)) { @@ -459,7 +459,7 @@ GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt3 return GHOST_kFailure; } -GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) +GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(int32_t x, int32_t y) { if (!::GetActiveWindow()) return GHOST_kFailure; @@ -1029,7 +1029,7 @@ void GHOST_SystemWin32::processPointerEvent( case WM_POINTERUPDATE: /* Coalesced pointer events are reverse chronological order, reorder chronologically. * Only contiguous move events are coalesced. */ - for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) { + for (uint32_t i = pointerInfo.size(); i-- > 0;) { system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time, GHOST_kEventCursorMove, window, @@ -1079,7 +1079,7 @@ void GHOST_SystemWin32::processPointerEvent( GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window) { - GHOST_TInt32 x_screen, y_screen; + int32_t x_screen, y_screen; GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); if (window->getTabletData().Active != GHOST_kTabletModeNone) { @@ -1090,9 +1090,9 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind system->getCursorPosition(x_screen, y_screen); if (window->getCursorGrabModeIsWarp()) { - GHOST_TInt32 x_new = x_screen; - GHOST_TInt32 y_new = y_screen; - GHOST_TInt32 x_accum, y_accum; + int32_t x_new = x_screen; + int32_t y_new = y_screen; + int32_t x_accum, y_accum; GHOST_Rect bounds; /* Fallback to window bounds. */ @@ -1197,8 +1197,8 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA // Don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical // composition. else if (MapVirtualKeyW(vk, 2) != 0) { - // todo: ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here). - // Could be up to 24 utf8 bytes. + /* TODO: #ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here). + * Could be up to 24 utf8 bytes. */ if ((r = ToUnicodeEx( vk, raw.data.keyboard.MakeCode, state, utf16, 2, 0, system->m_keylayout))) { if ((r > 0 && r < 3)) { @@ -1322,7 +1322,7 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax) bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw) { bool eventSent = false; - GHOST_TUns64 now = getMilliSeconds(); + uint64_t now = getMilliSeconds(); static bool firstEvent = true; if (firstEvent) { // determine exactly which device is plugged in @@ -1627,7 +1627,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, processPointerEvent(msg, window, wParam, lParam, eventHandled); break; case WM_POINTERLEAVE: { - GHOST_TUns32 pointerId = GET_POINTERID_WPARAM(wParam); + uint32_t pointerId = GET_POINTERID_WPARAM(wParam); POINTER_INFO pointerInfo; if (!GetPointerInfo(pointerId, &pointerInfo)) { break; @@ -2002,7 +2002,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, return lResult; } -GHOST_TUns8 *GHOST_SystemWin32::getClipboard(bool selection) const +char *GHOST_SystemWin32::getClipboard(bool selection) const { char *temp_buff; @@ -2026,7 +2026,7 @@ GHOST_TUns8 *GHOST_SystemWin32::getClipboard(bool selection) const GlobalUnlock(hData); CloseClipboard(); - return (GHOST_TUns8 *)temp_buff; + return temp_buff; } else if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) { char *buffer; @@ -2052,14 +2052,14 @@ GHOST_TUns8 *GHOST_SystemWin32::getClipboard(bool selection) const GlobalUnlock(hData); CloseClipboard(); - return (GHOST_TUns8 *)temp_buff; + return temp_buff; } else { return NULL; } } -void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const +void GHOST_SystemWin32::putClipboard(const char *buffer, bool selection) const { if (selection) { return; diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 7dd61421d4c..6c786aedfb1 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -69,14 +69,14 @@ class GHOST_SystemWin32 : public GHOST_System { * system process. * \return The number of milliseconds since the start of the system process. */ - GHOST_TUns64 performanceCounterToMillis(__int64 perf_ticks) const; + uint64_t performanceCounterToMillis(__int64 perf_ticks) const; /** * This method converts system ticks into milliseconds since the start of the * system process. * \return The number of milliseconds since the start of the system process. */ - GHOST_TUns64 tickCountToMillis(__int64 ticks) const; + uint64_t tickCountToMillis(__int64 ticks) const; /** * Returns the system time. @@ -84,7 +84,7 @@ class GHOST_SystemWin32 : public GHOST_System { * This overloaded method uses the high frequency timer if available. * \return The number of milliseconds. */ - GHOST_TUns64 getMilliSeconds() const; + uint64_t getMilliSeconds() const; /*************************************************************************************** ** Display/window management functionality @@ -94,19 +94,19 @@ class GHOST_SystemWin32 : public GHOST_System { * Returns the number of displays on this system. * \return The number of displays. */ - GHOST_TUns8 getNumDisplays() const; + uint8_t getNumDisplays() const; /** * Returns the dimensions of the main display on this system. * \return The dimension of the main display. */ - void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const; /** * Returns the dimensions of all displays on this system. * \return The dimension of the main display. */ - void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const; /** * Create a new window. @@ -126,10 +126,10 @@ class GHOST_SystemWin32 : public GHOST_System { * \return The new window (or 0 if creation failed). */ GHOST_IWindow *createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -189,7 +189,7 @@ class GHOST_SystemWin32 : public GHOST_System { * \param y: The y-coordinate of the cursor. * \return Indication of success. */ - GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const; + GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const; /** * Updates the location of the cursor (location in screen coordinates). @@ -197,7 +197,7 @@ class GHOST_SystemWin32 : public GHOST_System { * \param y: The y-coordinate of the cursor. * \return Indication of success. */ - GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + GHOST_TSuccess setCursorPosition(int32_t x, int32_t y); /*************************************************************************************** ** Access to mouse button and keyboard states. @@ -222,14 +222,14 @@ class GHOST_SystemWin32 : public GHOST_System { * \param selection: Used by X11 only. * \return Returns the Clipboard. */ - GHOST_TUns8 *getClipboard(bool selection) const; + char *getClipboard(bool selection) const; /** * Puts buffer to system clipboard. * \param selection: Used by X11 only. * \return No return. */ - void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + void putClipboard(const char *buffer, bool selection) const; /** * Show a system message box diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index c5564e9880e..172fcbeb3de 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -186,7 +186,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_ } /* Taking care not to overflow the `tv.tv_sec * 1000`. */ - m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000; + m_start_time = uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000; /* Use detectable auto-repeat, mac and windows also do this. */ int use_xkb; @@ -279,7 +279,7 @@ GHOST_TSuccess GHOST_SystemX11::init() return GHOST_kFailure; } -GHOST_TUns64 GHOST_SystemX11::getMilliSeconds() const +uint64_t GHOST_SystemX11::getMilliSeconds() const { timeval tv; if (gettimeofday(&tv, NULL) == -1) { @@ -287,24 +287,24 @@ GHOST_TUns64 GHOST_SystemX11::getMilliSeconds() const } /* Taking care not to overflow the tv.tv_sec * 1000 */ - return GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time; + return uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time; } -GHOST_TUns8 GHOST_SystemX11::getNumDisplays() const +uint8_t GHOST_SystemX11::getNumDisplays() const { - return GHOST_TUns8(1); + return uint8_t(1); } /** * Returns the dimensions of the main display on this system. * \return The dimension of the main display. */ -void GHOST_SystemX11::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemX11::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { if (m_display) { - /* note, for this to work as documented, + /* NOTE(campbell): for this to work as documented, * we would need to use Xinerama check r54370 for code that did this, - * we've since removed since its not worth the extra dep - campbell */ + * we've since removed since its not worth the extra dependency. */ getAllDisplayDimensions(width, height); } } @@ -313,7 +313,7 @@ void GHOST_SystemX11::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 * Returns the dimensions of the main display on this system. * \return The dimension of the main display. */ -void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +void GHOST_SystemX11::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const { if (m_display) { width = DisplayWidth(m_display, DefaultScreen(m_display)); @@ -339,10 +339,10 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 * \return The new window (or 0 if creation failed). */ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -570,7 +570,7 @@ GHOST_WindowX11 *GHOST_SystemX11::findGhostWindow(Window xwind) const return NULL; } -static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep) +static void SleepTillEvent(Display *display, int64_t maxSleep) { int fd = ConnectionNumber(display); fd_set fds; @@ -649,13 +649,13 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent) GHOST_TimerManager *timerMgr = getTimerManager(); if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) { - GHOST_TUns64 next = timerMgr->nextFireTime(); + uint64_t next = timerMgr->nextFireTime(); if (next == GHOST_kFireTimeNever) { SleepTillEvent(m_display, -1); } else { - GHOST_TInt64 maxSleep = next - getMilliSeconds(); + int64_t maxSleep = next - getMilliSeconds(); if (maxSleep >= 0) SleepTillEvent(m_display, next - getMilliSeconds()); @@ -965,9 +965,9 @@ void GHOST_SystemX11::processEvent(XEvent *xe) bool is_tablet = window->GetTabletData().Active != GHOST_kTabletModeNone; if (is_tablet == false && window->getCursorGrabModeIsWarp()) { - GHOST_TInt32 x_new = xme.x_root; - GHOST_TInt32 y_new = xme.y_root; - GHOST_TInt32 x_accum, y_accum; + int32_t x_new = xme.x_root; + int32_t y_new = xme.y_root; + int32_t x_accum, y_accum; GHOST_Rect bounds; /* fallback to window bounds */ @@ -1638,8 +1638,8 @@ GHOST_TSuccess GHOST_SystemX11::getButtons(GHOST_Buttons &buttons) const } static GHOST_TSuccess getCursorPosition_impl(Display *display, - GHOST_TInt32 &x, - GHOST_TInt32 &y, + int32_t &x, + int32_t &y, Window *child_return) { int rx, ry, wx, wy; @@ -1664,13 +1664,13 @@ static GHOST_TSuccess getCursorPosition_impl(Display *display, return GHOST_kSuccess; } -GHOST_TSuccess GHOST_SystemX11::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const +GHOST_TSuccess GHOST_SystemX11::getCursorPosition(int32_t &x, int32_t &y) const { Window child_return; return getCursorPosition_impl(m_display, x, y, &child_return); } -GHOST_TSuccess GHOST_SystemX11::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) +GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y) { /* This is a brute force move in screen coordinates @@ -2136,14 +2136,14 @@ void GHOST_SystemX11::getClipboard_xcout(const XEvent *evt, return; } -GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const +char *GHOST_SystemX11::getClipboard(bool selection) const { Atom sseln; Atom target = m_atom.UTF8_STRING; Window owner; /* from xclip.c doOut() v0.11 */ - unsigned char *sel_buf; + char *sel_buf; unsigned long sel_len = 0; XEvent evt; unsigned int context = XCLIB_XCOUT_NONE; @@ -2162,13 +2162,13 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const owner = XGetSelectionOwner(m_display, sseln); if (owner == win) { if (sseln == m_atom.CLIPBOARD) { - sel_buf = (unsigned char *)malloc(strlen(txt_cut_buffer) + 1); - strcpy((char *)sel_buf, txt_cut_buffer); + sel_buf = (char *)malloc(strlen(txt_cut_buffer) + 1); + strcpy(sel_buf, txt_cut_buffer); return sel_buf; } else { - sel_buf = (unsigned char *)malloc(strlen(txt_select_buffer) + 1); - strcpy((char *)sel_buf, txt_select_buffer); + sel_buf = (char *)malloc(strlen(txt_select_buffer) + 1); + strcpy(sel_buf, txt_select_buffer); return sel_buf; } } @@ -2187,7 +2187,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const } /* fetch the selection, or part of it */ - getClipboard_xcout(&evt, sseln, target, &sel_buf, &sel_len, &context); + getClipboard_xcout(&evt, sseln, target, (unsigned char **)&sel_buf, &sel_len, &context); if (restore_this_event) { restore_events.push_back(evt); @@ -2228,8 +2228,8 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const if (sel_len) { /* Only print the buffer out, and free it, if it's not empty. */ - unsigned char *tmp_data = (unsigned char *)malloc(sel_len + 1); - memcpy((char *)tmp_data, (char *)sel_buf, sel_len); + char *tmp_data = (char *)malloc(sel_len + 1); + memcpy(tmp_data, (char *)sel_buf, sel_len); tmp_data[sel_len] = '\0'; if (sseln == m_atom.STRING) @@ -2242,7 +2242,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const return NULL; } -void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const +void GHOST_SystemX11::putClipboard(const char *buffer, bool selection) const { Window m_window, owner; diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index ed5e945f69e..15ccde4a14b 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -98,25 +98,25 @@ class GHOST_SystemX11 : public GHOST_System { * Returns the number of milliseconds since the start of the system process. * \return The number of milliseconds. */ - GHOST_TUns64 getMilliSeconds() const; + uint64_t getMilliSeconds() const; /** * Returns the number of displays on this system. * \return The number of displays. */ - GHOST_TUns8 getNumDisplays() const; + uint8_t getNumDisplays() const; /** * Returns the dimensions of the main display on this system. * \return The dimension of the main display. */ - void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const; /** * Returns the dimensions of all displays on this system. * \return The dimension of the main display. */ - void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; + void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const; /** * Create a new window. @@ -136,10 +136,10 @@ class GHOST_SystemX11 : public GHOST_System { * \return The new window (or 0 if creation failed). */ GHOST_IWindow *createWindow(const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, @@ -168,9 +168,9 @@ class GHOST_SystemX11 : public GHOST_System { */ bool processEvents(bool waitForEvent); - GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const; + GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const; - GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + GHOST_TSuccess setCursorPosition(int32_t x, int32_t y); /** * Returns the state of all modifier keys. @@ -222,14 +222,14 @@ class GHOST_SystemX11 : public GHOST_System { * \param selection: Get selection, X11 only feature. * \return Returns the Clipboard indicated by Flag. */ - GHOST_TUns8 *getClipboard(bool selection) const; + char *getClipboard(bool selection) const; /** * Puts buffer to system clipboard * \param buffer: The buffer to copy to the clipboard. * \param selection: Set the selection into the clipboard, X11 only feature. */ - void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + void putClipboard(const char *buffer, bool selection) const; /** * Show a system message box @@ -351,7 +351,7 @@ class GHOST_SystemX11 : public GHOST_System { std::vector<GHOST_WindowX11 *> m_dirty_windows; /** Start time at initialization. */ - GHOST_TUns64 m_start_time; + uint64_t m_start_time; /** A vector of keyboard key masks. */ char m_keyboard_vector[32]; diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp index 22f646320ce..195135f5f85 100644 --- a/intern/ghost/intern/GHOST_TimerManager.cpp +++ b/intern/ghost/intern/GHOST_TimerManager.cpp @@ -40,9 +40,9 @@ GHOST_TimerManager::~GHOST_TimerManager() disposeTimers(); } -GHOST_TUns32 GHOST_TimerManager::getNumTimers() +uint32_t GHOST_TimerManager::getNumTimers() { - return (GHOST_TUns32)m_timers.size(); + return (uint32_t)m_timers.size(); } bool GHOST_TimerManager::getTimerFound(GHOST_TimerTask *timer) @@ -81,13 +81,13 @@ GHOST_TSuccess GHOST_TimerManager::removeTimer(GHOST_TimerTask *timer) return success; } -GHOST_TUns64 GHOST_TimerManager::nextFireTime() +uint64_t GHOST_TimerManager::nextFireTime() { - GHOST_TUns64 smallest = GHOST_kFireTimeNever; + uint64_t smallest = GHOST_kFireTimeNever; TTimerVector::iterator iter; for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) { - GHOST_TUns64 next = (*iter)->getNext(); + uint64_t next = (*iter)->getNext(); if (next < smallest) smallest = next; @@ -96,7 +96,7 @@ GHOST_TUns64 GHOST_TimerManager::nextFireTime() return smallest; } -bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time) +bool GHOST_TimerManager::fireTimers(uint64_t time) { TTimerVector::iterator iter; bool anyProcessed = false; @@ -109,20 +109,20 @@ bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time) return anyProcessed; } -bool GHOST_TimerManager::fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task) +bool GHOST_TimerManager::fireTimer(uint64_t time, GHOST_TimerTask *task) { - GHOST_TUns64 next = task->getNext(); + uint64_t next = task->getNext(); // Check if the timer should be fired if (time > next) { // Fire the timer GHOST_TimerProcPtr timerProc = task->getTimerProc(); - GHOST_TUns64 start = task->getStart(); + uint64_t start = task->getStart(); timerProc(task, time - start); // Update the time at which we will fire it again - GHOST_TUns64 interval = task->getInterval(); - GHOST_TUns64 numCalls = (next - start) / interval; + uint64_t interval = task->getInterval(); + uint64_t numCalls = (next - start) / interval; numCalls++; next = start + numCalls * interval; task->setNext(next); diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h index 3ca62202e5e..6261218a023 100644 --- a/intern/ghost/intern/GHOST_TimerManager.h +++ b/intern/ghost/intern/GHOST_TimerManager.h @@ -51,7 +51,7 @@ class GHOST_TimerManager { * Returns the number of timer tasks. * \return The number of events on the stack. */ - GHOST_TUns32 getNumTimers(); + uint32_t getNumTimers(); /** * Returns whether this timer task ins in our list. @@ -80,14 +80,14 @@ class GHOST_TimerManager { * \return The soonest time the next timer would fire, * or GHOST_kFireTimeNever if no timers exist. */ - GHOST_TUns64 nextFireTime(); + uint64_t nextFireTime(); /** * Checks all timer tasks to see if they are expired and fires them if needed. * \param time: The current time. * \return True if any timers were fired. */ - bool fireTimers(GHOST_TUns64 time); + bool fireTimers(uint64_t time); /** * Checks this timer task to see if they are expired and fires them if needed. @@ -95,7 +95,7 @@ class GHOST_TimerManager { * \param task: The timer task to check and optionally fire. * \return True if the timer fired. */ - bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task); + bool fireTimer(uint64_t time, GHOST_TimerTask *task); protected: /** diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h index 9c81d3d2637..e2812c6312b 100644 --- a/intern/ghost/intern/GHOST_TimerTask.h +++ b/intern/ghost/intern/GHOST_TimerTask.h @@ -38,8 +38,8 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * \param timerProc: The callback invoked when the interval expires. * \param userData: The timer user data. */ - GHOST_TimerTask(GHOST_TUns64 start, - GHOST_TUns64 interval, + GHOST_TimerTask(uint64_t start, + uint64_t interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = NULL) : m_start(start), @@ -55,7 +55,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Returns the timer start time. * \return The timer start time. */ - inline GHOST_TUns64 getStart() const + inline uint64_t getStart() const { return m_start; } @@ -64,7 +64,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Changes the timer start time. * \param start: The timer start time. */ - void setStart(GHOST_TUns64 start) + void setStart(uint64_t start) { m_start = start; } @@ -73,7 +73,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Returns the timer interval. * \return The timer interval. */ - inline GHOST_TUns64 getInterval() const + inline uint64_t getInterval() const { return m_interval; } @@ -82,7 +82,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Changes the timer interval. * \param interval: The timer interval. */ - void setInterval(GHOST_TUns64 interval) + void setInterval(uint64_t interval) { m_interval = interval; } @@ -91,7 +91,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Returns the time the timerProc will be called. * \return The time the timerProc will be called. */ - inline GHOST_TUns64 getNext() const + inline uint64_t getNext() const { return m_next; } @@ -100,7 +100,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Changes the time the timerProc will be called. * \param next: The time the timerProc will be called. */ - void setNext(GHOST_TUns64 next) + void setNext(uint64_t next) { m_next = next; } @@ -145,7 +145,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Returns the auxiliary storage room. * \return The auxiliary storage room. */ - inline GHOST_TUns32 getAuxData() const + inline uint32_t getAuxData() const { return m_auxData; } @@ -154,20 +154,20 @@ class GHOST_TimerTask : public GHOST_ITimerTask { * Changes the auxiliary storage room. * \param auxData: The auxiliary storage room. */ - void setAuxData(GHOST_TUns32 auxData) + void setAuxData(uint32_t auxData) { m_auxData = auxData; } protected: /** The time the timer task was started. */ - GHOST_TUns64 m_start; + uint64_t m_start; /** The interval between calls. */ - GHOST_TUns64 m_interval; + uint64_t m_interval; /** The time the timerProc will be called. */ - GHOST_TUns64 m_next; + uint64_t m_next; /** The callback invoked when the timer expires. */ GHOST_TimerProcPtr m_timerProc; @@ -176,5 +176,5 @@ class GHOST_TimerTask : public GHOST_ITimerTask { GHOST_TUserDataPtr m_userData; /** Auxiliary storage room. */ - GHOST_TUns32 m_auxData; + uint32_t m_auxData; }; diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index ca19e251279..6009d7dbcfc 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -31,8 +31,8 @@ #include <assert.h> -GHOST_Window::GHOST_Window(GHOST_TUns32 width, - GHOST_TUns32 height, +GHOST_Window::GHOST_Window(uint32_t width, + uint32_t height, GHOST_TWindowState state, const bool wantStereoVisual, const bool /*exclusive*/) @@ -143,7 +143,7 @@ GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible) GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_TAxisFlag wrap_axis, GHOST_Rect *bounds, - GHOST_TInt32 mouse_ungrab_xy[2]) + int32_t mouse_ungrab_xy[2]) { if (m_cursorGrab == mode) return GHOST_kSuccess; @@ -192,13 +192,8 @@ GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape) } } -GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, - int sizex, - int sizey, - int hotX, - int hotY, - bool canInvertColor) +GHOST_TSuccess GHOST_Window::setCustomCursorShape( + uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) { if (setWindowCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor)) { m_cursorShape = GHOST_kStandardCursorCustom; diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 3542c6f2bcf..f061e07b3c8 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -48,8 +48,8 @@ class GHOST_Window : public GHOST_IWindow { * \param stereoVisual: Stereo visual for quad buffered stereo. * \param exclusive: Use to show the window ontop and ignore others (used full-screen). */ - GHOST_Window(GHOST_TUns32 width, - GHOST_TUns32 height, + GHOST_Window(uint32_t width, + uint32_t height, GHOST_TWindowState state, const bool wantStereoVisual = false, const bool exclusive = false); @@ -62,13 +62,13 @@ class GHOST_Window : public GHOST_IWindow { * virtual std::string getTitle() const = 0; * virtual void getWindowBounds(GHOST_Rect& bounds) const = 0; * virtual void getClientBounds(GHOST_Rect& bounds) const = 0; - * virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0; - * virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0; - * virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; + * virtual GHOST_TSuccess setClientWidth(uint32_t width) = 0; + * virtual GHOST_TSuccess setClientHeight(uint32_t height) = 0; + * virtual GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) = 0; * virtual void screenToClient( - * GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; + * int32_t inX, int32_t inY, int32_t& outX, int32_t& outY) const = 0; * virtual void clientToScreen( - * GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; + * int32_t inX, int32_t inY, int32_t& outX, int32_t& outY) const = 0; * virtual GHOST_TWindowState getState() const = 0; * virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0; * virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0; @@ -126,8 +126,8 @@ class GHOST_Window : public GHOST_IWindow { * \param hotY: The Y coordinate of the cursor hot-spot. * \return Indication of success. */ - GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -142,9 +142,9 @@ class GHOST_Window : public GHOST_IWindow { inline GHOST_TGrabCursorMode getCursorGrabMode() const; inline bool getCursorGrabModeIsWarp() const; inline GHOST_TAxisFlag getCursorGrabAxis() const; - inline void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const; - inline void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const; - inline void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y); + inline void getCursorGrabInitPos(int32_t &x, int32_t &y) const; + inline void getCursorGrabAccum(int32_t &x, int32_t &y) const; + inline void setCursorGrabAccum(int32_t x, int32_t y); /** * Shows or hides the cursor. @@ -161,7 +161,7 @@ class GHOST_Window : public GHOST_IWindow { GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_TAxisFlag wrap_axis, GHOST_Rect *bounds, - GHOST_TInt32 mouse_ungrab_xy[2]); + int32_t mouse_ungrab_xy[2]); /** * Gets the cursor grab region, if unset the window is used. @@ -292,14 +292,13 @@ class GHOST_Window : public GHOST_IWindow { * Returns the recommended DPI for this window. * \return The recommended DPI for this window. */ - virtual inline GHOST_TUns16 getDPIHint() + virtual inline uint16_t getDPIHint() { return 96; } #ifdef WITH_INPUT_IME - virtual void beginIME( - GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed) + virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) { /* do nothing temporarily if not in windows */ } @@ -343,8 +342,8 @@ class GHOST_Window : public GHOST_IWindow { * Sets the cursor shape on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + virtual GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int szx, int szy, int hotX, @@ -369,10 +368,10 @@ class GHOST_Window : public GHOST_IWindow { GHOST_TAxisFlag m_cursorGrabAxis; /** Initial grab location. */ - GHOST_TInt32 m_cursorGrabInitPos[2]; + int32_t m_cursorGrabInitPos[2]; /** Accumulated offset from m_cursorGrabInitPos. */ - GHOST_TInt32 m_cursorGrabAccumPos[2]; + int32_t m_cursorGrabAccumPos[2]; /** Wrap the cursor within this region. */ GHOST_Rect m_cursorGrabBounds; @@ -396,9 +395,9 @@ class GHOST_Window : public GHOST_IWindow { bool m_wantStereoVisual; /** Full-screen width */ - GHOST_TUns32 m_fullScreenWidth; + uint32_t m_fullScreenWidth; /** Full-screen height */ - GHOST_TUns32 m_fullScreenHeight; + uint32_t m_fullScreenHeight; /* OSX only, retina screens */ float m_nativePixelSize; @@ -432,19 +431,19 @@ inline GHOST_TAxisFlag GHOST_Window::getCursorGrabAxis() const return m_cursorGrabAxis; } -inline void GHOST_Window::getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const +inline void GHOST_Window::getCursorGrabInitPos(int32_t &x, int32_t &y) const { x = m_cursorGrabInitPos[0]; y = m_cursorGrabInitPos[1]; } -inline void GHOST_Window::getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const +inline void GHOST_Window::getCursorGrabAccum(int32_t &x, int32_t &y) const { x = m_cursorGrabAccumPos[0]; y = m_cursorGrabAccumPos[1]; } -inline void GHOST_Window::setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y) +inline void GHOST_Window::setCursorGrabAccum(int32_t x, int32_t y) { m_cursorGrabAccumPos[0] = x; m_cursorGrabAccumPos[1] = y; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 3cfe46a080b..0fd70514ac6 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -29,6 +29,9 @@ #endif // __APPLE__ #include "GHOST_Window.h" +#ifdef WITH_INPUT_IME +# include "GHOST_Event.h" +#endif @class CAMetalLayer; @class CocoaMetalView; @@ -57,10 +60,10 @@ class GHOST_WindowCocoa : public GHOST_Window { */ GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 bottom, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t bottom, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, const bool stereoVisual = false, @@ -116,20 +119,20 @@ class GHOST_WindowCocoa : public GHOST_Window { * Resizes client rectangle width. * \param width: The new width of the client area of the window. */ - GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + GHOST_TSuccess setClientWidth(uint32_t width); /** * Resizes client rectangle height. * \param height: The new height of the client area of the window. */ - GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + GHOST_TSuccess setClientHeight(uint32_t height); /** * Resizes client rectangle. * \param width: The new width of the client area of the window. * \param height: The new height of the client area of the window. */ - GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + GHOST_TSuccess setClientSize(uint32_t width, uint32_t height); /** * Returns the state of the window (normal, minimized, maximized). @@ -151,10 +154,7 @@ class GHOST_WindowCocoa : public GHOST_Window { * \param outX: The x-coordinate in the client rectangle. * \param outY: The y-coordinate in the client rectangle. */ - void screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates @@ -163,10 +163,7 @@ class GHOST_WindowCocoa : public GHOST_Window { * \param outX: The x-coordinate on the screen. * \param outY: The y-coordinate on the screen. */ - void clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates @@ -176,10 +173,7 @@ class GHOST_WindowCocoa : public GHOST_Window { * \param outX: The x-coordinate on the screen. * \param outY: The y-coordinate on the screen. */ - void clientToScreenIntern(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void clientToScreenIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates, @@ -189,10 +183,7 @@ class GHOST_WindowCocoa : public GHOST_Window { * \param outX: The x-coordinate on the screen. * \param outY: The y-coordinate on the screen. */ - void screenToClientIntern(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void screenToClientIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; /** * Gets the screen the window is displayed in @@ -263,6 +254,11 @@ class GHOST_WindowCocoa : public GHOST_Window { return m_immediateDraw; } +#ifdef WITH_INPUT_IME + void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed); + void endIME(); +#endif /* WITH_INPUT_IME */ + protected: /** * \param type: The type of rendering context create. @@ -299,8 +295,8 @@ class GHOST_WindowCocoa : public GHOST_Window { * Sets the cursor shape on the window using * native window system calls. */ - GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -326,3 +322,30 @@ class GHOST_WindowCocoa : public GHOST_Window { bool m_debug_context; // for debug messages during context setup bool m_is_dialog; }; + +#ifdef WITH_INPUT_IME +class GHOST_EventIME : public GHOST_Event { + public: + /** + * Constructor. + * \param msec: The time this event was generated. + * \param type: The type of key event. + * \param key: The key code of the key. + */ + GHOST_EventIME(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata) + : GHOST_Event(msec, type, window) + { + this->m_data = customdata; + } +}; + +typedef int GHOST_ImeStateFlagCocoa; +enum { + GHOST_IME_INPUT_FOCUSED = (1 << 0), + GHOST_IME_ENABLED = (1 << 1), + GHOST_IME_COMPOSING = (1 << 2), + GHOST_IME_KEY_CONTROL_CHAR = (1 << 3), + GHOST_IME_COMPOSITION_EVENT = (1 << 4), // For Korean input + GHOST_IME_RESULT_EVENT = (1 << 5) // For Korean input +}; +#endif /* WITH_INPUT_IME */ diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index d082fa99ad8..0c3b3062126 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -284,10 +284,10 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 bottom, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t bottom, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, @@ -570,13 +570,13 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect &bounds) const [pool drain]; } -GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) +GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(uint32_t width) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); - if (((GHOST_TUns32)cBnds.getWidth()) != width) { + if (((uint32_t)cBnds.getWidth()) != width) { NSSize size; size.width = width; size.height = cBnds.getHeight(); @@ -586,13 +586,13 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) return GHOST_kSuccess; } -GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(uint32_t height) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); - if (((GHOST_TUns32)cBnds.getHeight()) != height) { + if (((uint32_t)cBnds.getHeight()) != height) { NSSize size; size.width = cBnds.getWidth(); size.height = height; @@ -602,14 +602,13 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) return GHOST_kSuccess; } -GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowCocoa::setClientSize(uint32_t width, uint32_t height) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); - if ((((GHOST_TUns32)cBnds.getWidth()) != width) || - (((GHOST_TUns32)cBnds.getHeight()) != height)) { + if ((((uint32_t)cBnds.getWidth()) != width) || (((uint32_t)cBnds.getHeight()) != height)) { NSSize size; size.width = width; size.height = height; @@ -654,10 +653,10 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const return state; } -void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowCocoa::screenToClient(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid"); @@ -669,10 +668,10 @@ void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, outY = (cBnds.getHeight() - 1) - outY; } -void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowCocoa::clientToScreen(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid"); @@ -684,10 +683,10 @@ void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, clientToScreenIntern(inX, inY, outX, outY); } -void GHOST_WindowCocoa::screenToClientIntern(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowCocoa::screenToClientIntern(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { NSRect screenCoord; NSRect baseCoord; @@ -701,10 +700,10 @@ void GHOST_WindowCocoa::screenToClientIntern(GHOST_TInt32 inX, outY = baseCoord.origin.y; } -void GHOST_WindowCocoa::clientToScreenIntern(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowCocoa::clientToScreenIntern(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { NSRect screenCoord; NSRect baseCoord; @@ -1127,9 +1126,9 @@ GHOST_TSuccess GHOST_WindowCocoa::hasCursorShape(GHOST_TStandardCursor shape) return success; } -/* Reverse the bits in a GHOST_TUns8 */ +/* Reverse the bits in a uint8_t */ #if 0 -static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) +static uint8_t uns8ReverseBits(uint8_t ch) { ch= ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA); ch= ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC); @@ -1138,8 +1137,8 @@ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) } #endif -/** Reverse the bits in a GHOST_TUns16 */ -static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) +/** Reverse the bits in a uint16_t */ +static uint16_t uns16ReverseBits(uint16_t shrt) { shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA); shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC); @@ -1148,20 +1147,15 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) return shrt; } -GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, - int sizex, - int sizey, - int hotX, - int hotY, - bool canInvertColor) +GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape( + uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) { int y, nbUns16; NSPoint hotSpotPoint; NSBitmapImageRep *cursorImageRep; NSImage *cursorImage; NSSize imSize; - GHOST_TUns16 *cursorBitmap; + uint16_t *cursorBitmap; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -1182,7 +1176,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap bytesPerRow:(sizex / 8 + (sizex % 8 > 0 ? 1 : 0)) bitsPerPixel:1]; - cursorBitmap = (GHOST_TUns16 *)[cursorImageRep bitmapData]; + cursorBitmap = (uint16_t *)[cursorImageRep bitmapData]; nbUns16 = [cursorImageRep bytesPerPlane] / 2; for (y = 0; y < nbUns16; y++) { @@ -1221,3 +1215,25 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap [pool drain]; return GHOST_kSuccess; } + +#ifdef WITH_INPUT_IME +void GHOST_WindowCocoa::beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) +{ + if (m_openGLView) { + [m_openGLView beginIME:x y:y w:w h:h completed:completed]; + } + else { + [m_metalView beginIME:x y:y w:w h:h completed:completed]; + } +} + +void GHOST_WindowCocoa::endIME() +{ + if (m_openGLView) { + [m_openGLView endIME]; + } + else { + [m_metalView endIME]; + } +} +#endif /* WITH_INPUT_IME */ diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index aca06ba75b5..a3f9e2f0a13 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -36,10 +36,10 @@ class GHOST_WindowNULL : public GHOST_Window { GHOST_WindowNULL(GHOST_SystemNULL *system, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, const GHOST_IWindow *parentWindow, GHOST_TDrawingContextType type, @@ -66,8 +66,8 @@ class GHOST_WindowNULL : public GHOST_Window { { return GHOST_kSuccess; } - GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -95,30 +95,24 @@ class GHOST_WindowNULL : public GHOST_Window { void getClientBounds(GHOST_Rect &bounds) const { /* nothing */ } - GHOST_TSuccess setClientWidth(GHOST_TUns32 width) + GHOST_TSuccess setClientWidth(uint32_t width) { return GHOST_kFailure; } - GHOST_TSuccess setClientHeight(GHOST_TUns32 height) + GHOST_TSuccess setClientHeight(uint32_t height) { return GHOST_kFailure; } - GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) + GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) { return GHOST_kFailure; } - void screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const + void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const { outX = inX; outY = inY; } - void clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const + void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const { outX = inX; outY = inY; diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index ff0c506feb7..fa1fcee2911 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -28,10 +28,10 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, @@ -175,7 +175,7 @@ void GHOST_WindowSDL::getClientBounds(GHOST_Rect &bounds) const bounds.m_b = y + h; } -GHOST_TSuccess GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width) +GHOST_TSuccess GHOST_WindowSDL::setClientWidth(uint32_t width) { int height; SDL_GetWindowSize(m_sdl_win, NULL, &height); @@ -183,7 +183,7 @@ GHOST_TSuccess GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width) return GHOST_kSuccess; } -GHOST_TSuccess GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowSDL::setClientHeight(uint32_t height) { int width; SDL_GetWindowSize(m_sdl_win, &width, NULL); @@ -191,16 +191,13 @@ GHOST_TSuccess GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height) return GHOST_kSuccess; } -GHOST_TSuccess GHOST_WindowSDL::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowSDL::setClientSize(uint32_t width, uint32_t height) { SDL_SetWindowSize(m_sdl_win, width, height); return GHOST_kSuccess; } -void GHOST_WindowSDL::screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowSDL::screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const { /* XXXSDL_WEAK_ABS_COORDS */ int x_win, y_win; @@ -209,10 +206,7 @@ void GHOST_WindowSDL::screenToClient(GHOST_TInt32 inX, outX = inX - x_win; outY = inY - y_win; } -void GHOST_WindowSDL::clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowSDL::clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const { /* XXXSDL_WEAK_ABS_COORDS */ int x_win, y_win; @@ -556,7 +550,7 @@ static SDL_Cursor *sdl_ghost_CreateCursor( return cursor; } -/* TODO, this is currently never freed but it won't leak either. */ +/* TODO: this is currently never freed but it won't leak either. */ static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape) { if (sdl_std_cursor_array[0] == NULL) { @@ -576,7 +570,7 @@ static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape) DEF_CURSOR(left_ptr, GHOST_kStandardCursorDefault); DEF_CURSOR(right_ptr, GHOST_kStandardCursorRightArrow); DEF_CURSOR(left_ptr, GHOST_kStandardCursorLeftArrow); - DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); // TODO, replace this one. + DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); /* TODO: replace this one. */ DEF_CURSOR(pirate, GHOST_kStandardCursorDestroy); DEF_CURSOR(question_arrow, GHOST_kStandardCursorHelp); DEF_CURSOR(watch, GHOST_kStandardCursorWait); @@ -622,13 +616,8 @@ GHOST_TSuccess GHOST_WindowSDL::hasCursorShape(GHOST_TStandardCursor shape) return (getStandardCursorShape(shape)) ? GHOST_kSuccess : GHOST_kFailure; } -GHOST_TSuccess GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, - int sizex, - int sizey, - int hotX, - int hotY, - bool canInvertColor) +GHOST_TSuccess GHOST_WindowSDL::setWindowCustomCursorShape( + uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) { if (m_sdl_custom_cursor) { SDL_FreeCursor(m_sdl_custom_cursor); @@ -647,7 +636,7 @@ GHOST_TSuccess GHOST_WindowSDL::setWindowCursorVisibility(bool visible) return GHOST_kSuccess; } -GHOST_TUns16 GHOST_WindowSDL::getDPIHint() +uint16_t GHOST_WindowSDL::getDPIHint() { int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win); if (displayIndex < 0) { diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h index bfe07af1c70..d2eedecc506 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.h +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -48,10 +48,10 @@ class GHOST_WindowSDL : public GHOST_Window { public: GHOST_WindowSDL(GHOST_SystemSDL *system, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, const bool stereoVisual = false, @@ -95,8 +95,8 @@ class GHOST_WindowSDL : public GHOST_Window { GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor shape); - GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -109,21 +109,15 @@ class GHOST_WindowSDL : public GHOST_Window { std::string getTitle() const; - GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + GHOST_TSuccess setClientWidth(uint32_t width); - GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + GHOST_TSuccess setClientHeight(uint32_t height); - GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + GHOST_TSuccess setClientSize(uint32_t width, uint32_t height); - void screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; - void clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; GHOST_TSuccess setState(GHOST_TWindowState state); @@ -146,5 +140,5 @@ class GHOST_WindowSDL : public GHOST_Window { return GHOST_kFailure; } - GHOST_TUns16 getDPIHint(); + uint16_t getDPIHint(); }; diff --git a/intern/ghost/intern/GHOST_WindowViewCocoa.h b/intern/ghost/intern/GHOST_WindowViewCocoa.h index f47e02704b2..fa629528809 100644 --- a/intern/ghost/intern/GHOST_WindowViewCocoa.h +++ b/intern/ghost/intern/GHOST_WindowViewCocoa.h @@ -17,6 +17,11 @@ * All rights reserved. */ +/* The Carbon API is still needed to check if the Input Source (Input Method or IME) is valid. */ +#ifdef WITH_INPUT_IME +# import <Carbon/Carbon.h> +#endif + /* NSView subclass for drawing and handling input. * * COCOA_VIEW_BASE_CLASS will be either NSView or NSOpenGLView depending if @@ -25,7 +30,7 @@ * Objective-C does not have multiple inheritance. */ // We need to subclass it in order to give Cocoa the feeling key events are trapped -@interface COCOA_VIEW_CLASS : COCOA_VIEW_BASE_CLASS <NSTextInput> +@interface COCOA_VIEW_CLASS : COCOA_VIEW_BASE_CLASS <NSTextInputClient> { GHOST_SystemCocoa *systemCocoa; GHOST_WindowCocoa *associatedWindow; @@ -33,10 +38,27 @@ bool composing; NSString *composing_text; - bool immediate_draw; +#ifdef WITH_INPUT_IME + struct { + GHOST_ImeStateFlagCocoa state_flag; + NSRect candidate_window_position; + + /* Event data. */ + GHOST_TEventImeData event; + std::string result; + std::string composite; + std::string combined_result; + } ime; +#endif } - (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; + +#ifdef WITH_INPUT_IME +- (void)beginIME:(int32_t)x y:(int32_t)y w:(int32_t)w h:(int32_t)h completed:(bool)completed; + +- (void)endIME; +#endif @end @implementation COCOA_VIEW_CLASS @@ -50,7 +72,21 @@ composing = false; composing_text = nil; - immediate_draw = false; +#ifdef WITH_INPUT_IME + ime.state_flag = 0; + ime.candidate_window_position = NSZeroRect; + ime.event.cursor_position = -1; + ime.event.target_start = -1; + ime.event.target_end = -1; + + /* Register a function to be executed when Input Method is changed using + * 'Control + Space' or language-specific keys (such as 'Eisu / Kana' key for Japanese).*/ + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(ImeDidChangeCallback:) + name:NSTextInputContextKeyboardSelectionDidChangeNotification + object:nil]; +#endif } - (BOOL)acceptsFirstResponder @@ -66,20 +102,38 @@ // The trick to prevent Cocoa from complaining (beeping) - (void)keyDown:(NSEvent *)event { - systemCocoa->handleKeyEvent(event); +#ifdef WITH_INPUT_IME + [self checkKeyCodeIsControlChar:event]; + const bool ime_process = [self isProcessedByIme]; +#else + const bool ime_process = false; +#endif + + if (!ime_process) { + systemCocoa->handleKeyEvent(event); + } /* Start or continue composing? */ if ([[event characters] length] == 0 || [[event charactersIgnoringModifiers] length] == 0 || - composing) { + composing || ime_process) { composing = YES; // interpret event to call insertText - NSMutableArray *events; - events = [[NSMutableArray alloc] initWithCapacity:1]; - [events addObject:event]; - [self interpretKeyEvents:events]; // calls insertText - [events removeObject:event]; - [events release]; + [self interpretKeyEvents:[NSArray arrayWithObject:event]]; // calls insertText + +#ifdef WITH_INPUT_IME + // For Korean input, control characters are also processed by handleKeyEvent. + const int controlCharForKorean = (GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT | + GHOST_IME_KEY_CONTROL_CHAR); + if (((ime.state_flag & controlCharForKorean) == controlCharForKorean)) { + systemCocoa->handleKeyEvent(event); + } + + ime.state_flag &= ~(GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT); + + ime.combined_result.clear(); +#endif + return; } } @@ -207,24 +261,90 @@ } } -- (void)insertText:(id)chars +// Processes the Result String sent from the Input Method. +- (void)insertText:(id)chars replacementRange:(NSRange)replacementRange { [self composing_free]; + +#ifdef WITH_INPUT_IME + if (ime.state_flag & GHOST_IME_ENABLED) { + if (!(ime.state_flag & GHOST_IME_COMPOSING)) { + [self processImeEvent:GHOST_kEventImeCompositionStart]; + } + + // For Chinese and Korean input, insertText may be executed twice with a single keyDown. + if (ime.state_flag & GHOST_IME_RESULT_EVENT) { + ime.combined_result += [self convertNSString:chars]; + } + else { + ime.combined_result = [self convertNSString:chars]; + } + + [self setImeResult:ime.combined_result]; + + /* For Korean input, both "Result Event" and "Composition Event" + * can occur in a single keyDown. */ + if (![self ime_did_composition]) { + [self processImeEvent:GHOST_kEventImeComposition]; + } + ime.state_flag |= GHOST_IME_RESULT_EVENT; + + [self processImeEvent:GHOST_kEventImeCompositionEnd]; + ime.state_flag &= ~GHOST_IME_COMPOSING; + } +#endif } -- (void)setMarkedText:(id)chars selectedRange:(NSRange)range +// Processes the Composition String sent from the Input Method. +- (void)setMarkedText:(id)chars + selectedRange:(NSRange)range + replacementRange:(NSRange)replacementRange { [self composing_free]; - if ([chars length] == 0) + + if ([chars length] == 0) { +#ifdef WITH_INPUT_IME + // Processes when the last Composition String is deleted. + if (ime.state_flag & GHOST_IME_COMPOSING) { + [self setImeResult:std::string()]; + [self processImeEvent:GHOST_kEventImeComposition]; + [self processImeEvent:GHOST_kEventImeCompositionEnd]; + ime.state_flag &= ~GHOST_IME_COMPOSING; + } +#endif + return; + } // start composing composing = YES; composing_text = [chars copy]; + // chars of markedText by Input Method is an instance of NSAttributedString + if ([chars isKindOfClass:[NSAttributedString class]]) { + composing_text = [[chars string] copy]; + } + // if empty, cancel if ([composing_text length] == 0) [self composing_free]; + +#ifdef WITH_INPUT_IME + if (ime.state_flag & GHOST_IME_ENABLED) { + if (!(ime.state_flag & GHOST_IME_COMPOSING)) { + ime.state_flag |= GHOST_IME_COMPOSING; + [self processImeEvent:GHOST_kEventImeCompositionStart]; + } + + [self setImeComposition:composing_text selectedRange:range]; + + // For Korean input, setMarkedText may be executed twice with a single keyDown. + if (![self ime_did_composition]) { + ime.state_flag |= GHOST_IME_COMPOSITION_EVENT; + [self processImeEvent:GHOST_kEventImeComposition]; + } + } +#endif } - (void)unmarkText @@ -246,12 +366,8 @@ return composing; } -- (NSInteger)conversationIdentifier -{ - return (NSInteger)self; -} - -- (NSAttributedString *)attributedSubstringFromRange:(NSRange)range +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range + actualRange:(NSRangePointer)actualRange { return [[[NSAttributedString alloc] init] autorelease]; } @@ -272,8 +388,14 @@ return NSMakeRange(0, length); } -- (NSRect)firstRectForCharacterRange:(NSRange)range +// Specify the position where the Chinese and Japanese candidate windows are displayed. +- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange { +#ifdef WITH_INPUT_IME + if (ime.state_flag & GHOST_IME_ENABLED) { + return ime.candidate_window_position; + } +#endif return NSZeroRect; } @@ -287,4 +409,165 @@ return [NSArray array]; } +#ifdef WITH_INPUT_IME +- (void)checkImeEnabled +{ + ime.state_flag &= ~GHOST_IME_ENABLED; + + if (ime.state_flag & GHOST_IME_INPUT_FOCUSED) { + /* Since there are no functions in Cocoa API, + * we will use the functions in the Carbon API. */ + TISInputSourceRef currentKeyboardInputSource = TISCopyCurrentKeyboardInputSource(); + bool ime_enabled = !CFBooleanGetValue((CFBooleanRef)TISGetInputSourceProperty( + currentKeyboardInputSource, kTISPropertyInputSourceIsASCIICapable)); + CFRelease(currentKeyboardInputSource); + + if (ime_enabled) { + ime.state_flag |= GHOST_IME_ENABLED; + return; + } + } + return; +} + +- (void)ImeDidChangeCallback:(NSNotification *)notification +{ + [self checkImeEnabled]; +} + +- (void)setImeCandidateWinPos:(int32_t)x y:(int32_t)y w:(int32_t)w h:(int32_t)h +{ + int32_t outX, outY; + associatedWindow->clientToScreen(x, y, outX, outY); + ime.candidate_window_position = NSMakeRect((CGFloat)outX, (CGFloat)outY, (CGFloat)w, (CGFloat)h); +} + +- (void)beginIME:(int32_t)x y:(int32_t)y w:(int32_t)w h:(int32_t)h completed:(bool)completed +{ + ime.state_flag |= GHOST_IME_INPUT_FOCUSED; + [self checkImeEnabled]; + [self setImeCandidateWinPos:x y:y w:w h:h]; +} + +- (void)endIME +{ + ime.state_flag = 0; + ime.result.clear(); + ime.composite.clear(); + + [self unmarkText]; + [[NSTextInputContext currentInputContext] discardMarkedText]; +} + +- (void)processImeEvent:(GHOST_TEventType)imeEventType +{ + ime.event.result_len = (GHOST_TUserDataPtr)ime.result.size(); + ime.event.result = (GHOST_TUserDataPtr)ime.result.c_str(); + ime.event.composite_len = (GHOST_TUserDataPtr)ime.composite.size(); + ime.event.composite = (GHOST_TUserDataPtr)ime.composite.c_str(); + + GHOST_Event *event = new GHOST_EventIME( + systemCocoa->getMilliSeconds(), imeEventType, associatedWindow, &ime.event); + systemCocoa->pushEvent(event); +} + +- (std::string)convertNSString:(NSString *)inString +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + std::string str([inString UTF8String]); + [pool drain]; + return str; +} + +- (void)setImeComposition:(NSString *)inString selectedRange:(NSRange)range +{ + ime.composite = [self convertNSString:inString]; + + // For Korean input, both "Result Event" and "Composition Event" can occur in a single keyDown. + if (!(ime.state_flag & GHOST_IME_RESULT_EVENT)) { + ime.result.clear(); + } + + /* The target string is equivalent to the string in selectedRange of setMarkedText. + * The cursor is displayed at the beginning of the target string. */ + char *front_string = (char *)[[inString substringWithRange:NSMakeRange(0, range.location)] + UTF8String]; + char *selected_string = (char *)[[inString substringWithRange:range] UTF8String]; + ime.event.cursor_position = strlen(front_string); + ime.event.target_start = ime.event.cursor_position; + ime.event.target_end = ime.event.target_start + strlen(selected_string); +} + +- (void)setImeResult:(std::string)result +{ + ime.result = result; + ime.composite.clear(); + ime.event.cursor_position = -1; + ime.event.target_start = -1; + ime.event.target_end = -1; +} + +- (void)checkKeyCodeIsControlChar:(NSEvent *)event +{ + ime.state_flag &= ~GHOST_IME_KEY_CONTROL_CHAR; + switch ([event keyCode]) { + case kVK_ANSI_KeypadEnter: + case kVK_ANSI_KeypadClear: + case kVK_F1: + case kVK_F2: + case kVK_F3: + case kVK_F4: + case kVK_F5: + case kVK_F6: + case kVK_F7: + case kVK_F8: + case kVK_F9: + case kVK_F10: + case kVK_F11: + case kVK_F12: + case kVK_F13: + case kVK_F14: + case kVK_F15: + case kVK_F16: + case kVK_F17: + case kVK_F18: + case kVK_F19: + case kVK_F20: + case kVK_UpArrow: + case kVK_DownArrow: + case kVK_LeftArrow: + case kVK_RightArrow: + case kVK_Return: + case kVK_Delete: + case kVK_ForwardDelete: + case kVK_Escape: + case kVK_Tab: + case kVK_Home: + case kVK_End: + case kVK_PageUp: + case kVK_PageDown: + case kVK_VolumeUp: + case kVK_VolumeDown: + case kVK_Mute: + ime.state_flag |= GHOST_IME_KEY_CONTROL_CHAR; + return; + } +} + +- (bool)ime_did_composition +{ + return (ime.state_flag & GHOST_IME_COMPOSITION_EVENT) || + (ime.state_flag & GHOST_IME_RESULT_EVENT); +} + +/* Even if IME is enabled, when not composing, control characters + * (such as arrow, enter, delete) are handled by handleKeyEvent. */ +- (bool)isProcessedByIme +{ + return ( + (ime.state_flag & GHOST_IME_ENABLED) && + ((ime.state_flag & GHOST_IME_COMPOSING) || !(ime.state_flag & GHOST_IME_KEY_CONTROL_CHAR))); +} +#endif /* WITH_INPUT_IME */ + @end diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 5be7724fd86..d0c8cfb9e73 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -36,7 +36,7 @@ struct window_t { wl_surface *surface; // outputs on which the window is currently shown on std::unordered_set<const output_t *> outputs; - GHOST_TUns16 dpi = 0; + uint16_t dpi = 0; int scale = 1; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; @@ -205,10 +205,10 @@ GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorS GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, const char *title, - GHOST_TInt32 /*left*/, - GHOST_TInt32 /*top*/, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t /*left*/, + int32_t /*top*/, + uint32_t width, + uint32_t height, GHOST_TWindowState state, const GHOST_IWindow *parentWindow, GHOST_TDrawingContextType type, @@ -344,13 +344,8 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor s return ok; } -GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, - int sizex, - int sizey, - int hotX, - int hotY, - bool canInvertColor) +GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape( + uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) { return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor); } @@ -377,35 +372,35 @@ void GHOST_WindowWayland::getClientBounds(GHOST_Rect &bounds) const bounds.set(0, 0, w->width, w->height); } -GHOST_TSuccess GHOST_WindowWayland::setClientWidth(GHOST_TUns32 width) +GHOST_TSuccess GHOST_WindowWayland::setClientWidth(uint32_t width) { - return setClientSize(width, GHOST_TUns32(w->height)); + return setClientSize(width, uint32_t(w->height)); } -GHOST_TSuccess GHOST_WindowWayland::setClientHeight(GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowWayland::setClientHeight(uint32_t height) { - return setClientSize(GHOST_TUns32(w->width), height); + return setClientSize(uint32_t(w->width), height); } -GHOST_TSuccess GHOST_WindowWayland::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowWayland::setClientSize(uint32_t width, uint32_t height) { wl_egl_window_resize(w->egl_window, int(width), int(height), 0, 0); return GHOST_kSuccess; } -void GHOST_WindowWayland::screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowWayland::screenToClient(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { outX = inX; outY = inY; } -void GHOST_WindowWayland::clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowWayland::clientToScreen(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { outX = inX; outY = inY; @@ -426,7 +421,7 @@ GHOST_WindowWayland::~GHOST_WindowWayland() delete w; } -GHOST_TUns16 GHOST_WindowWayland::getDPIHint() +uint16_t GHOST_WindowWayland::getDPIHint() { return w->dpi; } diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index dbddc7c469e..afbdf1268ee 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -29,9 +29,9 @@ class GHOST_SystemWayland; +struct output_t; struct window_t; struct wl_surface; -struct output_t; class GHOST_WindowWayland : public GHOST_Window { public: @@ -39,10 +39,10 @@ class GHOST_WindowWayland : public GHOST_Window { GHOST_WindowWayland(GHOST_SystemWayland *system, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, const GHOST_IWindow *parentWindow, GHOST_TDrawingContextType type, @@ -52,7 +52,7 @@ class GHOST_WindowWayland : public GHOST_Window { ~GHOST_WindowWayland() override; - GHOST_TUns16 getDPIHint() override; + uint16_t getDPIHint() override; GHOST_TSuccess close(); @@ -77,8 +77,8 @@ class GHOST_WindowWayland : public GHOST_Window { GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override; - GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -93,21 +93,15 @@ class GHOST_WindowWayland : public GHOST_Window { void getClientBounds(GHOST_Rect &bounds) const override; - GHOST_TSuccess setClientWidth(GHOST_TUns32 width) override; + GHOST_TSuccess setClientWidth(uint32_t width) override; - GHOST_TSuccess setClientHeight(GHOST_TUns32 height) override; + GHOST_TSuccess setClientHeight(uint32_t height) override; - GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) override; + GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) override; - void screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const override; + void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override; - void clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const override; + void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override; GHOST_TSuccess setWindowCursorVisibility(bool visible) override; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 1b73b765b49..b5d0fd8e6db 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -56,10 +56,10 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, bool wantStereoVisual, @@ -306,9 +306,13 @@ void GHOST_WindowWin32::setTitle(const char *title) std::string GHOST_WindowWin32::getTitle() const { - char buf[s_maxTitleLength]; /* CHANGE + never used yet. */ - ::GetWindowText(m_hWnd, buf, s_maxTitleLength); - return std::string(buf); + std::wstring wtitle(::GetWindowTextLengthW(m_hWnd) + 1, L'\0'); + ::GetWindowTextW(m_hWnd, &wtitle[0], wtitle.capacity()); + + std::string title(count_utf_8_from_16(wtitle.c_str()) + 1, '\0'); + conv_utf_16_to_8(wtitle.c_str(), &title[0], title.capacity()); + + return title; } void GHOST_WindowWin32::getWindowBounds(GHOST_Rect &bounds) const @@ -350,12 +354,12 @@ void GHOST_WindowWin32::getClientBounds(GHOST_Rect &bounds) const } } -GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width) +GHOST_TSuccess GHOST_WindowWin32::setClientWidth(uint32_t width) { GHOST_TSuccess success; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); - if (cBnds.getWidth() != (GHOST_TInt32)width) { + if (cBnds.getWidth() != (int32_t)width) { getWindowBounds(wBnds); int cx = wBnds.getWidth() + width - cBnds.getWidth(); int cy = wBnds.getHeight(); @@ -369,12 +373,12 @@ GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width) return success; } -GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowWin32::setClientHeight(uint32_t height) { GHOST_TSuccess success; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); - if (cBnds.getHeight() != (GHOST_TInt32)height) { + if (cBnds.getHeight() != (int32_t)height) { getWindowBounds(wBnds); int cx = wBnds.getWidth(); int cy = wBnds.getHeight() + height - cBnds.getHeight(); @@ -388,12 +392,12 @@ GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height) return success; } -GHOST_TSuccess GHOST_WindowWin32::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowWin32::setClientSize(uint32_t width, uint32_t height) { GHOST_TSuccess success; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); - if ((cBnds.getWidth() != (GHOST_TInt32)width) || (cBnds.getHeight() != (GHOST_TInt32)height)) { + if ((cBnds.getWidth() != (int32_t)width) || (cBnds.getHeight() != (int32_t)height)) { getWindowBounds(wBnds); int cx = wBnds.getWidth() + width - cBnds.getWidth(); int cy = wBnds.getHeight() + height - cBnds.getHeight(); @@ -419,10 +423,10 @@ GHOST_TWindowState GHOST_WindowWin32::getState() const return GHOST_kWindowStateNormal; } -void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowWin32::screenToClient(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { POINT point = {inX, inY}; ::ScreenToClient(m_hWnd, &point); @@ -430,10 +434,10 @@ void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, outY = point.y; } -void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowWin32::clientToScreen(int32_t inX, + int32_t inY, + int32_t &outX, + int32_t &outY) const { POINT point = {inX, inY}; ::ClientToScreen(m_hWnd, &point); @@ -662,7 +666,7 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const // Convert GHOST cursor to Windows OEM cursor HANDLE cursor = NULL; HMODULE module = ::GetModuleHandle(0); - GHOST_TUns32 flags = LR_SHARED | LR_DEFAULTSIZE; + uint32_t flags = LR_SHARED | LR_DEFAULTSIZE; int cx = 0, cy = 0; switch (shape) { @@ -831,7 +835,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode /* use to generate a mouse move event, otherwise the last event * blender gets can be outside the screen causing menus not to show * properly unless the user moves the mouse */ - GHOST_TInt32 pos[2]; + int32_t pos[2]; m_system->getCursorPosition(pos[0], pos[1]); m_system->setCursorPosition(pos[0], pos[1]); } @@ -863,10 +867,10 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam) { - GHOST_TInt32 pointerId = GET_POINTERID_WPARAM(wParam); - GHOST_TInt32 isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam); + int32_t pointerId = GET_POINTERID_WPARAM(wParam); + int32_t isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam); GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem(); - GHOST_TUns32 outCount = 0; + uint32_t outCount = 0; if (!(GetPointerPenInfoHistory(pointerId, &outCount, NULL))) { return GHOST_kFailure; @@ -879,7 +883,7 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( return GHOST_kFailure; } - for (GHOST_TUns32 i = 0; i < outCount; i++) { + for (uint32_t i = 0; i < outCount; i++) { POINTER_INFO pointerApiInfo = pointerPenInfo[i].pointerInfo; // Obtain the basic information from the event outPointerInfo[i].pointerId = pointerId; @@ -960,7 +964,7 @@ void GHOST_WindowWin32::loadWintab(bool enable) /* Focus Wintab if cursor is inside this window. This ensures Wintab is enabled when the * tablet is used to change the Tablet API. */ - GHOST_TInt32 x, y; + int32_t x, y; if (m_system->getCursorPosition(x, y)) { GHOST_Rect rect; getClientBounds(rect); @@ -1008,7 +1012,7 @@ GHOST_TabletData GHOST_WindowWin32::getTabletData() } } -GHOST_TUns16 GHOST_WindowWin32::getDPIHint() +uint16_t GHOST_WindowWin32::getDPIHint() { if (m_user32) { GHOST_WIN32_GetDpiForWindow fpGetDpiForWindow = (GHOST_WIN32_GetDpiForWindow)::GetProcAddress( @@ -1022,8 +1026,8 @@ GHOST_TUns16 GHOST_WindowWin32::getDPIHint() return USER_DEFAULT_SCREEN_DPI; } -/** Reverse the bits in a GHOST_TUns8 */ -static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) +/** Reverse the bits in a uint8_t */ +static uint8_t uns8ReverseBits(uint8_t ch) { ch = ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA); ch = ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC); @@ -1032,8 +1036,8 @@ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) } #if 0 /* UNUSED */ -/** Reverse the bits in a GHOST_TUns16 */ -static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) +/** Reverse the bits in a uint16_t */ +static uint16_t uns16ReverseBits(uint16_t shrt) { shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA); shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC); @@ -1043,17 +1047,12 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) } #endif -GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, - int sizeX, - int sizeY, - int hotX, - int hotY, - bool canInvertColor) +GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape( + uint8_t *bitmap, uint8_t *mask, int sizeX, int sizeY, int hotX, int hotY, bool canInvertColor) { - GHOST_TUns32 andData[32]; - GHOST_TUns32 xorData[32]; - GHOST_TUns32 fullBitRow, fullMaskRow; + uint32_t andData[32]; + uint32_t xorData[32]; + uint32_t fullBitRow, fullMaskRow; int x, y, cols; cols = sizeX / 8; /* Number of whole bytes per row (width of bitmap/mask). */ @@ -1111,10 +1110,9 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar() } #ifdef WITH_INPUT_IME -void GHOST_WindowWin32::beginIME( - GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed) +void GHOST_WindowWin32::beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) { - m_imeInput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), (bool)completed); + m_imeInput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), completed); } void GHOST_WindowWin32::endIME() diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 119092a001a..40a658bf88b 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -47,11 +47,11 @@ typedef BOOL(API *GHOST_WIN32_AdjustWindowRectExForDpi)( LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi); struct GHOST_PointerInfoWin32 { - GHOST_TInt32 pointerId; - GHOST_TInt32 isPrimary; + int32_t pointerId; + int32_t isPrimary; GHOST_TButtonMask buttonMask; POINT pixelLocation; - GHOST_TUns64 time; + uint64_t time; GHOST_TabletData tabletData; }; @@ -83,10 +83,10 @@ class GHOST_WindowWin32 : public GHOST_Window { */ GHOST_WindowWin32(GHOST_SystemWin32 *system, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, bool wantStereoVisual = false, @@ -152,20 +152,20 @@ class GHOST_WindowWin32 : public GHOST_Window { * Resizes client rectangle width. * \param width: The new width of the client area of the window. */ - GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + GHOST_TSuccess setClientWidth(uint32_t width); /** * Resizes client rectangle height. * \param height: The new height of the client area of the window. */ - GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + GHOST_TSuccess setClientHeight(uint32_t height); /** * Resizes client rectangle. * \param width: The new width of the client area of the window. * \param height: The new height of the client area of the window. */ - GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + GHOST_TSuccess setClientSize(uint32_t width, uint32_t height); /** * Returns the state of the window (normal, minimized, maximized). @@ -180,10 +180,7 @@ class GHOST_WindowWin32 : public GHOST_Window { * \param outX: The x-coordinate in the client rectangle. * \param outY: The y-coordinate in the client rectangle. */ - void screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates @@ -192,10 +189,7 @@ class GHOST_WindowWin32 : public GHOST_Window { * \param outX: The x-coordinate on the screen. * \param outY: The y-coordinate on the screen. */ - void clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; /** * Sets the state of the window (normal, minimized, maximized). @@ -309,7 +303,7 @@ class GHOST_WindowWin32 : public GHOST_Window { return GHOST_kFailure; } - GHOST_TUns16 getDPIHint() override; + uint16_t getDPIHint() override; /** True if the mouse is either over or captured by the window. */ bool m_mousePresent; @@ -323,7 +317,7 @@ class GHOST_WindowWin32 : public GHOST_Window { return &m_imeInput; } - void beginIME(GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed); + void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed); void endIME(); #endif /* WITH_INPUT_IME */ @@ -359,8 +353,8 @@ class GHOST_WindowWin32 : public GHOST_Window { * Sets the cursor shape on the window using * native window system calls. */ - GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index ea798441adb..0ade7a52891 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -213,10 +213,10 @@ static XVisualInfo *x11_visualinfo_from_glx(Display *display, GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_WindowX11 *parentWindow, GHOST_TDrawingContextType type, @@ -622,7 +622,7 @@ void GHOST_WindowX11::getClientBounds(GHOST_Rect &bounds) const Window root_return; int x_return, y_return; unsigned int w_return, h_return, border_w_return, depth_return; - GHOST_TInt32 screen_x, screen_y; + int32_t screen_x, screen_y; XGetGeometry(m_display, m_window, @@ -642,7 +642,7 @@ void GHOST_WindowX11::getClientBounds(GHOST_Rect &bounds) const bounds.m_b = bounds.m_t + h_return; } -GHOST_TSuccess GHOST_WindowX11::setClientWidth(GHOST_TUns32 width) +GHOST_TSuccess GHOST_WindowX11::setClientWidth(uint32_t width) { XWindowChanges values; unsigned int value_mask = CWWidth; @@ -652,7 +652,7 @@ GHOST_TSuccess GHOST_WindowX11::setClientWidth(GHOST_TUns32 width) return GHOST_kSuccess; } -GHOST_TSuccess GHOST_WindowX11::setClientHeight(GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowX11::setClientHeight(uint32_t height) { XWindowChanges values; unsigned int value_mask = CWHeight; @@ -661,7 +661,7 @@ GHOST_TSuccess GHOST_WindowX11::setClientHeight(GHOST_TUns32 height) return GHOST_kSuccess; } -GHOST_TSuccess GHOST_WindowX11::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +GHOST_TSuccess GHOST_WindowX11::setClientSize(uint32_t width, uint32_t height) { XWindowChanges values; unsigned int value_mask = CWWidth | CWHeight; @@ -671,10 +671,7 @@ GHOST_TSuccess GHOST_WindowX11::setClientSize(GHOST_TUns32 width, GHOST_TUns32 h return GHOST_kSuccess; } -void GHOST_WindowX11::screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowX11::screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const { /* This is correct! */ @@ -687,10 +684,7 @@ void GHOST_WindowX11::screenToClient(GHOST_TInt32 inX, outY = ay; } -void GHOST_WindowX11::clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const +void GHOST_WindowX11::clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const { int ax, ay; Window temp; @@ -1590,8 +1584,8 @@ GHOST_TSuccess GHOST_WindowX11::hasCursorShape(GHOST_TStandardCursor shape) return getStandardCursor(shape, xcursor); } -GHOST_TSuccess GHOST_WindowX11::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, +GHOST_TSuccess GHOST_WindowX11::setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, @@ -1679,7 +1673,7 @@ GHOST_TSuccess GHOST_WindowX11::endFullScreen() const return GHOST_kSuccess; } -GHOST_TUns16 GHOST_WindowX11::getDPIHint() +uint16_t GHOST_WindowX11::getDPIHint() { /* Try to read DPI setting set using xrdb */ char *resMan = XResourceManagerString(m_display); diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 01699e9d1ce..9f3d48dfafc 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -68,10 +68,10 @@ class GHOST_WindowX11 : public GHOST_Window { GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, + int32_t left, + int32_t top, + uint32_t width, + uint32_t height, GHOST_TWindowState state, GHOST_WindowX11 *parentWindow, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, @@ -93,21 +93,15 @@ class GHOST_WindowX11 : public GHOST_Window { bool isDialog() const; - GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + GHOST_TSuccess setClientWidth(uint32_t width); - GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + GHOST_TSuccess setClientHeight(uint32_t height); - GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + GHOST_TSuccess setClientSize(uint32_t width, uint32_t height); - void screenToClient(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; - void clientToScreen(GHOST_TInt32 inX, - GHOST_TInt32 inY, - GHOST_TInt32 &outX, - GHOST_TInt32 &outY) const; + void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const; GHOST_TWindowState getState() const; @@ -182,7 +176,7 @@ class GHOST_WindowX11 : public GHOST_Window { GHOST_TSuccess setDialogHints(GHOST_WindowX11 *parentWindow); - GHOST_TUns16 getDPIHint(); + uint16_t getDPIHint(); protected: /** @@ -216,8 +210,8 @@ class GHOST_WindowX11 : public GHOST_Window { * Sets the cursor shape on the window using * native window system calls (Arbitrary size/color). */ - GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, - GHOST_TUns8 *mask, + GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, + uint8_t *mask, int sizex, int sizey, int hotX, diff --git a/intern/ghost/intern/GHOST_Wintab.h b/intern/ghost/intern/GHOST_Wintab.h index 75017aa67d9..443c726d270 100644 --- a/intern/ghost/intern/GHOST_Wintab.h +++ b/intern/ghost/intern/GHOST_Wintab.h @@ -56,10 +56,10 @@ typedef std::unique_ptr<std::remove_pointer_t<HMODULE>, decltype(&::FreeLibrary) typedef std::unique_ptr<std::remove_pointer_t<HCTX>, GHOST_WIN32_WTClose> unique_hctx; struct GHOST_WintabInfoWin32 { - GHOST_TInt32 x, y; + int32_t x, y; GHOST_TEventType type; GHOST_TButtonMask button; - GHOST_TUns64 time; + uint64_t time; GHOST_TabletData tabletData; }; @@ -178,7 +178,7 @@ class GHOST_Wintab { bool m_focused = false; /** Pressed button map. */ - GHOST_TUns8 m_buttons = 0; + uint8_t m_buttons = 0; /** Range of a coordinate space. */ struct Range { diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp index b10e001df47..9c4f7fbc7d8 100644 --- a/intern/ghost/intern/GHOST_XrAction.cpp +++ b/intern/ghost/intern/GHOST_XrAction.cpp @@ -329,7 +329,7 @@ void GHOST_XrAction::updateState(XrSession session, void GHOST_XrAction::applyHapticFeedback(XrSession session, const char *action_name, - const GHOST_TInt64 &duration, + const int64_t &duration, const float &frequency, const float &litude) { diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h index bdc6cafb4a9..32445c616bd 100644 --- a/intern/ghost/intern/GHOST_XrAction.h +++ b/intern/ghost/intern/GHOST_XrAction.h @@ -91,7 +91,7 @@ class GHOST_XrAction { const XrTime &predicted_display_time); void applyHapticFeedback(XrSession session, const char *action_name, - const GHOST_TInt64 &duration, + const int64_t &duration, const float &frequency, const float &litude); void stopHapticFeedback(XrSession session, const char *action_name); diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index a7438fae13c..35280e77e22 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -772,7 +772,7 @@ bool GHOST_XrSession::syncActions(const char *action_set_name) bool GHOST_XrSession::applyHapticAction(const char *action_set_name, const char *action_name, - const GHOST_TInt64 &duration, + const int64_t &duration, const float &frequency, const float &litude) { diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h index a2d3cf2e385..c871b98da46 100644 --- a/intern/ghost/intern/GHOST_XrSession.h +++ b/intern/ghost/intern/GHOST_XrSession.h @@ -81,7 +81,7 @@ class GHOST_XrSession { bool syncActions(const char *action_set_name = nullptr); bool applyHapticAction(const char *action_set_name, const char *action_name, - const GHOST_TInt64 &duration, + const int64_t &duration, const float &frequency, const float &litude); void stopHapticAction(const char *action_set_name, const char *action_name); diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c index 8cd1b5acb89..3257c42118e 100644 --- a/intern/ghost/test/gears/GHOST_C-Test.c +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -46,7 +46,7 @@ # include <GL/gl.h> #endif /* defined(WIN32) || defined(__APPLE__) */ -static void gearsTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time); +static void gearsTimerProc(GHOST_TimerTaskHandle task, uint64_t time); int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData); static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; @@ -60,7 +60,7 @@ static GHOST_WindowHandle sFullScreenWindow = NULL; static GHOST_TimerTaskHandle sTestTimer; static GHOST_TimerTaskHandle sGearsTimer; -static void testTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) +static void testTimerProc(GHOST_TimerTaskHandle task, uint64_t time) { printf("timer1, time=%d\n", (int)time); } @@ -274,7 +274,7 @@ static void setViewPortGL(GHOST_WindowHandle hWindow) glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-w, w, -h, h, 5.0, 60.0); - /* glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10); */ + // glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -40.0); @@ -501,7 +501,7 @@ int main(int argc, char **argv) return 0; } -static void gearsTimerProc(GHOST_TimerTaskHandle hTask, GHOST_TUns64 time) +static void gearsTimerProc(GHOST_TimerTaskHandle hTask, uint64_t time) { GHOST_WindowHandle hWindow = NULL; fAngle += 2.0; diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index c9c497aacb4..c1cb5f29e2e 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -54,7 +54,7 @@ static bool nVidiaWindows; // very dirty but hey, it's for testing only -static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 time); +static void gearsTimerProc(GHOST_ITimerTask *task, uint64_t time); static class Application *fApp; static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; @@ -71,7 +71,7 @@ void StereoProjection(float left, float dist, float eye); -static void testTimerProc(GHOST_ITimerTask * /*task*/, GHOST_TUns64 time) +static void testTimerProc(GHOST_ITimerTask * /*task*/, uint64_t time) { std::cout << "timer1, time=" << (int)time << "\n"; } @@ -345,7 +345,7 @@ void StereoProjection(float left, float zero_plane, float dist, float eye) -/* Perform the perspective projection for one eye's subfield. +/* Perform the perspective projection for one eye's sub-field. * The projection is in the direction of the negative z axis. * * -6.0, 6.0, -4.8, 4.8, @@ -365,8 +365,8 @@ void StereoProjection(float left, * of zero parallax. * * -0.31 - * eye = half the eye separation; positive for the right eye subfield, - * negative for the left eye subfield. + * eye = half the eye separation; positive for the right eye sub-field, + * negative for the left eye sub-field. */ { float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw, dx, dy, n_over_d; @@ -392,8 +392,7 @@ void StereoProjection(float left, glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far); glTranslatef(-xmid - eye, -ymid, -zero_plane - dist); - return; -} /* stereoproj */ +} class Application : public GHOST_IEventConsumer { public: @@ -731,7 +730,7 @@ int main(int /*argc*/, char ** /*argv*/) return 0; } -static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 /*time*/) +static void gearsTimerProc(GHOST_ITimerTask *task, uint64_t /*time*/) { fAngle += 2.0; view_roty += 1.0; diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c index 788c0221753..44ea07bd880 100644 --- a/intern/ghost/test/multitest/EventToBuf.c +++ b/intern/ghost/test/multitest/EventToBuf.c @@ -203,7 +203,7 @@ static char *keytype_to_string(GHOST_TKey key) void event_to_buf(GHOST_EventHandle evt, char buf[128]) { GHOST_TEventType type = GHOST_GetEventType(evt); - double time = (double)((GHOST_TInt64)GHOST_GetEventTime(evt)) / 1000; + double time = (double)((int64_t)GHOST_GetEventTime(evt)) / 1000; GHOST_WindowHandle win = GHOST_GetEventWindow(evt); void *data = GHOST_GetEventData(evt); char *pos = buf; diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index ccbbbceb5b6..0e6602d9510 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -302,12 +302,12 @@ static void mainwindow_handle(void *priv, GHOST_EventHandle evt) /**/ -static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) +static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, uint64_t time) { MainWindow *mw = GHOST_GetTimerTaskUserData(task); char buf[64]; - sprintf(buf, "timer: %6.2f", (double)((GHOST_TInt64)time) / 1000); + sprintf(buf, "timer: %6.2f", (double)((int64_t)time) / 1000); mainwindow_log(mw, buf); } @@ -570,7 +570,7 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app) { GHOST_GLSettings glSettings = {0}; GHOST_SystemHandle sys = multitestapp_get_system(app); - GHOST_TUns32 screensize[2]; + uint32_t screensize[2]; GHOST_WindowHandle win; GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]); @@ -701,11 +701,11 @@ static void extrawindow_do_key(ExtraWindow *ew, GHOST_TKey key, int press) } } -static void extrawindow_spin_cursor(ExtraWindow *ew, GHOST_TUns64 time) +static void extrawindow_spin_cursor(ExtraWindow *ew, uint64_t time) { - GHOST_TUns8 bitmap[16][2]; - GHOST_TUns8 mask[16][2]; - double ftime = (double)((GHOST_TInt64)time) / 1000; + uint8_t bitmap[16][2]; + uint8_t mask[16][2]; + double ftime = (double)((int64_t)time) / 1000; float angle = fmod(ftime, 1.0) * 3.1415 * 2; int i; diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h index aa956150484..e4bd3d533a3 100644 --- a/intern/guardedalloc/intern/mallocn_intern.h +++ b/intern/guardedalloc/intern/mallocn_intern.h @@ -53,14 +53,8 @@ size_t malloc_usable_size(void *ptr); # undef USE_MALLOC_USABLE_SIZE #endif -/* Blame Microsoft for LLP64 and no inttypes.h, quick workaround needed: */ -#if defined(WIN64) -# define SIZET_FORMAT "%I64u" -# define SIZET_ARG(a) ((unsigned long long)(a)) -#else -# define SIZET_FORMAT "%lu" -# define SIZET_ARG(a) ((unsigned long)(a)) -#endif +#define SIZET_FORMAT "%zu" +#define SIZET_ARG(a) ((size_t)(a)) #define SIZET_ALIGN_4(len) ((len + 3) & ~(size_t)3) diff --git a/intern/libmv/libmv/numeric/numeric.h b/intern/libmv/libmv/numeric/numeric.h index e3d44226338..e3ebdb5a4bb 100644 --- a/intern/libmv/libmv/numeric/numeric.h +++ b/intern/libmv/libmv/numeric/numeric.h @@ -43,7 +43,7 @@ inline void sincos(double x, double* sinx, double* cosx) { # endif #endif // !__MINGW64__ -#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__) +#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) inline long lround(double d) { return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5)); } diff --git a/intern/libmv/libmv/tracking/retrack_region_tracker.cc b/intern/libmv/libmv/tracking/retrack_region_tracker.cc index 9152078053c..124a032cdff 100644 --- a/intern/libmv/libmv/tracking/retrack_region_tracker.cc +++ b/intern/libmv/libmv/tracking/retrack_region_tracker.cc @@ -37,7 +37,7 @@ bool RetrackRegionTracker::Track(const FloatImage& image1, } // Now track x2 and y2 backward, to get xx1 and yy1 which, if the track is // good, should match x1 and y1 (but may not if the track is bad). - double xx1 = *x2, yy1 = *x2; + double xx1 = *x2, yy1 = *y2; if (!tracker_->Track(image2, image1, *x2, *y2, &xx1, &yy1)) { return false; } diff --git a/intern/numaapi/source/build_config.h b/intern/numaapi/source/build_config.h index fdd6ff704c3..49d82aa3e87 100644 --- a/intern/numaapi/source/build_config.h +++ b/intern/numaapi/source/build_config.h @@ -324,6 +324,16 @@ # define ARCH_CPU_ARM64 1 # define ARCH_CPU_64_BITS 1 # define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__riscv) && __riscv_xlen == 32 +# define ARCH_CPU_RISCV_FAMILY 1 +# define ARCH_CPU_RISCV32 1 +# define ARCH_CPU_64_BITS 0 +# define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__riscv) && __riscv_xlen == 64 +# define ARCH_CPU_RISCV_FAMILY 1 +# define ARCH_CPU_RISCV64 1 +# define ARCH_CPU_64_BITS 1 +# define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__) # define ARCH_CPU_32_BITS 1 # define ARCH_CPU_LITTLE_ENDIAN 1 @@ -381,6 +391,9 @@ #if !defined(ARCH_CPU_PPC64_FAMILY) # define ARCH_CPU_PPC64_FAMILY 0 #endif +#if !defined(ARCH_CPU_RISCV_FAMILY) +# define ARCH_CPU_RISCV_FAMILY 0 +#endif #if !defined(ARCH_CPU_S390_FAMILY) # define ARCH_CPU_S390_FAMILY 0 #endif diff --git a/release/scripts/freestyle/modules/freestyle/shaders.py b/release/scripts/freestyle/modules/freestyle/shaders.py index 28b8aa9b23e..95e1c873657 100644 --- a/release/scripts/freestyle/modules/freestyle/shaders.py +++ b/release/scripts/freestyle/modules/freestyle/shaders.py @@ -1153,11 +1153,9 @@ class RoundCapShader(StrokeShader): return # calculate the number of additional vertices to form caps thickness_beg = sum(stroke[0].attribute.thickness) - caplen_beg = thickness_beg / 2.0 nverts_beg = max(5, int(thickness_beg)) thickness_end = sum(stroke[-1].attribute.thickness) - caplen_end = (thickness_end) / 2.0 nverts_end = max(5, int(thickness_end)) # adjust the total number of stroke vertices @@ -1169,7 +1167,7 @@ class RoundCapShader(StrokeShader): # reshape the cap at the beginning of the stroke q, attr = buffer[1] p, attr = buffer[0] - direction = (p - q).normalized() * caplen_beg + direction = (p - q).normalized() * thickness_beg n = 1.0 / nverts_beg R, L = attr.thickness for t, svert in zip(range(nverts_beg, 0, -1), stroke): @@ -1180,7 +1178,7 @@ class RoundCapShader(StrokeShader): # reshape the cap at the end of the stroke q, attr = buffer[-2] p, attr = buffer[-1] - direction = (p - q).normalized() * caplen_beg + direction = (p - q).normalized() * thickness_end n = 1.0 / nverts_end R, L = attr.thickness for t, svert in zip(range(nverts_end, 0, -1), reversed(stroke)): diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py index f63b6990cdd..fda93682dc5 100644 --- a/release/scripts/modules/bl_i18n_utils/utils.py +++ b/release/scripts/modules/bl_i18n_utils/utils.py @@ -781,7 +781,6 @@ class I18nMessages: print("Could not import bpy, find_best_messages_matches must be run from whithin Blender.") return - # Build helper mappings. # Note it's user responsibility to know when to invalidate (and hence force rebuild) this cache! if self._reverse_cache is None: diff --git a/release/scripts/modules/bl_i18n_utils/utils_cli.py b/release/scripts/modules/bl_i18n_utils/utils_cli.py index d3750d5e9a4..e18491fa042 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_cli.py +++ b/release/scripts/modules/bl_i18n_utils/utils_cli.py @@ -140,6 +140,7 @@ def main(): args.func(args=args, settings=settings) + if __name__ == "__main__": print("\n\n *** Running {} *** \n".format(__file__)) main() diff --git a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py index aff1108568b..26f38cf09fc 100644 --- a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py +++ b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py @@ -449,6 +449,5 @@ def generate(context, space_type, *, use_fallback_keys=True, use_reset=True): ) kmi.properties.skip_depressed = True - wm.keyconfigs.update() return keymap diff --git a/release/scripts/modules/bl_previews_utils/bl_previews_render.py b/release/scripts/modules/bl_previews_utils/bl_previews_render.py index 51ea53c0eba..17577a9a9f2 100644 --- a/release/scripts/modules/bl_previews_utils/bl_previews_render.py +++ b/release/scripts/modules/bl_previews_utils/bl_previews_render.py @@ -37,6 +37,7 @@ OBJECT_TYPES_RENDER = {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'} def ids_nolib(bids): return (bid for bid in bids if not bid.library) + def ids_nolib_with_preview(bids): return (bid for bid in bids if (not bid.library and bid.preview)) diff --git a/release/scripts/modules/bl_rna_utils/data_path.py b/release/scripts/modules/bl_rna_utils/data_path.py index 42942b7a295..439dfcae12a 100644 --- a/release/scripts/modules/bl_rna_utils/data_path.py +++ b/release/scripts/modules/bl_rna_utils/data_path.py @@ -23,6 +23,7 @@ __all__ = ( "decompose_data_path", ) + class _TokenizeDataPath: """ Class to split up tokens of a data-path. diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index e6c7bca3e3c..58b20d9e3c8 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -155,6 +155,7 @@ def _test_import(module_name, loaded_modules): # This supports the case of loading a new preferences file which may reset scripts path. _sys_path_ensure_paths = set() + def _sys_path_ensure_prepend(path): if path not in _sys.path: _sys.path.insert(0, path) diff --git a/release/scripts/modules/bpy_extras/asset_utils.py b/release/scripts/modules/bpy_extras/asset_utils.py index 1656c21a137..2cd5dddefbc 100644 --- a/release/scripts/modules/bpy_extras/asset_utils.py +++ b/release/scripts/modules/bpy_extras/asset_utils.py @@ -31,6 +31,7 @@ __all__ = ( "SpaceAssetInfo", ) + class SpaceAssetInfo: @classmethod def is_asset_browser(cls, space_data: bpy.types.Space): @@ -46,6 +47,7 @@ class SpaceAssetInfo: active_file = context.active_file return active_file.asset_data if active_file else None + class AssetBrowserPanel: bl_space_type = 'FILE_BROWSER' @@ -53,6 +55,18 @@ class AssetBrowserPanel: def poll(cls, context): return SpaceAssetInfo.is_asset_browser_poll(context) + +class AssetBrowserSpecificCategoryPanel(AssetBrowserPanel): + asset_categories = set() # Set of strings like 'ANIMATIONS', see `asset_category_items` in rna_space.c + + @classmethod + def poll(cls, context): + return ( + SpaceAssetInfo.is_asset_browser_poll(context) + and context.space_data.params.asset_category in cls.asset_categories + ) + + class AssetMetaDataPanel: bl_space_type = 'FILE_BROWSER' bl_region_type = 'TOOL_PROPS' diff --git a/release/scripts/modules/bpy_extras/node_shader_utils.py b/release/scripts/modules/bpy_extras/node_shader_utils.py index 54124fd4ca6..e37c1a17152 100644 --- a/release/scripts/modules/bpy_extras/node_shader_utils.py +++ b/release/scripts/modules/bpy_extras/node_shader_utils.py @@ -681,7 +681,10 @@ class ShaderImageTextureWrapper(): tree = self.owner_shader.material.node_tree node_image = tree.nodes.new(type='ShaderNodeTexImage') - self.owner_shader._grid_to_location(-1, 0 + self.grid_row_diff, dst_node=node_image, ref_node=self.node_dst) + self.owner_shader._grid_to_location( + -1, 0 + self.grid_row_diff, + dst_node=node_image, ref_node=self.node_dst, + ) tree.links.new(node_image.outputs["Alpha" if self.use_alpha else "Color"], self.socket_dst) if self.use_alpha: @@ -778,7 +781,7 @@ class ShaderImageTextureWrapper(): socket_dst = self.node_image.inputs["Vector"] # If not already existing, we need to create texcoords -> mapping link (from UV). socket_src = (socket_dst.links[0].from_socket if socket_dst.is_linked - else self.owner_shader.node_texcoords.outputs['UV']) + else self.owner_shader.node_texcoords.outputs['UV']) tree = self.owner_shader.material.node_tree node_mapping = tree.nodes.new(type='ShaderNodeMapping') diff --git a/release/scripts/modules/console/complete_calltip.py b/release/scripts/modules/console/complete_calltip.py index 706af67905b..60daa1d2045 100644 --- a/release/scripts/modules/console/complete_calltip.py +++ b/release/scripts/modules/console/complete_calltip.py @@ -41,7 +41,7 @@ RE_DEF_COMPLETE = re.compile( # allow empty string '''|)''' # allow opening bracket(s) - '''(?:\(|\s)*)$''') + r'''(?:\(|\s)*)$''') def reduce_newlines(text): diff --git a/release/scripts/presets/camera/1_inch.py b/release/scripts/presets/camera/1_inch.py index 72b039fb978..97e87b8c5a7 100644 --- a/release/scripts/presets/camera/1_inch.py +++ b/release/scripts/presets/camera/1_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 13.2 bpy.context.camera.sensor_height = 8.80 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/1_slash_1.8_inch.py b/release/scripts/presets/camera/1_slash_1.8_inch.py index 38e09182de6..8b0dc3cea1d 100644 --- a/release/scripts/presets/camera/1_slash_1.8_inch.py +++ b/release/scripts/presets/camera/1_slash_1.8_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 7.18 bpy.context.camera.sensor_height = 5.32 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/1_slash_2.3_inch.py b/release/scripts/presets/camera/1_slash_2.3_inch.py index 4d55738f4ed..bd6808da082 100644 --- a/release/scripts/presets/camera/1_slash_2.3_inch.py +++ b/release/scripts/presets/camera/1_slash_2.3_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 6.17 bpy.context.camera.sensor_height = 4.55 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/1_slash_2.5_inch.py b/release/scripts/presets/camera/1_slash_2.5_inch.py index cbdb6f3cbe0..90f60e7d7f0 100644 --- a/release/scripts/presets/camera/1_slash_2.5_inch.py +++ b/release/scripts/presets/camera/1_slash_2.5_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 5.76 bpy.context.camera.sensor_height = 4.29 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/1_slash_2.7_inch.py b/release/scripts/presets/camera/1_slash_2.7_inch.py index 5ccfa4ab555..4a9591803d0 100644 --- a/release/scripts/presets/camera/1_slash_2.7_inch.py +++ b/release/scripts/presets/camera/1_slash_2.7_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 5.37 bpy.context.camera.sensor_height = 4.04 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/1_slash_3.2_inch.py b/release/scripts/presets/camera/1_slash_3.2_inch.py index 1963f7ec048..5f31b9ec49c 100644 --- a/release/scripts/presets/camera/1_slash_3.2_inch.py +++ b/release/scripts/presets/camera/1_slash_3.2_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 4.54 bpy.context.camera.sensor_height = 3.42 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/2_slash_3_inch.py b/release/scripts/presets/camera/2_slash_3_inch.py index 25b46016800..eb463a31af7 100644 --- a/release/scripts/presets/camera/2_slash_3_inch.py +++ b/release/scripts/presets/camera/2_slash_3_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 8.8 bpy.context.camera.sensor_height = 6.6 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/APS-C.py b/release/scripts/presets/camera/APS-C.py index 84e40825248..4031e8bae71 100644 --- a/release/scripts/presets/camera/APS-C.py +++ b/release/scripts/presets/camera/APS-C.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 23.6 bpy.context.camera.sensor_height = 15.6 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/APS-C_(Canon).py b/release/scripts/presets/camera/APS-C_(Canon).py index 55f20ce0eac..484929a54e7 100644 --- a/release/scripts/presets/camera/APS-C_(Canon).py +++ b/release/scripts/presets/camera/APS-C_(Canon).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 22.30 bpy.context.camera.sensor_height = 14.90 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/APS-H_(Canon).py b/release/scripts/presets/camera/APS-H_(Canon).py index d63f733280b..d3b61d1aa46 100644 --- a/release/scripts/presets/camera/APS-H_(Canon).py +++ b/release/scripts/presets/camera/APS-H_(Canon).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 27.90 bpy.context.camera.sensor_height = 18.60 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Analog_16mm.py b/release/scripts/presets/camera/Analog_16mm.py index aa98eaf2408..a290839c8e0 100644 --- a/release/scripts/presets/camera/Analog_16mm.py +++ b/release/scripts/presets/camera/Analog_16mm.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 10.26 bpy.context.camera.sensor_height = 7.49 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Analog_35mm.py b/release/scripts/presets/camera/Analog_35mm.py index a0dee1f0166..fe3338dd292 100644 --- a/release/scripts/presets/camera/Analog_35mm.py +++ b/release/scripts/presets/camera/Analog_35mm.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 22 bpy.context.camera.sensor_height = 16 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Analog_65mm.py b/release/scripts/presets/camera/Analog_65mm.py index 8de91ac0ee3..d6eb9c32283 100644 --- a/release/scripts/presets/camera/Analog_65mm.py +++ b/release/scripts/presets/camera/Analog_65mm.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 52.45 bpy.context.camera.sensor_height = 23.01 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Analog_IMAX.py b/release/scripts/presets/camera/Analog_IMAX.py index 5a445f3de8c..b71b910dee0 100644 --- a/release/scripts/presets/camera/Analog_IMAX.py +++ b/release/scripts/presets/camera/Analog_IMAX.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 71.41 bpy.context.camera.sensor_height = 52.63 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Analog_Super_16.py b/release/scripts/presets/camera/Analog_Super_16.py index a340a31dc25..f76238c69d3 100644 --- a/release/scripts/presets/camera/Analog_Super_16.py +++ b/release/scripts/presets/camera/Analog_Super_16.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 12.35 bpy.context.camera.sensor_height = 7.42 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Analog_Super_35.py b/release/scripts/presets/camera/Analog_Super_35.py index 3c8f1837253..b22ff545c68 100644 --- a/release/scripts/presets/camera/Analog_Super_35.py +++ b/release/scripts/presets/camera/Analog_Super_35.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 24.89 bpy.context.camera.sensor_height = 18.66 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Arri_Alexa_65.py b/release/scripts/presets/camera/Arri_Alexa_65.py index b1467709949..24d03e022ae 100644 --- a/release/scripts/presets/camera/Arri_Alexa_65.py +++ b/release/scripts/presets/camera/Arri_Alexa_65.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 54.12 bpy.context.camera.sensor_height = 25.58 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Arri_Alexa_LF.py b/release/scripts/presets/camera/Arri_Alexa_LF.py index 1cde94fce8d..430fdc996a6 100644 --- a/release/scripts/presets/camera/Arri_Alexa_LF.py +++ b/release/scripts/presets/camera/Arri_Alexa_LF.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 36.70 bpy.context.camera.sensor_height = 25.54 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py b/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py index 0f61d35a0f9..90998bc0da0 100644 --- a/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py +++ b/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 29.90 bpy.context.camera.sensor_height = 15.77 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py b/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py index 260bfbaf94f..bb2b172919e 100644 --- a/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py +++ b/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 12.48 bpy.context.camera.sensor_height = 7.02 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Blackmagic_Pocket_4K.py b/release/scripts/presets/camera/Blackmagic_Pocket_4K.py index dc057397828..4b735283c8b 100644 --- a/release/scripts/presets/camera/Blackmagic_Pocket_4K.py +++ b/release/scripts/presets/camera/Blackmagic_Pocket_4K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 18.96 bpy.context.camera.sensor_height = 10.00 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Blackmagic_Pocket_6k.py b/release/scripts/presets/camera/Blackmagic_Pocket_6k.py index a483f3d5f98..1a882f05786 100644 --- a/release/scripts/presets/camera/Blackmagic_Pocket_6k.py +++ b/release/scripts/presets/camera/Blackmagic_Pocket_6k.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 23.10 bpy.context.camera.sensor_height = 12.99 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py b/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py index c71e42d72d3..767d16984d8 100644 --- a/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py +++ b/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 25.34 bpy.context.camera.sensor_height = 14.25 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Foveon_(Sigma).py b/release/scripts/presets/camera/Foveon_(Sigma).py index e6a1a0ed344..6b35f29acaf 100644 --- a/release/scripts/presets/camera/Foveon_(Sigma).py +++ b/release/scripts/presets/camera/Foveon_(Sigma).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 20.70 bpy.context.camera.sensor_height = 13.80 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Fullframe.py b/release/scripts/presets/camera/Fullframe.py index 95fb4afc10b..c8017331b28 100644 --- a/release/scripts/presets/camera/Fullframe.py +++ b/release/scripts/presets/camera/Fullframe.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 36 bpy.context.camera.sensor_height = 24 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/MFT.py b/release/scripts/presets/camera/MFT.py index bc0dd49baa8..7441f1aea76 100644 --- a/release/scripts/presets/camera/MFT.py +++ b/release/scripts/presets/camera/MFT.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 17.3 bpy.context.camera.sensor_height = 13.0 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/Medium-format_(Hasselblad).py b/release/scripts/presets/camera/Medium-format_(Hasselblad).py index e9b16024b79..d03a4f22db7 100644 --- a/release/scripts/presets/camera/Medium-format_(Hasselblad).py +++ b/release/scripts/presets/camera/Medium-format_(Hasselblad).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 44 bpy.context.camera.sensor_height = 33 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/RED_Dragon_5K.py b/release/scripts/presets/camera/RED_Dragon_5K.py index fa95a98f8c4..e8b990d4d00 100644 --- a/release/scripts/presets/camera/RED_Dragon_5K.py +++ b/release/scripts/presets/camera/RED_Dragon_5K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 25.60 bpy.context.camera.sensor_height = 13.5 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/RED_Dragon_6K.py b/release/scripts/presets/camera/RED_Dragon_6K.py index 80f7ad1bbb8..982e2ab8e00 100644 --- a/release/scripts/presets/camera/RED_Dragon_6K.py +++ b/release/scripts/presets/camera/RED_Dragon_6K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 30.70 bpy.context.camera.sensor_height = 15.80 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/RED_Helium_8K.py b/release/scripts/presets/camera/RED_Helium_8K.py index 0f61d35a0f9..90998bc0da0 100644 --- a/release/scripts/presets/camera/RED_Helium_8K.py +++ b/release/scripts/presets/camera/RED_Helium_8K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 29.90 bpy.context.camera.sensor_height = 15.77 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/camera/RED_Monstro_8K.py b/release/scripts/presets/camera/RED_Monstro_8K.py index 86c382624ab..1c8bc11dfaa 100644 --- a/release/scripts/presets/camera/RED_Monstro_8K.py +++ b/release/scripts/presets/camera/RED_Monstro_8K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 40.96 bpy.context.camera.sensor_height = 21.60 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/keyconfig/Blender.py b/release/scripts/presets/keyconfig/Blender.py index 222ee43432f..eb66c961472 100644 --- a/release/scripts/presets/keyconfig/Blender.py +++ b/release/scripts/presets/keyconfig/Blender.py @@ -103,8 +103,8 @@ class Prefs(bpy.types.KeyConfigPreferences): v3d_tilde_action: EnumProperty( name="Tilde Action", items=( - ('OBJECT_SWITCH', "Object Switch", - "Switch the active object under the cursor (when not in object mode)", + ('VIEW', "Navigate", + "View operations (useful for keyboards without a numpad)", 0), ('GIZMO', "Gizmos", "Control transform gizmos", @@ -113,7 +113,7 @@ class Prefs(bpy.types.KeyConfigPreferences): description=( "Action when 'Tilde' is pressed" ), - default='OBJECT_SWITCH', + default='VIEW', update=update_fn, ) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 7f1039a975b..3527e993173 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -730,6 +730,8 @@ def km_user_interface(_params): ("anim.keyingset_button_add", {"type": 'K', "value": 'PRESS'}, None), ("anim.keyingset_button_remove", {"type": 'K', "value": 'PRESS', "alt": True}, None), ("ui.reset_default_button", {"type": 'BACK_SPACE', "value": 'PRESS'}, {"properties": [("all", True)]}), + # UI lists (polls check if there's a UI list under the cursor). + ("ui.list_start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None), ]) return keymap @@ -1084,7 +1086,13 @@ def km_view3d(params): {"properties": [("use_all_regions", True), ("center", False)]}), ("view3d.view_all", {"type": 'C', "value": 'PRESS', "shift": True}, {"properties": [("center", True)]}), - op_menu_pie("VIEW3D_MT_view_pie", {"type": 'D', "value": 'CLICK_DRAG'}), + op_menu_pie( + "VIEW3D_MT_view_pie" if params.v3d_tilde_action == 'VIEW' else "VIEW3D_MT_transform_gizmo_pie", + {"type": 'ACCENT_GRAVE', "value": params.pie_value}, + ), + *(() if not params.use_pie_click_drag else + (("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'CLICK'}, None),)), + ("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "shift": True}, None), ("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "shift": True}, None), # Numpad views. ("view3d.view_camera", {"type": 'NUMPAD_0', "value": 'PRESS'}, None), @@ -1328,32 +1336,6 @@ def km_view3d(params): op_tool_cycle("builtin.select_box", {"type": 'W', "value": 'PRESS'}), ]) - # Tilda key. - if params.use_pie_click_drag: - items.extend([ - ("object.transfer_mode", - {"type": 'ACCENT_GRAVE', "value": 'CLICK' if params.use_pie_click_drag else 'PRESS'}, - None), - op_menu_pie( - "VIEW3D_MT_transform_gizmo_pie", - {"type": 'ACCENT_GRAVE', "value": 'CLICK_DRAG'}, - ) - ]) - else: - if params.v3d_tilde_action == 'OBJECT_SWITCH': - items.append( - ("object.transfer_mode", - {"type": 'ACCENT_GRAVE', "value": 'PRESS'}, - {"properties": [("use_eyedropper", False)]}) - ) - else: - items.append( - op_menu_pie( - "VIEW3D_MT_transform_gizmo_pie", - {"type": 'ACCENT_GRAVE', "value": 'PRESS'}, - ) - ) - return keymap @@ -2679,7 +2661,8 @@ def km_sequencer(params): {"properties": [("side", 'LEFT')]}), ("sequencer.select_side_of_frame", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, {"properties": [("side", 'RIGHT')]}), - + ("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True}, + {"properties": [("data_path", 'tool_settings.use_snap_sequencer')]}), *_template_items_context_menu("SEQUENCER_MT_context_menu", params.context_menu_event), ]) @@ -4113,7 +4096,7 @@ def km_pose(params): ("pose.bone_layers", {"type": 'M', "value": 'PRESS'}, None), ("transform.bbone_resize", {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True}, None), ("anim.keyframe_insert_menu", {"type": 'I', "value": 'PRESS'}, None), - ("anim.keyframe_delete", {"type": 'I', "value": 'PRESS', "alt": True}, None), + ("anim.keyframe_delete_v3d", {"type": 'I', "value": 'PRESS', "alt": True}, None), ("anim.keying_set_active_set", {"type": 'I', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), ("poselib.browse_interactive", {"type": 'L', "value": 'PRESS', "alt": True}, None), ("poselib.pose_add", {"type": 'L', "value": 'PRESS', "shift": True}, None), @@ -4185,7 +4168,7 @@ def km_object_mode(params): ("wm.context_toggle", {"type": 'PERIOD', "value": 'PRESS', "ctrl": True}, {"properties": [("data_path", 'tool_settings.use_transform_data_origin')]}), ("anim.keyframe_insert_menu", {"type": 'I', "value": 'PRESS'}, None), - ("anim.keyframe_delete", {"type": 'I', "value": 'PRESS', "alt": True}, None), + ("anim.keyframe_delete_v3d", {"type": 'I', "value": 'PRESS', "alt": True}, None), ("anim.keying_set_active_set", {"type": 'I', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), ("collection.create", {"type": 'G', "value": 'PRESS', "ctrl": True}, None), ("collection.objects_remove", {"type": 'G', "value": 'PRESS', "ctrl": True, "alt": True}, None), @@ -5071,6 +5054,11 @@ def km_object_non_modal(params): ("object.origin_set", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), ]) else: + items.extend([ + # NOTE: this shortcut (while not temporary) is not ideal, see: T89757. + ("object.transfer_mode", {"type": 'Q', "value": 'PRESS', "alt": True}, None), + ]) + if params.use_pie_click_drag: items.extend([ ("object.mode_set", {"type": 'TAB', "value": 'CLICK'}, @@ -5551,6 +5539,7 @@ def km_view3d_walk_modal(_params): ("DECELERATE", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "any": True, "repeat": True}, None), ("ACCELERATE", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "any": True}, None), ("DECELERATE", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "any": True}, None), + ("AXIS_LOCK_Z", {"type": 'Z', "value": 'PRESS'}, None), ]) return keymap diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index b0144672745..714126903d8 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -3015,7 +3015,7 @@ def km_pose(params): ("anim.keyframe_insert_by_name", {"type": 'R', "value": 'PRESS', "shift": True}, {"properties": [("type", 'Scaling')]}), - ("anim.keyframe_delete", {"type": 'S', "value": 'PRESS', "alt": True}, None), + ("anim.keyframe_delete_v3d", {"type": 'S', "value": 'PRESS', "alt": True}, None), ("anim.keying_set_active_set", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), *_template_items_context_menu("VIEW3D_MT_pose_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}), # Tools @@ -3086,7 +3086,7 @@ def km_object_mode(params): {"properties": [("type", 'Rotation')]}), ("anim.keyframe_insert_by_name", {"type": 'R', "value": 'PRESS', "shift": True}, {"properties": [("type", 'Scaling')]}), - ("anim.keyframe_delete", {"type": 'S', "value": 'PRESS', "alt": True}, None), + ("anim.keyframe_delete_v3d", {"type": 'S', "value": 'PRESS', "alt": True}, None), ("anim.keying_set_active_set", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), *_template_items_context_menu("VIEW3D_MT_object_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}), ("object.move_to_collection", {"type": 'G', "value": 'PRESS', "ctrl": True}, None), diff --git a/release/scripts/presets/tracking_camera/1_inch.py b/release/scripts/presets/tracking_camera/1_inch.py index 72b039fb978..97e87b8c5a7 100644 --- a/release/scripts/presets/tracking_camera/1_inch.py +++ b/release/scripts/presets/tracking_camera/1_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 13.2 bpy.context.camera.sensor_height = 8.80 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py b/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py index 38e09182de6..8b0dc3cea1d 100644 --- a/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py +++ b/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 7.18 bpy.context.camera.sensor_height = 5.32 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py b/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py index 4d55738f4ed..bd6808da082 100644 --- a/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py +++ b/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 6.17 bpy.context.camera.sensor_height = 4.55 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py b/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py index cbdb6f3cbe0..90f60e7d7f0 100644 --- a/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py +++ b/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 5.76 bpy.context.camera.sensor_height = 4.29 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py b/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py index 5ccfa4ab555..4a9591803d0 100644 --- a/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py +++ b/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 5.37 bpy.context.camera.sensor_height = 4.04 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py b/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py index 1963f7ec048..5f31b9ec49c 100644 --- a/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py +++ b/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 4.54 bpy.context.camera.sensor_height = 3.42 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/2_slash_3_inch.py b/release/scripts/presets/tracking_camera/2_slash_3_inch.py index 25b46016800..eb463a31af7 100644 --- a/release/scripts/presets/tracking_camera/2_slash_3_inch.py +++ b/release/scripts/presets/tracking_camera/2_slash_3_inch.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 8.8 bpy.context.camera.sensor_height = 6.6 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/APS-C.py b/release/scripts/presets/tracking_camera/APS-C.py index 84e40825248..4031e8bae71 100644 --- a/release/scripts/presets/tracking_camera/APS-C.py +++ b/release/scripts/presets/tracking_camera/APS-C.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 23.6 bpy.context.camera.sensor_height = 15.6 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/APS-C_(Canon).py b/release/scripts/presets/tracking_camera/APS-C_(Canon).py index 55f20ce0eac..484929a54e7 100644 --- a/release/scripts/presets/tracking_camera/APS-C_(Canon).py +++ b/release/scripts/presets/tracking_camera/APS-C_(Canon).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 22.30 bpy.context.camera.sensor_height = 14.90 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/APS-H_(Canon).py b/release/scripts/presets/tracking_camera/APS-H_(Canon).py index d63f733280b..d3b61d1aa46 100644 --- a/release/scripts/presets/tracking_camera/APS-H_(Canon).py +++ b/release/scripts/presets/tracking_camera/APS-H_(Canon).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 27.90 bpy.context.camera.sensor_height = 18.60 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Analog_16mm.py b/release/scripts/presets/tracking_camera/Analog_16mm.py index aa98eaf2408..a290839c8e0 100644 --- a/release/scripts/presets/tracking_camera/Analog_16mm.py +++ b/release/scripts/presets/tracking_camera/Analog_16mm.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 10.26 bpy.context.camera.sensor_height = 7.49 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Analog_35mm.py b/release/scripts/presets/tracking_camera/Analog_35mm.py index a0dee1f0166..fe3338dd292 100644 --- a/release/scripts/presets/tracking_camera/Analog_35mm.py +++ b/release/scripts/presets/tracking_camera/Analog_35mm.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 22 bpy.context.camera.sensor_height = 16 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Analog_65mm.py b/release/scripts/presets/tracking_camera/Analog_65mm.py index 8de91ac0ee3..d6eb9c32283 100644 --- a/release/scripts/presets/tracking_camera/Analog_65mm.py +++ b/release/scripts/presets/tracking_camera/Analog_65mm.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 52.45 bpy.context.camera.sensor_height = 23.01 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Analog_IMAX.py b/release/scripts/presets/tracking_camera/Analog_IMAX.py index 5a445f3de8c..b71b910dee0 100644 --- a/release/scripts/presets/tracking_camera/Analog_IMAX.py +++ b/release/scripts/presets/tracking_camera/Analog_IMAX.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 71.41 bpy.context.camera.sensor_height = 52.63 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Analog_Super_16.py b/release/scripts/presets/tracking_camera/Analog_Super_16.py index a340a31dc25..f76238c69d3 100644 --- a/release/scripts/presets/tracking_camera/Analog_Super_16.py +++ b/release/scripts/presets/tracking_camera/Analog_Super_16.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 12.35 bpy.context.camera.sensor_height = 7.42 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Analog_Super_35.py b/release/scripts/presets/tracking_camera/Analog_Super_35.py index 3c8f1837253..b22ff545c68 100644 --- a/release/scripts/presets/tracking_camera/Analog_Super_35.py +++ b/release/scripts/presets/tracking_camera/Analog_Super_35.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 24.89 bpy.context.camera.sensor_height = 18.66 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Arri_Alexa_65.py b/release/scripts/presets/tracking_camera/Arri_Alexa_65.py index b1467709949..24d03e022ae 100644 --- a/release/scripts/presets/tracking_camera/Arri_Alexa_65.py +++ b/release/scripts/presets/tracking_camera/Arri_Alexa_65.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 54.12 bpy.context.camera.sensor_height = 25.58 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py b/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py index 1cde94fce8d..430fdc996a6 100644 --- a/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py +++ b/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 36.70 bpy.context.camera.sensor_height = 25.54 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py b/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py index 0f61d35a0f9..90998bc0da0 100644 --- a/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py +++ b/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 29.90 bpy.context.camera.sensor_height = 15.77 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py index 260bfbaf94f..bb2b172919e 100644 --- a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py +++ b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 12.48 bpy.context.camera.sensor_height = 7.02 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py index dc057397828..4b735283c8b 100644 --- a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py +++ b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 18.96 bpy.context.camera.sensor_height = 10.00 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py index a483f3d5f98..1a882f05786 100644 --- a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py +++ b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 23.10 bpy.context.camera.sensor_height = 12.99 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py b/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py index c71e42d72d3..767d16984d8 100644 --- a/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py +++ b/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 25.34 bpy.context.camera.sensor_height = 14.25 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Foveon_(Sigma).py b/release/scripts/presets/tracking_camera/Foveon_(Sigma).py index e6a1a0ed344..6b35f29acaf 100644 --- a/release/scripts/presets/tracking_camera/Foveon_(Sigma).py +++ b/release/scripts/presets/tracking_camera/Foveon_(Sigma).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 20.70 bpy.context.camera.sensor_height = 13.80 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Fullframe.py b/release/scripts/presets/tracking_camera/Fullframe.py index 95fb4afc10b..c8017331b28 100644 --- a/release/scripts/presets/tracking_camera/Fullframe.py +++ b/release/scripts/presets/tracking_camera/Fullframe.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 36 bpy.context.camera.sensor_height = 24 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/MFT.py b/release/scripts/presets/tracking_camera/MFT.py index bc0dd49baa8..7441f1aea76 100644 --- a/release/scripts/presets/tracking_camera/MFT.py +++ b/release/scripts/presets/tracking_camera/MFT.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 17.3 bpy.context.camera.sensor_height = 13.0 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py b/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py index e9b16024b79..d03a4f22db7 100644 --- a/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py +++ b/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 44 bpy.context.camera.sensor_height = 33 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/RED_Dragon_5K.py b/release/scripts/presets/tracking_camera/RED_Dragon_5K.py index fa95a98f8c4..e8b990d4d00 100644 --- a/release/scripts/presets/tracking_camera/RED_Dragon_5K.py +++ b/release/scripts/presets/tracking_camera/RED_Dragon_5K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 25.60 bpy.context.camera.sensor_height = 13.5 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/RED_Dragon_6K.py b/release/scripts/presets/tracking_camera/RED_Dragon_6K.py index 80f7ad1bbb8..982e2ab8e00 100644 --- a/release/scripts/presets/tracking_camera/RED_Dragon_6K.py +++ b/release/scripts/presets/tracking_camera/RED_Dragon_6K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 30.70 bpy.context.camera.sensor_height = 15.80 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/RED_Helium_8K.py b/release/scripts/presets/tracking_camera/RED_Helium_8K.py index 0f61d35a0f9..90998bc0da0 100644 --- a/release/scripts/presets/tracking_camera/RED_Helium_8K.py +++ b/release/scripts/presets/tracking_camera/RED_Helium_8K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 29.90 bpy.context.camera.sensor_height = 15.77 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/presets/tracking_camera/RED_Monstro_8K.py b/release/scripts/presets/tracking_camera/RED_Monstro_8K.py index 86c382624ab..1c8bc11dfaa 100644 --- a/release/scripts/presets/tracking_camera/RED_Monstro_8K.py +++ b/release/scripts/presets/tracking_camera/RED_Monstro_8K.py @@ -1,4 +1,4 @@ import bpy bpy.context.camera.sensor_width = 40.96 bpy.context.camera.sensor_height = 21.60 -bpy.context.camera.sensor_fit = 'HORIZONTAL'
\ No newline at end of file +bpy.context.camera.sensor_fit = 'HORIZONTAL' diff --git a/release/scripts/startup/bl_operators/assets.py b/release/scripts/startup/bl_operators/assets.py index 48f07a03773..d2655784afd 100644 --- a/release/scripts/startup/bl_operators/assets.py +++ b/release/scripts/startup/bl_operators/assets.py @@ -18,7 +18,9 @@ # <pep8 compliant> from __future__ import annotations +from pathlib import Path +import bpy from bpy.types import Operator from bpy_extras.asset_utils import ( @@ -72,7 +74,88 @@ class ASSET_OT_tag_remove(Operator): return {'FINISHED'} +class ASSET_OT_open_containing_blend_file(Operator): + """Open the blend file that contains the active asset""" + + bl_idname = "asset.open_containing_blend_file" + bl_label = "Open Blend File" + bl_options = {'REGISTER'} + + _process = None # Optional[subprocess.Popen] + + @classmethod + def poll(cls, context): + asset_file_handle = getattr(context, 'asset_file_handle', None) + asset_library = getattr(context, 'asset_library', None) + + if not asset_library: + cls.poll_message_set("No asset library selected") + return False + if not asset_file_handle: + cls.poll_message_set("No asset selected") + return False + if asset_file_handle.local_id: + cls.poll_message_set("Selected asset is contained in the current file") + return False + return True + + def execute(self, context): + asset_file_handle = context.asset_file_handle + asset_library = context.asset_library + + if asset_file_handle.local_id: + self.report({'WARNING'}, "This asset is stored in the current blend file") + return {'CANCELLED'} + + asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library) + self.open_in_new_blender(asset_lib_path) + + wm = context.window_manager + self._timer = wm.event_timer_add(0.1, window=context.window) + wm.modal_handler_add(self) + + return {'RUNNING_MODAL'} + + def modal(self, context, event): + if event.type != 'TIMER': + return {'PASS_THROUGH'} + + if self._process is None: + self.report({'ERROR'}, "Unable to find any running process") + self.cancel(context) + return {'CANCELLED'} + + returncode = self._process.poll() + if returncode is None: + # Process is still running. + return {'RUNNING_MODAL'} + + if returncode: + self.report({'WARNING'}, "Blender subprocess exited with error code %d" % returncode) + + # TODO(Sybren): Replace this with a generic "reload assets" operator + # that can run outside of the Asset Browser context. + if bpy.ops.file.refresh.poll(): + bpy.ops.file.refresh() + if bpy.ops.asset.list_refresh.poll(): + bpy.ops.asset.list_refresh() + + self.cancel(context) + return {'FINISHED'} + + def cancel(self, context): + wm = context.window_manager + wm.event_timer_remove(self._timer) + + def open_in_new_blender(self, filepath): + import subprocess + + cli_args = [bpy.app.binary_path, str(filepath)] + self._process = subprocess.Popen(cli_args) + + classes = ( ASSET_OT_tag_add, ASSET_OT_tag_remove, + ASSET_OT_open_containing_blend_file, ) diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py index 3cefaf6929b..2959232fa51 100644 --- a/release/scripts/startup/bl_operators/node.py +++ b/release/scripts/startup/bl_operators/node.py @@ -306,67 +306,6 @@ class NODE_OT_tree_path_parent(Operator): return {'FINISHED'} -class NODE_OT_active_preview_toggle(Operator): - '''Toggle active preview state of node''' - bl_idname = "node.active_preview_toggle" - bl_label = "Toggle Active Preview" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(cls, context): - space = context.space_data - if space is None: - return False - if space.type != 'NODE_EDITOR': - return False - if space.edit_tree is None: - return False - if space.edit_tree.nodes.active is None: - return False - return True - - def execute(self, context): - node_editor = context.space_data - ntree = node_editor.edit_tree - active_node = ntree.nodes.active - - if active_node.active_preview: - self._disable_preview(context, active_node) - else: - self._enable_preview(context, node_editor, ntree, active_node) - - return {'FINISHED'} - - @classmethod - def _enable_preview(cls, context, node_editor, ntree, active_node): - spreadsheets = cls._find_unpinned_spreadsheets(context) - - for spreadsheet in spreadsheets: - spreadsheet.set_geometry_node_context(node_editor, active_node) - - for node in ntree.nodes: - node.active_preview = False - active_node.active_preview = True - - @classmethod - def _disable_preview(cls, context, active_node): - spreadsheets = cls._find_unpinned_spreadsheets(context) - for spreadsheet in spreadsheets: - spreadsheet.context_path.clear() - - active_node.active_preview = False - - @staticmethod - def _find_unpinned_spreadsheets(context): - spreadsheets = [] - for window in context.window_manager.windows: - for area in window.screen.areas: - space = area.spaces.active - if space.type == 'SPREADSHEET' and not space.is_pinned: - spreadsheets.append(space) - return spreadsheets - - classes = ( NodeSetting, @@ -375,5 +314,4 @@ classes = ( NODE_OT_add_search, NODE_OT_collapse_hide_unused_toggle, NODE_OT_tree_path_parent, - NODE_OT_active_preview_toggle, ) diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py index 48a02a4c5c6..8f678896e61 100644 --- a/release/scripts/startup/bl_operators/sequencer.py +++ b/release/scripts/startup/bl_operators/sequencer.py @@ -108,14 +108,13 @@ class SequencerSplitMulticam(Operator): if s.multicam_source == camera or camera >= s.channel: return {'FINISHED'} - if not s.select: - s.select = True - cfra = context.scene.frame_current - bpy.ops.sequencer.split(frame=cfra, type='SOFT', side='RIGHT') - for s in context.scene.sequence_editor.sequences_all: - if s.select and s.type == 'MULTICAM' and s.frame_final_start <= cfra and cfra < s.frame_final_end: - context.scene.sequence_editor.active_strip = s + right_strip = s.split(frame=cfra, split_method='SOFT') + + if right_strip: + s.select = False + right_strip.select = True + context.scene.sequence_editor.active_strip = right_strip context.scene.sequence_editor.active_strip.multicam_source = camera return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/spreadsheet.py b/release/scripts/startup/bl_operators/spreadsheet.py index 5cc83d4eddd..b5098d63dac 100644 --- a/release/scripts/startup/bl_operators/spreadsheet.py +++ b/release/scripts/startup/bl_operators/spreadsheet.py @@ -20,6 +20,7 @@ from __future__ import annotations from bpy.types import Operator + class SPREADSHEET_OT_toggle_pin(Operator): '''Turn on or off pinning''' bl_idname = "spreadsheet.toggle_pin" @@ -47,18 +48,7 @@ class SPREADSHEET_OT_toggle_pin(Operator): def unpin(self, context): space = context.space_data space.is_pinned = False - - space.context_path.clear() - - # Try to find a node with an active preview in any open editor. - if space.object_eval_state == 'EVALUATED': - node_editors = self.find_geometry_node_editors(context) - for node_editor in node_editors: - ntree = node_editor.edit_tree - for node in ntree.nodes: - if node.active_preview: - space.set_geometry_node_context(node_editor, node) - return + space.context_path.guess() def find_geometry_node_editors(self, context): editors = [] diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 2cc7b828c11..6a3830ad1e4 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -135,7 +135,7 @@ def context_path_decompose(data_path): if base_path: assert(base_path.startswith(".")) - base_path= base_path[1:] + base_path = base_path[1:] if prop_attr: assert(prop_attr.startswith(".")) prop_attr = prop_attr[1:] diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index ef705f8fe37..25484e905c3 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -117,13 +117,15 @@ def register(): for cls in mod.classes: register_class(cls) - # space_userprefs.py from bpy.props import ( EnumProperty, StringProperty, ) - from bpy.types import WindowManager + from bpy.types import ( + WindowManager, + ) + # space_userprefs.py def addon_filter_items(_self, _context): import addon_utils @@ -234,3 +236,21 @@ class UI_UL_list(bpy.types.UIList): bpy.utils.register_class(UI_UL_list) + + +class UI_MT_list_item_context_menu(bpy.types.Menu): + """ + UI List item context menu definition. Scripts can append/prepend this to + add own operators to the context menu. They must check context though, so + their items only draw in a valid context and for the correct UI list. + """ + + bl_label = "List Item" + bl_idname = "UI_MT_list_item_context_menu" + + def draw(self, context): + # Dummy function. This type is just for scripts to append their own + # context menu items. + pass + +bpy.utils.register_class(UI_MT_list_item_context_menu) diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py index 27de80bb88d..b51d7157c06 100644 --- a/release/scripts/startup/bl_ui/properties_collection.py +++ b/release/scripts/startup/bl_ui/properties_collection.py @@ -35,7 +35,7 @@ def lineart_make_line_type_entry(col, line_type, text_disp, expand, search_from) if line_type.use and expand: col.prop_search(line_type, "layer", search_from, "layers", icon='GREASEPENCIL') - col.prop_search(line_type, "material", search_from, + col.prop_search(line_type, "material", search_from, "materials", icon='SHADING_TEXTURE') @@ -90,7 +90,7 @@ class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel): row = layout.row(align=True, heading="Masks") row.active = collection.lineart_use_intersection_mask - for i in range(0,8): + for i in range(8): row.prop(collection, "lineart_intersection_mask", index=i, text=str(i), toggle=True) diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index a88def34767..2a0cf56534c 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -505,6 +505,7 @@ class ConstraintButtonsPanel: self.target_template(layout, con) + layout.prop(con, "remove_target_shear") layout.prop(con, "mix_mode", text="Mix") self.space_template(layout, con) diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py index e71ea2f31a4..b273eee4e19 100644 --- a/release/scripts/startup/bl_ui/properties_data_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py @@ -93,8 +93,8 @@ class GPENCIL_MT_layer_context_menu(Menu): gpd = ob.data gpl = gpd.layers.active - layout.operator("gpencil.layer_duplicate", text="Duplicate", icon='DUPLICATE').mode='ALL' - layout.operator("gpencil.layer_duplicate", text="Duplicate Empty Keyframes").mode='EMPTY' + layout.operator("gpencil.layer_duplicate", text="Duplicate", icon='DUPLICATE').mode = 'ALL' + layout.operator("gpencil.layer_duplicate", text="Duplicate Empty Keyframes").mode = 'EMPTY' layout.separator() @@ -113,8 +113,8 @@ class GPENCIL_MT_layer_context_menu(Menu): layout.operator("gpencil.layer_merge", icon='SORT_ASC', text="Merge Down") layout.separator() - layout.operator("gpencil.layer_duplicate_object", text="Copy Layer to Selected").only_active=True - layout.operator("gpencil.layer_duplicate_object", text="Copy All Layers to Selected").only_active=False + layout.operator("gpencil.layer_duplicate_object", text="Copy Layer to Selected").only_active = True + layout.operator("gpencil.layer_duplicate_object", text="Copy All Layers to Selected").only_active = False class DATA_PT_gpencil_layers(DataButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index fb8aedd1f49..d9ad094ac4f 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -41,7 +41,6 @@ class MESH_MT_vertex_group_context_menu(Menu): ).sort_type = 'BONE_HIERARCHY' layout.separator() layout.operator("object.vertex_group_copy", icon='DUPLICATE') - layout.operator("object.vertex_group_copy_to_linked") layout.operator("object.vertex_group_copy_to_selected") layout.separator() layout.operator("object.vertex_group_mirror", icon='ARROW_LEFTRIGHT').use_topology = False @@ -647,7 +646,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel): if len(colliding_names) == 0: return - layout.label(text="Name Collisions: {}".format(", ".join(colliding_names)), icon='INFO') + layout.label(text="Name collisions: {}".format(", ".join(colliding_names)), icon='ERROR') classes = ( diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 0da0716e850..de743033036 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -847,6 +847,7 @@ class GreasePencilLayerRelationsPanel: col.enabled = bool(gpl.viewlayer_render) col.prop(gpl, "use_viewlayer_masks") + class GreasePencilLayerDisplayPanel: def draw(self, context): diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 96920af1c7e..afbc3abf302 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -72,8 +72,9 @@ class CLIP_PT_marker_display(Panel): col.prop(view, "show_marker_pattern", text="Pattern") col.prop(view, "show_marker_search", text="Search") - col.active = view.show_track_path col.prop(view, "show_track_path", text="Path") + col = col.column() + col.active = view.show_track_path col.prop(view, "path_length", text="Length") col = row.column() @@ -113,7 +114,6 @@ class CLIP_PT_clip_display(Panel): row = layout.row() col = row.column() col.prop(sc.clip_user, "use_render_undistorted", text="Render Undistorted") - col.prop(sc, "lock_selection", text="Lock to Selection") col = row.column() col.prop(sc, "show_stable", text="Show Stable") col.prop(sc, "show_grid", text="Grid") @@ -190,7 +190,7 @@ class CLIP_HT_header(Header): row.prop(sc, "pivot_point", text="", icon_only=True) row = layout.row(align=True) icon = 'LOCKED' if sc.lock_selection else 'UNLOCKED' - row.prop(sc, "lock_selection", icon=icon, text="") + row.operator("clip.lock_selection_toggle", icon=icon, text="", depress=sc.lock_selection) row.popover(panel='CLIP_PT_display') elif sc.view == 'GRAPH': @@ -250,7 +250,7 @@ class CLIP_HT_header(Header): row.popover(panel='CLIP_PT_mask_display') row = layout.row(align=True) icon = 'LOCKED' if sc.lock_selection else 'UNLOCKED' - row.prop(sc, "lock_selection", icon=icon, text="") + row.operator("clip.lock_selection_toggle", icon=icon, text="", depress=sc.lock_selection) row.popover(panel='CLIP_PT_display') def draw(self, context): @@ -1477,9 +1477,13 @@ class CLIP_MT_track(Menu): layout.separator() - layout.operator("clip.solve_camera", - text="Solve Camera Motion" if tracking_object.is_camera - else "Solve Object Motion") + layout.operator( + "clip.solve_camera", + text=( + "Solve Camera Motion" if tracking_object.is_camera else + "Solve Object Motion" + ), + ) layout.separator() diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index ffb7b9e5c20..84d1c36c53d 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -609,9 +609,9 @@ class DOPESHEET_MT_context_menu(Menu): layout.operator_menu_enum("action.keyframe_type", "type", text="Keyframe Type") if st.mode != 'GPENCIL': - layout.operator_menu_enum("action.handle_type", "type", text="Handle Type") - layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode") - layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode") + layout.operator_menu_enum("action.handle_type", "type", text="Handle Type") + layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode") + layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode") layout.separator() @@ -625,8 +625,8 @@ class DOPESHEET_MT_context_menu(Menu): layout.operator("action.delete") if st.mode == 'GPENCIL': - layout.operator("gpencil.interpolate_reverse") - layout.operator("gpencil.frame_clean_duplicate", text="Delete Duplicate Frames") + layout.operator("gpencil.interpolate_reverse") + layout.operator("gpencil.frame_clean_duplicate", text="Delete Duplicate Frames") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 1ad88744b16..8ca93d2406c 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -552,6 +552,10 @@ class FILEBROWSER_MT_context_menu(Menu): sub.operator_context = 'EXEC_DEFAULT' sub.operator("file.delete", text="Delete") + active_asset = asset_utils.SpaceAssetInfo.get_active_asset(context) + if active_asset: + layout.operator("asset.open_containing_blend_file") + layout.separator() sub = layout.row() @@ -592,15 +596,28 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel): def draw(self, context): layout = self.layout - active_file = context.active_file - active_asset = asset_utils.SpaceAssetInfo.get_active_asset(context) + asset_file_handle = context.asset_file_handle - if not active_file or not active_asset: + if asset_file_handle is None: layout.label(text="No asset selected", icon='INFO') return - # If the active file is an ID, use its name directly so renaming is possible from right here. - layout.prop(context.id if context.id is not None else active_file, "name", text="") + asset_library = context.asset_library + asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library) + + if asset_file_handle.local_id: + # If the active file is an ID, use its name directly so renaming is possible from right here. + layout.prop(asset_file_handle.local_id, "name", text="") + row = layout.row() + row.label(text="Source: Current File") + else: + layout.prop(asset_file_handle, "name", text="") + col = layout.column(align=True) # Just to reduce margin. + col.label(text="Source:") + row = col.row() + row.label(text=asset_lib_path) + + row.operator("asset.open_containing_blend_file", text="", icon='TOOL_SETTINGS') class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel): diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 3fafa328289..0fceb864ac2 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -257,8 +257,9 @@ class IMAGE_MT_image_flip(Menu): def draw(self, _context): layout = self.layout - layout.operator("image.flip", text="Horizontally").use_flip_horizontal = True - layout.operator("image.flip", text="Vertically").use_flip_vertical = True + layout.operator("image.flip", text="Horizontally").use_flip_x = True + layout.operator("image.flip", text="Vertically").use_flip_y = True + class IMAGE_MT_image_invert(Menu): bl_label = "Invert" diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 1208ca0a64a..fba86676ad4 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -694,6 +694,97 @@ class NODE_UL_interface_sockets(bpy.types.UIList): layout.template_node_socket(color=color) +class NodeTreeInterfacePanel: + def draw_socket_list(self, context, in_out, sockets_propname, active_socket_propname): + layout = self.layout + + snode = context.space_data + tree = snode.edit_tree + sockets = getattr(tree, sockets_propname) + active_socket_index = getattr(tree, active_socket_propname) + active_socket = sockets[active_socket_index] if active_socket_index >= 0 else None + + split = layout.row() + + split.template_list("NODE_UL_interface_sockets", in_out, tree, sockets_propname, tree, active_socket_propname) + + ops_col = split.column() + + add_remove_col = ops_col.column(align=True) + props = add_remove_col.operator("node.tree_socket_add", icon='ADD', text="") + props.in_out = in_out + props = add_remove_col.operator("node.tree_socket_remove", icon='REMOVE', text="") + props.in_out = in_out + + ops_col.separator() + + up_down_col = ops_col.column(align=True) + props = up_down_col.operator("node.tree_socket_move", icon='TRIA_UP', text="") + props.in_out = in_out + props.direction = 'UP' + props = up_down_col.operator("node.tree_socket_move", icon='TRIA_DOWN', text="") + props.in_out = in_out + props.direction = 'DOWN' + + if active_socket is not None: + # Mimicking property split. + layout.use_property_split = False + layout.use_property_decorate = False + layout_row = layout.row(align=True) + layout_split = layout_row.split(factor=0.4, align=True) + + label_column = layout_split.column(align=True) + label_column.alignment = 'RIGHT' + # Menu to change the socket type. + label_column.label(text="Type") + + property_row = layout_split.row(align=True) + props = property_row.operator_menu_enum( + "node.tree_socket_change_type", + "socket_type", + text=active_socket.bl_label if active_socket.bl_label else active_socket.bl_idname + ) + props.in_out = in_out + + layout.use_property_split = True + layout.use_property_decorate = False + + layout.prop(active_socket, "name") + # Display descriptions only for Geometry Nodes, since it's only used in the modifier panel. + if tree.type == 'GEOMETRY': + layout.prop(active_socket, "description") + active_socket.draw(context, layout) + + +class NODE_PT_node_tree_interface_inputs(NodeTreeInterfacePanel, Panel): + bl_space_type = 'NODE_EDITOR' + bl_region_type = 'UI' + bl_category = "Group" + bl_label = "Inputs" + + @classmethod + def poll(cls, context): + snode = context.space_data + return snode.edit_tree is not None + + def draw(self, context): + self.draw_socket_list(context, "IN", "inputs", "active_input") + +class NODE_PT_node_tree_interface_outputs(NodeTreeInterfacePanel, Panel): + bl_space_type = 'NODE_EDITOR' + bl_region_type = 'UI' + bl_category = "Group" + bl_label = "Outputs" + + @classmethod + def poll(cls, context): + snode = context.space_data + return snode.edit_tree is not None + + def draw(self, context): + self.draw_socket_list(context, "OUT", "outputs", "active_output") + + # Grease Pencil properties class NODE_PT_annotation(AnnotationDataPanel, Panel): bl_space_type = 'NODE_EDITOR' @@ -752,6 +843,8 @@ classes = ( NODE_PT_quality, NODE_PT_annotation, NODE_UL_interface_sockets, + NODE_PT_node_tree_interface_inputs, + NODE_PT_node_tree_interface_outputs, node_panel(EEVEE_MATERIAL_PT_settings), node_panel(MATERIAL_PT_viewport), diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index 7a694108e14..ba91b6e8d50 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -442,7 +442,6 @@ class OUTLINER_PT_filter(Panel): row.prop(space, "use_filter_lib_override_system", text="System Overrides") - classes = ( OUTLINER_HT_header, OUTLINER_MT_editor_menus, diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index ab05461f185..55714e0b0a5 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -400,7 +400,7 @@ class SEQUENCER_MT_view(Menu): layout.menu("SEQUENCER_MT_proxy") layout.operator_context = 'INVOKE_DEFAULT' - + layout.separator() layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("sequencer.refresh_all", icon='FILE_REFRESH', text="Refresh All") @@ -467,6 +467,7 @@ class SEQUENCER_MT_select_handle(Menu): layout.operator("sequencer.select_handles", text="Left Neighbor").side = 'LEFT_NEIGHBOR' layout.operator("sequencer.select_handles", text="Right Neighbor").side = 'RIGHT_NEIGHBOR' + class SEQUENCER_MT_select_channel(Menu): bl_label = "Select Channel" @@ -1415,7 +1416,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel): split.label(text="%dx%d" % size, translate=False) else: split.label(text="None") - #FPS + # FPS if elem.orig_fps: split = col.split(factor=0.5, align=False) split.alignment = 'RIGHT' @@ -1424,7 +1425,6 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel): split.label(text="%.2f" % elem.orig_fps, translate=False) - class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): bl_label = "Scene" bl_category = "Strip" @@ -1857,7 +1857,7 @@ class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel): @classmethod def poll(cls, context): show_developer_ui = context.preferences.view.show_developer_ui - return cls.has_sequencer(context) and context.scene.sequence_editor and show_developer_ui + return cls.has_sequencer(context) and context.scene.sequence_editor and show_developer_ui def draw(self, context): layout = self.layout @@ -2286,14 +2286,15 @@ class SEQUENCER_PT_snapping(Panel): layout.use_property_decorate = False col = layout.column(heading="Snap to", align=True) - col.prop(sequencer_tool_settings, "snap_seq_element", expand=True) + col.prop(sequencer_tool_settings, "snap_to_current_frame") + col.prop(sequencer_tool_settings, "snap_to_hold_offset") col = layout.column(heading="Ignore", align=True) col.prop(sequencer_tool_settings, "snap_ignore_muted", text="Muted Strips") - col.prop(sequencer_tool_settings, "snap_ignore_sound",text="Sound Strips") + col.prop(sequencer_tool_settings, "snap_ignore_sound", text="Sound Strips") col = layout.column() - col.prop(sequencer_tool_settings, "snap_distance", slider=True, text="Distance") + col.prop(sequencer_tool_settings, "use_snap_current_frame_to_strips") classes = ( diff --git a/release/scripts/startup/bl_ui/space_spreadsheet.py b/release/scripts/startup/bl_ui/space_spreadsheet.py index 178be9ef0b7..afdbfea5091 100644 --- a/release/scripts/startup/bl_ui/space_spreadsheet.py +++ b/release/scripts/startup/bl_ui/space_spreadsheet.py @@ -54,8 +54,11 @@ class SPREADSHEET_HT_header(bpy.types.Header): pin_icon = 'PINNED' if space.is_pinned else 'UNPINNED' layout.operator("spreadsheet.toggle_pin", text="", icon=pin_icon, emboss=False) + if space.object_eval_state == 'VIEWER_NODE' and len(context_path) < 3: + layout.label(text="No active viewer node.", icon='INFO') + layout.separator_spacer() - + row = layout.row(align=True) sub = row.row(align=True) sub.active = self.selection_filter_available(space) @@ -112,6 +115,7 @@ class SPREADSHEET_HT_header(bpy.types.Header): return False return True + classes = ( SPREADSHEET_HT_header, ) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index f9359a8b4a0..7e6fde1ebaf 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1391,7 +1391,6 @@ class USERPREF_PT_file_paths_asset_libraries(FilePathsPanel, Panel): row.separator() row.label(text="Path") - for i, library in enumerate(paths.asset_libraries): name_col.prop(library, "name", text="") row = path_col.row() diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 80cede9ee5a..df41445ee6f 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2765,23 +2765,27 @@ class VIEW3D_MT_make_single_user(Menu): props = layout.operator("object.make_single_user", text="Object") props.object = True - props.obdata = props.material = props.animation = False + props.obdata = props.material = props.animation = props.obdata_animation = False props = layout.operator("object.make_single_user", text="Object & Data") props.object = props.obdata = True - props.material = props.animation = False + props.material = props.animation = props.obdata_animation = False props = layout.operator("object.make_single_user", text="Object & Data & Materials") props.object = props.obdata = props.material = True - props.animation = False + props.animation = props.obdata_animation = False props = layout.operator("object.make_single_user", text="Materials") props.material = True - props.object = props.obdata = props.animation = False + props.object = props.obdata = props.animation = props.obdata_animation = False props = layout.operator("object.make_single_user", text="Object Animation") props.animation = True - props.object = props.obdata = props.material = False + props.object = props.obdata = props.material = props.obdata_animation = False + + props = layout.operator("object.make_single_user", text="Object Data Animation") + props.obdata_animation = props.obdata = True + props.object = props.material = props.animation = False class VIEW3D_MT_object_convert(Menu): @@ -3129,7 +3133,6 @@ class VIEW3D_MT_mask(Menu): layout.menu("VIEW3D_MT_random_mask", text="Random Mask") - class VIEW3D_MT_face_sets(Menu): bl_label = "Face Sets" @@ -3259,6 +3262,7 @@ class VIEW3D_MT_random_mask(Menu): op = layout.operator("sculpt.mask_init", text='Per Loose Part') op.mode = 'RANDOM_PER_LOOSE_PART' + class VIEW3D_MT_particle(Menu): bl_label = "Particle" diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index bc385faf378..46fed79332d 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1731,7 +1731,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff from bl_ui.space_toolsystem_common import ToolSelectPanelHelper tool = ToolSelectPanelHelper.tool_active_from_context(context) - if tool and tool.idname != 'builtin_brush.Tint': + if tool and tool.idname != 'builtin_brush.Tint': return False gptool = brush.gpencil_tool @@ -2057,7 +2057,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel): from bl_ui.space_toolsystem_common import ToolSelectPanelHelper tool = ToolSelectPanelHelper.tool_active_from_context(context) - if tool and tool.idname in('builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'): + if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}: return False if brush.gpencil_tool == 'TINT': @@ -2118,7 +2118,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel): from bl_ui.space_toolsystem_common import ToolSelectPanelHelper tool = ToolSelectPanelHelper.tool_active_from_context(context) - if tool and tool.idname in('builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'): + if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}: return False if brush.gpencil_tool == 'TINT': diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py index 2fc2d966ea9..ceffeaaff6c 100644 --- a/release/scripts/startup/keyingsets_builtins.py +++ b/release/scripts/startup/keyingsets_builtins.py @@ -383,6 +383,7 @@ class BUILTIN_KSI_Available(KeyingSetInfo): ############################### + class WholeCharacterMixin: # these prefixes should be avoided, as they are not really bones # that animators should be touching (or need to touch) diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 8ae5d95f639..15c54fe18f9 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -508,14 +508,17 @@ geometry_node_categories = [ NodeItem("GeometryNodeCurveResample"), NodeItem("GeometryNodeMeshToCurve"), NodeItem("GeometryNodeCurveToPoints"), + NodeItem("GeometryNodeCurveEndpoints"), NodeItem("GeometryNodeCurveLength"), NodeItem("GeometryNodeCurveReverse"), ]), GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[ + NodeItem("GeometryNodeCurvePrimitiveLine"), NodeItem("GeometryNodeCurvePrimitiveCircle"), NodeItem("GeometryNodeCurveStar"), NodeItem("GeometryNodeCurveSpiral"), NodeItem("GeometryNodeCurveQuadraticBezier"), + NodeItem("GeometryNodeCurvePrimitiveQuadrilateral"), NodeItem("GeometryNodeCurvePrimitiveBezierSegment"), ]), GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[ @@ -547,7 +550,7 @@ geometry_node_categories = [ NodeItem("GeometryNodeTriangulate"), NodeItem("GeometryNodeEdgeSplit"), NodeItem("GeometryNodeSubdivisionSurface"), - NodeItem("GeometryNodeSubdivide"), + NodeItem("GeometryNodeMeshSubdivide"), ]), GeometryNodeCategory("GEO_PRIMITIVES_MESH", "Mesh Primitives", items=[ NodeItem("GeometryNodeMeshCircle"), @@ -559,6 +562,7 @@ geometry_node_categories = [ NodeItem("GeometryNodeMeshLine"), NodeItem("GeometryNodeMeshUVSphere"), ]), + GeometryNodeCategory("GEO_POINT", "Point", items=[ NodeItem("GeometryNodePointDistribute"), NodeItem("GeometryNodePointInstance"), @@ -574,6 +578,7 @@ geometry_node_categories = [ NodeItem("ShaderNodeMath"), NodeItem("FunctionNodeBooleanMath"), NodeItem("FunctionNodeFloatCompare"), + NodeItem("FunctionNodeFloatToInt"), NodeItem("GeometryNodeSwitch"), ]), GeometryNodeCategory("GEO_VECTOR", "Vector", items=[ @@ -583,6 +588,9 @@ geometry_node_categories = [ NodeItem("ShaderNodeVectorMath"), NodeItem("ShaderNodeVectorRotate"), ]), + GeometryNodeCategory("GEO_OUTPUT", "Output", items=[ + NodeItem("GeometryNodeViewer"), + ]), GeometryNodeCategory("GEO_VOLUME", "Volume", items=[ NodeItem("GeometryNodePointsToVolume"), NodeItem("GeometryNodeVolumeToMesh"), diff --git a/release/scripts/templates_py/image_processing.py b/release/scripts/templates_py/image_processing.py index 2392faf440c..ab14436ad8e 100644 --- a/release/scripts/templates_py/image_processing.py +++ b/release/scripts/templates_py/image_processing.py @@ -20,9 +20,9 @@ input_image.pixels.foreach_get(pixel_data.ravel()) # Do whatever image processing you want using numpy here: # Example 1: Inverse red green and blue channels. -pixel_data[:,:,:3] = 1.0 - pixel_data[:,:,:3] +pixel_data[:, :, :3] = 1.0 - pixel_data[:, :, :3] # Example 2: Change gamma on the red channel. -pixel_data[:,:,0] = np.power(pixel_data[:,:,0], 1.5) +pixel_data[:, :, 0] = np.power(pixel_data[:, :, 0], 1.5) # Create output image. if output_image_name in bpy.data.images: diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py index aa5b9ebf880..3fc7636459b 100644 --- a/release/scripts/templates_py/operator_mesh_add.py +++ b/release/scripts/templates_py/operator_mesh_add.py @@ -6,6 +6,7 @@ from bpy.props import ( FloatProperty, ) + def add_box(width, height, depth): """ This function takes inputs and returns vertex and face arrays. diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index b7c226ada1d..2c7ffbe8e42 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -351,8 +351,7 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font, * characters. */ -/* Note, - * blf_font_ensure_ascii_table(font, gc); must be called before this macro */ +/* NOTE: `blf_font_ensure_ascii_table(font, gc);` must be called before this macro. */ #define BLF_UTF8_NEXT_FAST(_font, _gc, _g, _str, _i, _c, _glyph_ascii_table) \ if (((_c) = (_str)[_i]) < 0x80) { \ @@ -376,8 +375,7 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font, ft_kerning_default : \ (FT_UInt)FT_KERNING_UNFITTED) -/* Note, - * blf_font_ensure_ascii_kerning(font, gc, kern_mode); must be called before this macro */ +/* NOTE: `blf_font_ensure_ascii_kerning(font, gc, kern_mode);` must be called before this macro. */ #define BLF_KERNING_STEP_FAST(_font, _kern_mode, _g_prev, _g, _c_prev, _c, _pen_x) \ { \ diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 2ec0ca22865..3f01501fda4 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -406,7 +406,7 @@ static void blf_texture_draw(const unsigned char color[4], float y2) { /* Only one vertex per glyph, geometry shader expand it into a quad. */ - /* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */ + /* TODO: Get rid of Geom Shader because it's not optimal AT ALL for the GPU. */ copy_v4_fl4(GPU_vertbuf_raw_step(&g_batch.pos_step), x1 + g_batch.ofs[0], y1 + g_batch.ofs[1], diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 684296381eb..904b7bb8718 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -55,7 +55,7 @@ */ /* - * Note: This structure is read-only, for all practical purposes. + * NOTE: This structure is read-only, for all practical purposes. * At some point in the future, we may want to consider * creating a replacement structure that implements a proper * abstract mesh kernel interface. Or, we can leave this @@ -89,7 +89,7 @@ struct Object; struct Scene; /* - * Note: all mface interfaces now officially operate on tessellated data. + * NOTE: all mface interfaces now officially operate on tessellated data. * Also, the mface origindex layer indexes mpolys, not mfaces. */ diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h index 6c07708b5ef..14ab9f21424 100644 --- a/source/blender/blenkernel/BKE_anim_data.h +++ b/source/blender/blenkernel/BKE_anim_data.h @@ -50,8 +50,8 @@ bool id_can_have_animdata(const struct ID *id); /* Get AnimData from the given ID-block */ struct AnimData *BKE_animdata_from_id(struct ID *id); -/* Add AnimData to the given ID-block */ -struct AnimData *BKE_animdata_add_id(struct ID *id); +/* Ensure AnimData is present in the ID-block (when supported). */ +struct AnimData *BKE_animdata_ensure_id(struct ID *id); /* Set active action used by AnimData from the given ID-block */ bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 030560015a9..07da9d75e59 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -268,6 +268,12 @@ void animsys_evaluate_action(struct PointerRNA *ptr, const struct AnimationEvalContext *anim_eval_context, bool flush_to_original); +/* Evaluate action, and blend the result into the current values (instead of overwriting fully). */ +void animsys_blend_in_action(struct PointerRNA *ptr, + struct bAction *act, + const AnimationEvalContext *anim_eval_context, + float blend_factor); + /* Evaluate Action Group */ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 86aa18e5739..e13475fd78c 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -28,7 +28,6 @@ extern "C" { #endif struct AnimationEvalContext; -struct bAction; struct BMEditMesh; struct Bone; struct Depsgraph; @@ -39,6 +38,7 @@ struct Mesh; struct Object; struct PoseTree; struct Scene; +struct bAction; struct bArmature; struct bConstraint; struct bGPDstroke; @@ -207,9 +207,18 @@ void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan); /* Evaluate the action and apply it to the pose. If any pose bones are selected, only FCurves that * relate to those bones are evaluated. */ -void BKE_pose_apply_action(struct Object *ob, - struct bAction *action, - struct AnimationEvalContext *anim_eval_context); +void BKE_pose_apply_action_selected_bones(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context); +/* Evaluate the action and apply it to the pose. Ignore selection state of the bones. */ +void BKE_pose_apply_action_all_bones(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context); + +void BKE_pose_apply_action_blend(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context, + float blend_factor); void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3]); void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3]); diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h index d1f543b1f38..50eb2859279 100644 --- a/source/blender/blenkernel/BKE_asset.h +++ b/source/blender/blenkernel/BKE_asset.h @@ -26,6 +26,7 @@ extern "C" { #endif +struct AssetLibraryReference; struct BlendDataReader; struct BlendWriter; struct ID; @@ -45,6 +46,8 @@ struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(struct AssetMetaData * const char *name); void BKE_asset_metadata_tag_remove(struct AssetMetaData *asset_data, struct AssetTag *tag); +void BKE_asset_library_reference_init_default(struct AssetLibraryReference *library_ref); + struct PreviewImage *BKE_asset_metadata_preview_get_from_id(const struct AssetMetaData *asset_data, const struct ID *owner_id); diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 6a1f1feb14f..5fda30224c6 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -39,8 +39,8 @@ struct ReportList; /* Attribute.domain */ /** - * \warning: Careful when changing existing items. Arrays may be initialized from this (e.g. - * #DATASET_layout_hierarchy). + * \warning Careful when changing existing items. + * Arrays may be initialized from this (e.g. #DATASET_layout_hierarchy). */ typedef enum AttributeDomain { ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */ diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index d5baeb08ccc..28903c4787c 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,13 +39,13 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 7 +#define BLENDER_FILE_SUBVERSION 12 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file * was written with too new a version. */ -#define BLENDER_FILE_MIN_VERSION 290 -#define BLENDER_FILE_MIN_SUBVERSION 0 +#define BLENDER_FILE_MIN_VERSION 300 +#define BLENDER_FILE_MIN_SUBVERSION 11 /** User readable version string. */ const char *BKE_blender_version_string(void); diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 78908908343..8be2fcbdb83 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -218,7 +218,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data, ThreadMutex *mesh_eval_mutex); BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, - struct Mesh *mesh, + const struct Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type); diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index f47cdf32ca0..0326386e5c1 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -76,6 +76,7 @@ struct Collection *BKE_collection_duplicate(struct Main *bmain, /* Master Collection for Scene */ +#define BKE_SCENE_COLLECTION_NAME "Scene Collection" struct Collection *BKE_collection_master_add(void); /* Collection Objects */ diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 50aa6027840..8917580689d 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -23,6 +23,9 @@ * \ingroup bke */ +/* XXX temporary, until AssetHandle is designed properly and queries can return a pointer to it. */ +#include "DNA_asset_types.h" + #include "DNA_listBase.h" #include "DNA_object_enums.h" #include "RNA_types.h" @@ -357,6 +360,9 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list); int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list); int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list); +const struct AssetLibraryReference *CTX_wm_asset_library(const bContext *C); +struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid); + bool CTX_wm_interface_locked(const bContext *C); /* Gets pointer to the dependency graph. diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index d861baba14d..a2544e43c3d 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -112,7 +112,7 @@ enum { }; /* How to map a source layer to a destination layer, for types supporting multi-layers. - * Note: if no matching layer can be found, it will be created. */ + * NOTE: if no matching layer can be found, it will be created. */ enum { DT_LAYERS_ACTIVE_DST = -1, /* Only for DT_LAYERS_FROMSEL_ACTIVE. */ DT_LAYERS_NAME_DST = -2, diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 8b5fdf69bb0..f4221d57428 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -30,6 +30,7 @@ extern "C" { struct BlendDataReader; struct BlendWriter; +struct ID; struct ListBase; struct MDeformVert; struct MEdge; @@ -38,6 +39,18 @@ struct MPoly; struct Object; struct bDeformGroup; +bool BKE_object_supports_vertex_groups(const struct Object *ob); +const struct ListBase *BKE_object_defgroup_list(const struct Object *ob); +struct ListBase *BKE_object_defgroup_list_mutable(struct Object *ob); + +int BKE_object_defgroup_count(const struct Object *ob); +int BKE_object_defgroup_active_index_get(const struct Object *ob); +void BKE_object_defgroup_active_index_set(struct Object *ob, const int new_index); + +const struct ListBase *BKE_id_defgroup_list_get(const struct ID *id); +struct ListBase *BKE_id_defgroup_list_get_mutable(struct ID *id); +int BKE_id_defgroup_name_index(const struct ID *id, const char *name); + struct bDeformGroup *BKE_object_defgroup_new(struct Object *ob, const char *name); void BKE_defgroup_copy_list(struct ListBase *outbase, const struct ListBase *inbase); struct bDeformGroup *BKE_defgroup_duplicate(const struct bDeformGroup *ingroup); @@ -171,6 +184,7 @@ void BKE_defvert_blend_write(struct BlendWriter *writer, int count, struct MDefo void BKE_defvert_blend_read(struct BlendDataReader *reader, int count, struct MDeformVert *mdverts); +void BKE_defbase_blend_write(struct BlendWriter *writer, const ListBase *defbase); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index e31a0a16408..ffd8ac42c63 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -24,7 +24,7 @@ * only concerned with low level operations on the #BMEditMesh structure. */ -#include "BKE_customdata.h" +#include "DNA_customdata_types.h" #include "bmesh.h" #ifdef __cplusplus @@ -32,8 +32,8 @@ extern "C" { #endif struct BMLoop; -struct BMesh; struct BMPartialUpdate; +struct BMesh; struct BMeshCalcTessellation_Params; struct BoundBox; struct Depsgraph; @@ -44,38 +44,39 @@ struct Scene; /** * This structure is used for mesh edit-mode. * - * through this, you get access to both the edit #BMesh, - * its tessellation, and various stuff that doesn't belong in the BMesh - * struct itself. + * Through this, you get access to both the edit #BMesh, its tessellation, + * and various data that doesn't belong in the #BMesh struct itself + * (mostly related to mesh evaluation). * - * the entire derivedmesh and modifier system works with this structure, - * and not BMesh. Mesh->edit_bmesh stores a pointer to this structure. */ + * The entire modifier system works with this structure, and not #BMesh. + * #Mesh.edit_bmesh stores a pointer to this structure. */ typedef struct BMEditMesh { struct BMesh *bm; - /* This is for undoing failed operations. */ - struct BMEditMesh *emcopy; - int emcopyusers; - - /* we store tessellations as triplets of three loops, - * which each define a triangle. */ + /** + * Face triangulation (tessellation) is stored as triplets of three loops, + * which each define a triangle. + * + * \see #MLoopTri as the documentation gives useful hints that apply to this data too. + */ struct BMLoop *(*looptris)[3]; int tottri; struct Mesh *mesh_eval_final, *mesh_eval_cage; - /** Cached cage bounding box for selection. */ + /** Cached cage bounding box of `mesh_eval_cage` for selection. */ struct BoundBox *bb_cage; /** Evaluated mesh data-mask. */ CustomData_MeshMasks lastDataMask; - /* Selection mode. */ + /** Selection mode (#SCE_SELECT_VERTEX, #SCE_SELECT_EDGE & #SCE_SELECT_FACE). */ short selectmode; + /** The active material (assigned to newly created faces). */ short mat_nr; - /* Temp variables for x-mirror editing. */ - int mirror_cdlayer; /* -1 is invalid */ + /** Temp variables for x-mirror editing (-1 when the layer does not exist). */ + int mirror_cdlayer; /** * ID data is older than edit-mode data. @@ -98,11 +99,11 @@ void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em, void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em); -BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate); +BMEditMesh *BKE_editmesh_create(BMesh *bm); BMEditMesh *BKE_editmesh_copy(BMEditMesh *em); BMEditMesh *BKE_editmesh_from_object(struct Object *ob); -void BKE_editmesh_free_derivedmesh(BMEditMesh *em); -void BKE_editmesh_free(BMEditMesh *em); +void BKE_editmesh_free_derived_caches(BMEditMesh *em); +void BKE_editmesh_free_data(BMEditMesh *em); float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph, struct BMEditMesh *em, diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 82c9a31dfce..42e9ce82278 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -35,12 +35,12 @@ #include "BKE_geometry_set.h" struct Collection; +struct Curve; +struct CurveEval; struct Mesh; struct Object; struct PointCloud; struct Volume; -struct Curve; -struct CurveEval; enum class GeometryOwnershipType { /* The geometry is owned. This implies that it can be changed. */ @@ -325,10 +325,6 @@ class MeshComponent : public GeometryComponent { private: Mesh *mesh_ = nullptr; GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned; - /* Due to historical design choices, vertex group data is stored in the mesh, but the vertex - * group names are stored on an object. Since we don't have an object here, we copy over the - * names into this map. */ - blender::Map<std::string, int> vertex_group_names_; public: MeshComponent(); @@ -338,14 +334,8 @@ class MeshComponent : public GeometryComponent { void clear(); bool has_mesh() const; void replace(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned); - void replace_mesh_but_keep_vertex_group_names( - Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned); Mesh *release(); - void copy_vertex_group_names_from_object(const struct Object &object); - const blender::Map<std::string, int> &vertex_group_names() const; - blender::Map<std::string, int> &vertex_group_names(); - const Mesh *get_for_read() const; Mesh *get_for_write(); diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 657e66729e1..92e70b41e7b 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -49,22 +49,22 @@ struct bGPDlayer_Mask; struct bGPDstroke; struct bGPdata; -#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)) +#define GPENCIL_SIMPLIFY(scene) (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE) #define GPENCIL_SIMPLIFY_ONPLAY(playing) \ (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \ ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0)) #define GPENCIL_SIMPLIFY_FILL(scene, playing) \ - ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && GPENCIL_SIMPLIFY(scene) && \ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL))) #define GPENCIL_SIMPLIFY_MODIF(scene) \ ((GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER))) #define GPENCIL_SIMPLIFY_FX(scene, playing) \ - ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && GPENCIL_SIMPLIFY(scene) && \ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX))) #define GPENCIL_SIMPLIFY_TINT(scene) \ - ((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT)) + (GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT)) #define GPENCIL_SIMPLIFY_AA(scene) \ - ((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_AA)) + (GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_AA)) /* Vertex Color macros. */ #define GPENCIL_USE_VERTEX_COLOR(toolsettings) \ @@ -154,17 +154,6 @@ bool BKE_gpencil_merge_materials(struct Object *ob, /* statistics functions */ void BKE_gpencil_stats_update(struct bGPdata *gpd); -/* Utilities for creating and populating GP strokes */ -/* - Number of values defining each point in the built-in data - * buffers for primitives (e.g. 2D Monkey) - */ -#define GP_PRIM_DATABUF_SIZE 5 - -void BKE_gpencil_stroke_add_points(struct bGPDstroke *gps, - const float *array, - const int totpoints, - const float mat[4][4]); - struct bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness); struct bGPDstroke *BKE_gpencil_stroke_add( struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head); @@ -282,20 +271,25 @@ bool BKE_gpencil_from_image(struct SpaceImage *sima, const float size, const bool mask); -/* Iterator */ +/* Iterators */ /* frame & stroke are NULL if it is a layer callback. */ typedef void (*gpIterCb)(struct bGPDlayer *layer, struct bGPDframe *frame, struct bGPDstroke *stroke, void *thunk); -void BKE_gpencil_visible_stroke_iter(struct ViewLayer *view_layer, - struct Object *ob, +void BKE_gpencil_visible_stroke_iter(struct bGPdata *gpd, gpIterCb layer_cb, gpIterCb stroke_cb, - void *thunk, - bool do_onion, - int cfra); + void *thunk); + +void BKE_gpencil_visible_stroke_advanced_iter(struct ViewLayer *view_layer, + struct Object *ob, + gpIterCb layer_cb, + gpIterCb stroke_cb, + void *thunk, + bool do_onion, + int cfra); extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd); extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd); diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index 8fbc2112c77..33524e47473 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -325,6 +325,12 @@ struct bGPDframe *BKE_gpencil_frame_retime_get(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct bGPDlayer *gpl); +int BKE_gpencil_time_modifier_cfra(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob, + struct bGPDlayer *gpl, + const int cfra, + const bool is_render); void BKE_gpencil_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase); void BKE_gpencil_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 58b8d19abaa..70d65e02246 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -71,7 +71,7 @@ void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock * char *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb); /* conversion functions */ -/* Note: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */ +/* NOTE: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */ void BKE_keyblock_update_from_lattice(struct Lattice *lt, struct KeyBlock *kb); void BKE_keyblock_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb); void BKE_keyblock_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt); diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 27076d908e7..c6658ff424a 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -42,8 +42,8 @@ extern "C" { #endif -struct Collection; struct BlendFileReadReport; +struct Collection; struct ID; struct IDOverrideLibrary; struct IDOverrideLibraryProperty; diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h index e806dedc14c..c90a284c204 100644 --- a/source/blender/blenkernel/BKE_lib_remap.h +++ b/source/blender/blenkernel/BKE_lib_remap.h @@ -91,7 +91,7 @@ enum { ID_REMAP_FORCE_USER_REFCOUNT = 1 << 8, }; -/* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, +/* NOTE: Requiring new_id to be non-null, this *may* not be the case ultimately, * but makes things simpler for now. */ void BKE_libblock_remap_locked(struct Main *bmain, void *old_idv, diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 2c6e5ed3873..ed930fe539d 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -100,7 +100,7 @@ typedef struct MainIDRelations { /* Mapping from an ID pointer to all of its parents (IDs using it) and children (IDs it uses). * Values are `MainIDRelationsEntry` pointers. */ struct GHash *relations_from_pointers; - /* Note: we could add more mappings when needed (e.g. from session uuid?). */ + /* NOTE: we could add more mappings when needed (e.g. from session uuid?). */ short flag; diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 8d76a025e87..12560ebed7b 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -299,7 +299,7 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop, struct MLoopTri *mlooptri, const float (*poly_normals)[3]); -/* *** mesh_normals.c *** */ +/* *** mesh_normals.cc *** */ void BKE_mesh_calc_normals_mapping_simple(struct Mesh *me); void BKE_mesh_calc_normals_mapping(struct MVert *mverts, @@ -494,7 +494,7 @@ void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh, void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loopnors)[3]); void BKE_mesh_set_custom_normals_from_vertices(struct Mesh *mesh, float (*r_custom_vertnors)[3]); -/* *** mesh_evaluate.c *** */ +/* *** mesh_evaluate.cc *** */ void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly, const struct MLoop *loopstart, diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index 02f8af6443c..7f8f028c26b 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -115,7 +115,7 @@ enum { MREMAP_USE_INTERP, /* ***** Target's loops ***** */ - /* Note: when islands are given to loop mapping func, + /* NOTE: when islands are given to loop mapping func, * all loops from the same destination face will always be mapped * to loops of source faces within a same island, regardless of mapping mode. */ MREMAP_MODE_LOOP = 1 << 26, diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 67c87e96aff..3efbef94081 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -45,7 +45,7 @@ void BKE_mesh_runtime_reset(struct Mesh *mesh); void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, const int flag); int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh); void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh); -const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh); +const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh); bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh); bool BKE_mesh_runtime_clear_edit_data(struct Mesh *mesh); bool BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh); diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index aed8c44a031..b223d3872ff 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -27,6 +27,7 @@ typedef enum eMeshBatchDirtyMode { BKE_MESH_BATCH_DIRTY_SELECT, BKE_MESH_BATCH_DIRTY_SELECT_PAINT, BKE_MESH_BATCH_DIRTY_SHADING, + BKE_MESH_BATCH_DIRTY_DEFORM, BKE_MESH_BATCH_DIRTY_UVEDIT_ALL, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT, } eMeshBatchDirtyMode; diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index af238fda659..cf8848fe607 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -156,10 +156,10 @@ enum eNlaTime_ConvertModes { /* convert from global time to strip time - for evaluation */ NLATIME_CONVERT_EVAL = 0, /* convert from global time to strip time - for editing corrections */ - // XXX old 0 invert + /* XXX: old 0 invert. */ NLATIME_CONVERT_UNMAP, /* convert from strip time to global time */ - // xxx old 1 invert + /* XXX: old 1 invert. */ NLATIME_CONVERT_MAP, }; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index e390919c128..6d57106435b 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -144,7 +144,10 @@ typedef void *SocketGetCPPValueFunction; * Defines the appearance and behavior of a socket in the UI. */ typedef struct bNodeSocketType { - char idname[64]; /* identifier name */ + /* Identifier name */ + char idname[64]; + /* Type label */ + char label[64]; void (*draw)(struct bContext *C, struct uiLayout *layout, @@ -420,7 +423,7 @@ typedef struct bNodeTreeType { void (*node_add_init)(struct bNodeTree *ntree, struct bNode *bnode); /* Check if the socket type is valid for this tree type. */ - bool (*valid_socket_type)(enum eNodeSocketDatatype socket_type, struct bNodeTreeType *ntreetype); + bool (*valid_socket_type)(struct bNodeTreeType *ntreetype, struct bNodeSocketType *socket_type); /* RNA integration */ ExtensionRNA rna_ext; @@ -562,8 +565,12 @@ void nodeRegisterSocketType(struct bNodeSocketType *stype); void nodeUnregisterSocketType(struct bNodeSocketType *stype); bool nodeSocketIsRegistered(struct bNodeSocket *sock); struct GHashIterator *nodeSocketTypeGetIterator(void); +const char *nodeSocketTypeLabel(const bNodeSocketType *stype); + +bool nodeIsStaticSocketType(const struct bNodeSocketType *stype); const char *nodeStaticSocketType(int type, int subtype); const char *nodeStaticSocketInterfaceType(int type, int subtype); +const char *nodeStaticSocketLabel(int type, int subtype); /* helper macros for iterating over node types */ #define NODE_SOCKET_TYPES_BEGIN(stype) \ @@ -613,7 +620,11 @@ struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, const char *name); void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock); void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node); -void nodeModifySocketType( +void nodeModifySocketType(struct bNodeTree *ntree, + struct bNode *node, + struct bNodeSocket *sock, + const char *idname); +void nodeModifySocketTypeStatic( struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, int type, int subtype); struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname); @@ -973,7 +984,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, /** \name Shader Nodes * \{ */ -/* note: types are needed to restore callbacks, don't change values */ +/* NOTE: types are needed to restore callbacks, don't change values. */ /* range 1 - 100 is reserved for common nodes */ /* using toolbox, we add node groups by assuming the values below * don't exceed NODE_GROUP_MENU for now. */ @@ -1140,7 +1151,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree, // #define RRES_OUT_SUBSURFACE_COLOR 30 // #define RRES_OUT_DEBUG 31 -/* note: types are needed to restore callbacks, don't change values */ +/* NOTE: types are needed to restore callbacks, don't change values. */ #define CMP_NODE_VIEWER 201 #define CMP_NODE_RGB 202 #define CMP_NODE_VALUE 203 @@ -1271,6 +1282,11 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree, #define CMP_CRYPTOMATTE_SRC_RENDER 0 #define CMP_CRYPTOMATTE_SRC_IMAGE 1 +/* Default SMAA configuration values. */ +#define CMP_DEFAULT_SMAA_THRESHOLD 1.0f +#define CMP_DEFAULT_SMAA_CONTRAST_LIMIT 0.2f +#define CMP_DEFAULT_SMAA_CORNER_ROUNDING 0.25f + /* API */ void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, @@ -1414,7 +1430,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_VOLUME_TO_MESH 1026 #define GEO_NODE_ATTRIBUTE_COMBINE_XYZ 1027 #define GEO_NODE_ATTRIBUTE_SEPARATE_XYZ 1028 -#define GEO_NODE_SUBDIVIDE 1029 +#define GEO_NODE_MESH_SUBDIVIDE 1029 #define GEO_NODE_ATTRIBUTE_REMOVE 1030 #define GEO_NODE_ATTRIBUTE_CONVERT 1031 #define GEO_NODE_MESH_PRIMITIVE_CUBE 1032 @@ -1452,8 +1468,12 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER 1064 #define GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT 1065 #define GEO_NODE_CURVE_PRIMITIVE_CIRCLE 1066 -#define GEO_NODE_ATTRIBUTE_GET 1067 -#define GEO_NODE_ATTRIBUTE_SET 1068 +#define GEO_NODE_VIEWER 1067 +#define GEO_NODE_CURVE_PRIMITIVE_LINE 1068 +#define GEO_NODE_CURVE_ENDPOINTS 1069 +#define GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL 1070 +#define GEO_NODE_ATTRIBUTE_GET 1071 +#define GEO_NODE_ATTRIBUTE_SET 1072 /** \} */ @@ -1466,6 +1486,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define FN_NODE_RANDOM_FLOAT 1206 #define FN_NODE_INPUT_VECTOR 1207 #define FN_NODE_INPUT_STRING 1208 +#define FN_NODE_FLOAT_TO_INT 1209 /** \} */ diff --git a/source/blender/blenkernel/BKE_node_ui_storage.hh b/source/blender/blenkernel/BKE_node_ui_storage.hh deleted file mode 100644 index 4ec165aad8c..00000000000 --- a/source/blender/blenkernel/BKE_node_ui_storage.hh +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#pragma once - -#include <mutex> - -#include "BLI_hash.hh" -#include "BLI_map.hh" -#include "BLI_session_uuid.h" -#include "BLI_set.hh" - -#include "DNA_ID.h" -#include "DNA_customdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_session_uuid_types.h" - -#include "BKE_attribute.h" - -struct ModifierData; -struct Object; -struct bNode; -struct bNodeTree; -struct bContext; - -/** - * Contains the context necessary to determine when to display settings for a certain node tree - * that may be used for multiple modifiers and objects. The object name and modifier session UUID - * are used instead of pointers because they are re-allocated between evaluations. - * - * \note This does not yet handle the context of nested node trees. - */ -class NodeTreeEvaluationContext { - private: - std::string object_name_; - SessionUUID modifier_session_uuid_; - - public: - NodeTreeEvaluationContext(const Object &object, const ModifierData &modifier) - { - object_name_ = reinterpret_cast<const ID &>(object).name; - modifier_session_uuid_ = modifier.session_uuid; - } - - uint64_t hash() const - { - return blender::get_default_hash_2(object_name_, modifier_session_uuid_); - } - - friend bool operator==(const NodeTreeEvaluationContext &a, const NodeTreeEvaluationContext &b) - { - return a.object_name_ == b.object_name_ && - BLI_session_uuid_is_equal(&a.modifier_session_uuid_, &b.modifier_session_uuid_); - } -}; - -enum class NodeWarningType { - Error, - Warning, - Info, -}; - -struct NodeWarning { - NodeWarningType type; - std::string message; -}; - -struct AvailableAttributeInfo { - std::string name; - AttributeDomain domain; - CustomDataType data_type; - - uint64_t hash() const - { - return blender::get_default_hash(name); - } - - friend bool operator==(const AvailableAttributeInfo &a, const AvailableAttributeInfo &b) - { - return a.name == b.name; - } -}; - -struct NodeUIStorage { - blender::Vector<NodeWarning> warnings; - blender::Set<AvailableAttributeInfo> attribute_hints; -}; - -struct NodeTreeUIStorage { - std::mutex mutex; - blender::Map<NodeTreeEvaluationContext, blender::Map<std::string, NodeUIStorage>> context_map; - - /** - * Attribute search uses this to store the fake info for the string typed into a node, in order - * to pass the info to the execute callback that sets node socket values. This is mutable since - * we can count on only one attribute search being open at a time, and there is no real data - * stored here. - */ - mutable AvailableAttributeInfo dummy_info_for_search; -}; - -const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C, - const bNodeTree &ntree, - const bNode &node); - -void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree, - const NodeTreeEvaluationContext &context); - -void BKE_nodetree_error_message_add(bNodeTree &ntree, - const NodeTreeEvaluationContext &context, - const bNode &node, - const NodeWarningType type, - std::string message); - -void BKE_nodetree_attribute_hint_add(bNodeTree &ntree, - const NodeTreeEvaluationContext &context, - const bNode &node, - const blender::StringRef attribute_name, - const AttributeDomain domain, - const CustomDataType data_type); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index af9f5d7bf22..a16822fd7dd 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -70,10 +70,6 @@ void BKE_object_free_curve_cache(struct Object *ob); void BKE_object_free_derived_caches(struct Object *ob); void BKE_object_free_caches(struct Object *object); -void BKE_object_preview_geometry_set_add(struct Object *ob, - const uint64_t key, - struct GeometrySet *geometry_set); - void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd); void BKE_object_modifier_gpencil_hook_reset(struct Object *ob, struct HookGpencilModifierData *hmd); @@ -243,7 +239,7 @@ void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis void BKE_object_empty_draw_type_set(struct Object *ob, const int value); void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set); -void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval); +void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval); void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph, struct Scene *scene, @@ -378,6 +374,10 @@ void BKE_object_runtime_free_data(struct Object *object); void BKE_object_batch_cache_dirty_tag(struct Object *ob); void BKE_object_data_batch_cache_dirty_tag(struct ID *object_data); +void BKE_object_data_eval_batch_cache_dirty_tag(struct Depsgraph *depsgraph, + struct ID *object_data); +void BKE_object_data_eval_batch_cache_deform_tag(struct Depsgraph *depsgraph, + struct ID *object_data); /* this function returns a superset of the scenes selection based on relationships */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 97e5698d6f9..056a7e2d897 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -329,7 +329,7 @@ bool BKE_pbvh_is_deformed(struct PBVH *pbvh); * - allow the compiler to eliminate dead code and variables * - spend most of the time in the relatively simple inner loop */ -/* note: PBVH_ITER_ALL does not skip hidden vertices, +/* NOTE: PBVH_ITER_ALL does not skip hidden vertices, * PBVH_ITER_UNIQUE does */ #define PBVH_ITER_ALL 0 #define PBVH_ITER_UNIQUE 1 diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 8731162b720..3f99a0dc793 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -45,7 +45,7 @@ extern "C" { #define PTCACHE_RESET_OUTDATED 2 /* #define PTCACHE_RESET_FREE 3 */ /*UNUSED*/ -/* Add the blendfile name after blendcache_ */ +/* Add the blend-file name after `blendcache_`. */ #define PTCACHE_EXT ".bphys" #define PTCACHE_PATH "blendcache_" diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 9792f819bf9..6d58e165ea3 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -124,14 +124,16 @@ bool BKE_scene_camera_switch_update(struct Scene *scene); const char *BKE_scene_find_marker_name(const struct Scene *scene, int frame); const char *BKE_scene_find_last_marker_name(const struct Scene *scene, int frame); -int BKE_scene_frame_snap_by_seconds(struct Scene *scene, double interval_in_seconds, int cfra); +int BKE_scene_frame_snap_by_seconds(struct Scene *scene, double interval_in_seconds, int frame); /* checks for cycle, returns 1 if it's all OK */ bool BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce); +float BKE_scene_ctime_get(const struct Scene *scene); +float BKE_scene_frame_to_ctime(const struct Scene *scene, const int frame); + float BKE_scene_frame_get(const struct Scene *scene); -float BKE_scene_frame_to_ctime(const struct Scene *scene, const float frame); -void BKE_scene_frame_set(struct Scene *scene, double cfra); +void BKE_scene_frame_set(struct Scene *scene, float frame); struct TransformOrientationSlot *BKE_scene_orientation_slot_get_from_flag(struct Scene *scene, int flag); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index fed155626ed..0b08bbfeff5 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -332,6 +332,9 @@ typedef void (*uiListFilterItemsFunc)(struct uiList *ui_list, struct PointerRNA *, const char *propname); +/* Listen to notifiers. Only for lists defined in C. */ +typedef void (*uiListListener)(struct uiList *ui_list, wmRegionListenerParams *params); + typedef struct uiListType { struct uiListType *next, *prev; @@ -341,6 +344,9 @@ typedef struct uiListType { uiListDrawFilterFunc draw_filter; uiListFilterItemsFunc filter_items; + /* For lists defined in C only. */ + uiListListener listener; + /* RNA integration */ ExtensionRNA rna_ext; } uiListType; diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index 1aac2e311e3..f85e62768f7 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -337,6 +337,18 @@ class BezierSpline final : public Spline { blender::MutableSpan<blender::float3> positions) const; bool segment_is_vector(const int start_index) const; + /** See comment and diagram for #calculate_segment_insertion. */ + struct InsertResult { + blender::float3 handle_prev; + blender::float3 left_handle; + blender::float3 position; + blender::float3 right_handle; + blender::float3 handle_next; + }; + InsertResult calculate_segment_insertion(const int index, + const int next_index, + const float parameter); + private: void correct_end_tangents() const final; void copy_settings(Spline &dst) const final; diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index 70b8743bcd2..59b1c2b28d9 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -145,7 +145,7 @@ typedef struct StudioLight { void BKE_studiolight_init(void); void BKE_studiolight_free(void); -void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4]); +void BKE_studiolight_default(SolidLight lights[4], float light_ambient[3]); struct StudioLight *BKE_studiolight_find(const char *name, int flag); struct StudioLight *BKE_studiolight_findindex(int index, int flag); struct StudioLight *BKE_studiolight_find_default(int flag); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index c2544c06514..47145a7d6bd 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -161,7 +161,7 @@ struct MovieTrackingMarker *BKE_tracking_marker_get_exact(struct MovieTrackingTr struct MovieTrackingMarker *BKE_tracking_marker_ensure(struct MovieTrackingTrack *track, int framenr); -/* Get marker position, possibly interpolating interpolating gap between keyframed/tracked markers. +/* Get marker position, possibly interpolating gap between key-framed/tracked markers. * * The result marker frame number is set to the requested frame number. Its flags are 0 if the * marker is interpolated, and is set to original marker flag if there were no interpolation diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index efac5d9097f..2973a432723 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -162,6 +162,13 @@ typedef enum UndoTypeFlags { * \note Callback is still supposed to properly deal with a NULL context pointer. */ UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE = 1 << 0, + + /** + * When the active undo step is of this type, it must be read before loading other undo steps. + * + * This is typically used for undo systems that store both before/after states. + */ + UNDOTYPE_FLAG_DECODE_ACTIVE_STEP = 1 << 1, } UndoTypeFlags; /* Expose since we need to perform operations on specific undo types (rarely). */ diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h index cf755827a6c..d9333996632 100644 --- a/source/blender/blenkernel/BKE_volume.h +++ b/source/blender/blenkernel/BKE_volume.h @@ -214,7 +214,7 @@ auto BKE_volume_grid_type_operation(const VolumeGridType grid_type, OpType &&op) } /* Should never be called. */ - BLI_assert(!"should never be reached"); + BLI_assert_msg(0, "should never be reached"); return op.template operator()<openvdb::FloatGrid>(); } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b66cb9e224d..527996ee46d 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -93,7 +93,7 @@ set(SRC intern/boids.c intern/bpath.c intern/brush.c - intern/bvhutils.c + intern/bvhutils.cc intern/cachefile.c intern/callbacks.c intern/camera.c @@ -143,7 +143,7 @@ set(SRC intern/geometry_set_instances.cc intern/gpencil.c intern/gpencil_curve.c - intern/gpencil_geom.c + intern/gpencil_geom.cc intern/gpencil_modifier.c intern/hair.c intern/icons.cc @@ -184,13 +184,13 @@ set(SRC intern/mesh.c intern/mesh_boolean_convert.cc intern/mesh_convert.c - intern/mesh_evaluate.c + intern/mesh_evaluate.cc intern/mesh_fair.cc intern/mesh_iterators.c intern/mesh_mapping.c intern/mesh_merge.c intern/mesh_mirror.c - intern/mesh_normals.c + intern/mesh_normals.cc intern/mesh_remap.c intern/mesh_remesh_voxel.c intern/mesh_runtime.c @@ -215,7 +215,6 @@ set(SRC intern/multires_versioning.c intern/nla.c intern/node.cc - intern/node_ui_storage.cc intern/object.c intern/object_deform.c intern/object_dupli.cc @@ -331,7 +330,6 @@ set(SRC BKE_customdata_file.h BKE_data_transfer.h BKE_deform.h - BKE_spline.hh BKE_displist.h BKE_displist_tangent.h BKE_duplilist.h @@ -399,7 +397,6 @@ set(SRC BKE_multires.h BKE_nla.h BKE_node.h - BKE_node_ui_storage.hh BKE_object.h BKE_object_deform.h BKE_object_facemap.h @@ -423,6 +420,7 @@ set(SRC BKE_softbody.h BKE_sound.h BKE_speaker.h + BKE_spline.hh BKE_studiolight.h BKE_subdiv.h BKE_subdiv_ccg.h @@ -767,6 +765,7 @@ add_dependencies(bf_blenkernel bf_dna) if(WITH_GTESTS) set(TEST_SRC + intern/action_test.cc intern/armature_test.cc intern/cryptomatte_test.cc intern/fcurve_test.cc diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 7063c670ee4..ba8cf8debe9 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -829,7 +829,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, } if (do_loop_normals) { - /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */ + /* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). */ BKE_mesh_calc_normals_split(mesh_final); BKE_mesh_tessface_clear(mesh_final); } @@ -900,7 +900,7 @@ static Mesh *prepare_geometry_set_for_mesh_modifier(Mesh *mesh, GeometrySet &r_g { /* Add the mesh to the geometry set. */ MeshComponent &mesh_component = r_geometry_set.get_component_for_write<MeshComponent>(); - mesh_component.replace_mesh_but_keep_vertex_group_names(mesh, GeometryOwnershipType::Editable); + mesh_component.replace(mesh, GeometryOwnershipType::Editable); } { /* Combine mesh and all instances into a single mesh that can be passed to the modifier. */ @@ -948,8 +948,7 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md, /* Replace only the mesh rather than the whole component, because the entire #MeshComponent * might have been replaced by data from a different object in the node tree, which means the * component contains vertex group name data for that object that should not be removed. */ - mesh_component.replace_mesh_but_keep_vertex_group_names(input_mesh, - GeometryOwnershipType::Editable); + mesh_component.replace(input_mesh, GeometryOwnershipType::Editable); /* Let the modifier change the geometry set. */ mti->modifyGeometrySet(md, &mectx, &geometry_set); @@ -993,12 +992,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* This geometry set contains the non-mesh data that might be generated by modifiers. */ GeometrySet geometry_set_final; - /* Add the initial mesh component, with a copy of the vertex group names from the object, - * since they need to be stored in the geometry set for evaluation. */ - MeshComponent &initial_mesh_component = - geometry_set_final.get_component_for_write<MeshComponent>(); - initial_mesh_component.copy_vertex_group_names_from_object(*ob); - BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); /* Deformed vertex locations array. Deform only modifier need this type of @@ -1076,10 +1069,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, continue; } - if (mti->dependsOnTime && mti->dependsOnTime(md)) { - continue; - } - if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { if (!deformed_verts) { deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); @@ -1173,10 +1162,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, continue; } - if (mti->dependsOnTime && mti->dependsOnTime(md)) { - continue; - } - /* Add orco mesh as layer if needed by this modifier. */ if (mesh_final && mesh_orco && mti->requiredDataMask) { CustomData_MeshMasks mask = {0}; @@ -1412,7 +1397,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, * we need to apply these back onto the Mesh. If we have no * Mesh then we need to build one. */ if (mesh_final == nullptr) { - /* Note: this check on cdmask is a bit dodgy, it handles the issue at stake here (see T68211), + /* NOTE: this check on cdmask is a bit dodgy, it handles the issue at stake here (see T68211), * but other cases might require similar handling? * Could be a good idea to define a proper CustomData_MeshMask for that then. */ if (deformed_verts == nullptr && allow_shared_mesh && @@ -1610,12 +1595,6 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, /* This geometry set contains the non-mesh data that might be generated by modifiers. */ GeometrySet geometry_set_final; - /* Add the initial mesh component, with a copy of the vertex group names from the object, - * since they need to be stored in the geometry set for evaluation. */ - MeshComponent &initial_mesh_component = - geometry_set_final.get_component_for_write<MeshComponent>(); - initial_mesh_component.copy_vertex_group_names_from_object(*ob); - /* Deformed vertex locations array. Deform only modifier need this type of * float array rather than MVert*. Tracked along with mesh_final as an * optimization to avoid copying coordinates back and forth if there are @@ -1959,8 +1938,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph, /* Add the final mesh as read-only non-owning component to the geometry set. */ MeshComponent &mesh_component = geometry_set_eval->get_component_for_write<MeshComponent>(); - mesh_component.replace_mesh_but_keep_vertex_group_names(mesh_eval, - GeometryOwnershipType::ReadOnly); + mesh_component.replace(mesh_eval, GeometryOwnershipType::ReadOnly); ob->runtime.geometry_set_eval = geometry_set_eval; ob->runtime.mesh_deform_eval = mesh_deform_eval; @@ -1998,7 +1976,7 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph, BKE_sculpt_update_object_before_eval(obedit); } - BKE_editmesh_free_derivedmesh(em); + BKE_editmesh_free_derived_caches(em); Mesh *me_cage; Mesh *me_final; @@ -2426,7 +2404,7 @@ static void dm_debug_info_layers(DynStr *dynstr, for (type = 0; type < CD_NUMTYPES; type++) { if (CustomData_has_layer(cd, type)) { - /* note: doesn't account for multiple layers */ + /* NOTE: doesn't account for multiple layers. */ const char *name = CustomData_layertype_name(type); const int size = CustomData_sizeof(type); const void *pt = getElemDataArray(dm, type); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index fdf3558abed..d55f023d209 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -120,7 +120,7 @@ static void action_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, for (fcurve_src = action_src->curves.first; fcurve_src; fcurve_src = fcurve_src->next) { /* Duplicate F-Curve. */ - /* XXX TODO pass subdata flag? + /* XXX TODO: pass subdata flag? * But surprisingly does not seem to be doing any ID refcounting... */ fcurve_dst = BKE_fcurve_copy(fcurve_src); @@ -497,9 +497,8 @@ void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve) } /* Reconstruct group channel pointers. - * Assumes that the channels are still in the proper order, i.e. that channels of the same group - * are adjacent in the act->channels list. It also assumes that the groups - * referred to by the FCurves are already in act->groups. + * Assumes that the groups referred to by the FCurves are already in act->groups. + * Reorders the main channel list to match group order. */ void BKE_action_groups_reconstruct(bAction *act) { @@ -514,23 +513,30 @@ void BKE_action_groups_reconstruct(bAction *act) BLI_listbase_clear(&group->channels); } - bActionGroup *grp; - bActionGroup *last_grp = NULL; - LISTBASE_FOREACH (FCurve *, fcurve, &act->curves) { - if (fcurve->grp == NULL) { - continue; - } + /* Sort the channels into the group lists, destroying the act->curves list. */ + ListBase ungrouped = {NULL, NULL}; - grp = fcurve->grp; - if (last_grp != grp) { - /* If this is the first time we see this group, this must be the first channel. */ - grp->channels.first = fcurve; + LISTBASE_FOREACH_MUTABLE (FCurve *, fcurve, &act->curves) { + if (fcurve->grp) { + BLI_assert(BLI_findindex(&act->groups, fcurve->grp) >= 0); + + BLI_addtail(&fcurve->grp->channels, fcurve); + } + else { + BLI_addtail(&ungrouped, fcurve); } + } + + /* Recombine into the main list. */ + BLI_listbase_clear(&act->curves); - /* This is the last channel, until it's overwritten by a later iteration. */ - grp->channels.last = fcurve; - last_grp = grp; + LISTBASE_FOREACH (bActionGroup *, group, &act->groups) { + /* Copy the list header to preserve the pointers in the group. */ + ListBase tmp = group->channels; + BLI_movelisttolist(&act->curves, &tmp); } + + BLI_movelisttolist(&act->curves, &ungrouped); } /* Remove the given channel from all groups */ diff --git a/source/blender/blenkernel/intern/action_mirror.c b/source/blender/blenkernel/intern/action_mirror.c index 69e0091444b..48472dfc9b3 100644 --- a/source/blender/blenkernel/intern/action_mirror.c +++ b/source/blender/blenkernel/intern/action_mirror.c @@ -322,6 +322,25 @@ static void action_flip_pchan(Object *ob_arm, /* Move back to bone-space space, using the flipped bone if it exists. */ mul_m4_m4m4(chan_mat, arm_mat_inv, chan_mat); + /* The rest pose having an X-axis that is not mapping to a left/right direction (so aligned + * with the Y or Z axis) creates issues when flipping the pose. Instead of a negative scale on + * the X-axis, it turns into a 180 degree rotation over the Y-axis. + * This has only been observed with bones that can't be flipped, + * hence the check for `pchan_flip`. */ + const float unit_x[4] = {1.0f, 0.0f, 0.0f, 0.0f}; + const bool is_problematic = pchan_flip == NULL && + fabsf(dot_v4v4(pchan->bone->arm_mat[0], unit_x)) <= 1e-6; + if (is_problematic) { + /* Matrix needs to flip both the X and Z axes to come out right. */ + float extra_mat[4][4] = { + {-1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, -1.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}, + }; + mul_m4_m4m4(chan_mat, extra_mat, chan_mat); + } + BKE_pchan_apply_mat4(&pchan_temp, chan_mat, false); /* Write the values back to the F-curves. */ diff --git a/source/blender/blenkernel/intern/action_test.cc b/source/blender/blenkernel/intern/action_test.cc new file mode 100644 index 00000000000..c02eca966ad --- /dev/null +++ b/source/blender/blenkernel/intern/action_test.cc @@ -0,0 +1,144 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 Blender Foundation + * All rights reserved. + */ + +#include "BKE_action.h" + +#include "DNA_action_types.h" +#include "DNA_anim_types.h" + +#include "BLI_listbase.h" + +#include "testing/testing.h" + +namespace blender::bke::tests { + +TEST(action_groups, ReconstructGroupsWithReordering) +{ + /* Construct an Action with three groups. */ + bAction action = {{nullptr}}; + FCurve groupAcurve1 = {nullptr}; + FCurve groupAcurve2 = {nullptr}; + FCurve groupBcurve1 = {nullptr}; + FCurve groupBcurve2 = {nullptr}; + FCurve groupBcurve3 = {nullptr}; + /* Group C has no curves intentionally. */ + FCurve groupDcurve1 = {nullptr}; + FCurve groupDcurve2 = {nullptr}; + + groupAcurve1.rna_path = (char *)"groupAcurve1"; + groupAcurve2.rna_path = (char *)"groupAcurve2"; + groupBcurve1.rna_path = (char *)"groupBcurve1"; + groupBcurve2.rna_path = (char *)"groupBcurve2"; + groupDcurve1.rna_path = (char *)"groupDcurve1"; + groupBcurve3.rna_path = (char *)"groupBcurve3"; + groupDcurve2.rna_path = (char *)"groupDcurve2"; + + BLI_addtail(&action.curves, &groupAcurve1); + BLI_addtail(&action.curves, &groupAcurve2); + BLI_addtail(&action.curves, &groupBcurve1); + BLI_addtail(&action.curves, &groupBcurve2); + BLI_addtail(&action.curves, &groupDcurve1); + BLI_addtail(&action.curves, &groupBcurve3); /* <-- The error that should be corrected. */ + BLI_addtail(&action.curves, &groupDcurve2); + + /* Introduce another error type, by changing some `prev` pointers. */ + groupBcurve1.prev = nullptr; + groupBcurve3.prev = &groupBcurve2; + groupDcurve1.prev = &groupBcurve3; + + bActionGroup groupA = {nullptr}; + bActionGroup groupB = {nullptr}; + bActionGroup groupC = {nullptr}; + bActionGroup groupD = {nullptr}; + strcpy(groupA.name, "groupA"); + strcpy(groupB.name, "groupB"); + strcpy(groupC.name, "groupC"); + strcpy(groupD.name, "groupD"); + + BLI_addtail(&action.groups, &groupA); + BLI_addtail(&action.groups, &groupB); + BLI_addtail(&action.groups, &groupC); + BLI_addtail(&action.groups, &groupD); + + groupAcurve1.grp = &groupA; + groupAcurve2.grp = &groupA; + groupBcurve1.grp = &groupB; + groupBcurve2.grp = &groupB; + groupBcurve3.grp = &groupB; + groupDcurve1.grp = &groupD; + groupDcurve2.grp = &groupD; + + groupA.channels.first = &groupAcurve1; + groupA.channels.last = &groupAcurve2; + groupB.channels.first = &groupBcurve1; + groupB.channels.last = &groupBcurve3; /* The last channel in group B, after group C curve 1. */ + groupD.channels.first = &groupDcurve1; + groupD.channels.last = &groupDcurve2; + + EXPECT_EQ(groupA.channels.first, &groupAcurve1); + EXPECT_EQ(groupA.channels.last, &groupAcurve2); + EXPECT_EQ(groupB.channels.first, &groupBcurve1); + EXPECT_EQ(groupB.channels.last, &groupBcurve3); + EXPECT_EQ(groupC.channels.first, nullptr); + EXPECT_EQ(groupC.channels.last, nullptr); + EXPECT_EQ(groupD.channels.first, &groupDcurve1); + EXPECT_EQ(groupD.channels.last, &groupDcurve2); + + BKE_action_groups_reconstruct(&action); + + EXPECT_EQ(action.curves.first, &groupAcurve1); + EXPECT_EQ(action.curves.last, &groupDcurve2); + + EXPECT_EQ(groupA.prev, nullptr); + EXPECT_EQ(groupB.prev, &groupA); + EXPECT_EQ(groupC.prev, &groupB); + EXPECT_EQ(groupD.prev, &groupC); + + EXPECT_EQ(groupA.next, &groupB); + EXPECT_EQ(groupB.next, &groupC); + EXPECT_EQ(groupC.next, &groupD); + EXPECT_EQ(groupD.next, nullptr); + + EXPECT_EQ(groupA.channels.first, &groupAcurve1); + EXPECT_EQ(groupA.channels.last, &groupAcurve2); + EXPECT_EQ(groupB.channels.first, &groupBcurve1); + EXPECT_EQ(groupB.channels.last, &groupBcurve3); + EXPECT_EQ(groupC.channels.first, nullptr); + EXPECT_EQ(groupC.channels.last, nullptr); + EXPECT_EQ(groupD.channels.first, &groupDcurve1); + EXPECT_EQ(groupD.channels.last, &groupDcurve2); + + EXPECT_EQ(groupAcurve1.prev, nullptr); + EXPECT_EQ(groupAcurve2.prev, &groupAcurve1); + EXPECT_EQ(groupBcurve1.prev, &groupAcurve2); + EXPECT_EQ(groupBcurve2.prev, &groupBcurve1); + EXPECT_EQ(groupBcurve3.prev, &groupBcurve2); + EXPECT_EQ(groupDcurve1.prev, &groupBcurve3); + EXPECT_EQ(groupDcurve2.prev, &groupDcurve1); + + EXPECT_EQ(groupAcurve1.next, &groupAcurve2); + EXPECT_EQ(groupAcurve2.next, &groupBcurve1); + EXPECT_EQ(groupBcurve1.next, &groupBcurve2); + EXPECT_EQ(groupBcurve2.next, &groupBcurve3); + EXPECT_EQ(groupBcurve3.next, &groupDcurve1); + EXPECT_EQ(groupDcurve1.next, &groupDcurve2); + EXPECT_EQ(groupDcurve2.next, nullptr); +} + +} // namespace blender::bke::tests diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 2f71dda17f2..7e4ab754500 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -89,16 +89,16 @@ bool id_can_have_animdata(const ID *id) return id_type_can_have_animdata(GS(id->name)); } -/* Get AnimData from the given ID-block. In order for this to work, we assume that - * the AnimData pointer is stored immediately after the given ID-block in the struct, - * as per IdAdtTemplate. +/** + * Get #AnimData from the given ID-block. */ AnimData *BKE_animdata_from_id(ID *id) { - /* only some ID-blocks have this info for now, so we cast the - * types that do to be of type IdAdtTemplate, and extract the - * AnimData that way - */ + /* In order for this to work, we assume that the #AnimData pointer is stored + * immediately after the given ID-block in the struct, as per IdAdtTemplate. */ + + /* Only some ID-blocks have this info for now, so we cast the types that do + * to be of type IdAdtTemplate, and add the AnimData to it using the template. */ if (id_can_have_animdata(id)) { IdAdtTemplate *iat = (IdAdtTemplate *)id; return iat->adt; @@ -106,16 +106,16 @@ AnimData *BKE_animdata_from_id(ID *id) return NULL; } -/* Add AnimData to the given ID-block. In order for this to work, we assume that - * the AnimData pointer is stored immediately after the given ID-block in the struct, - * as per IdAdtTemplate. Also note that +/** + * Ensure #AnimData exists in the given ID-block (when supported). */ -AnimData *BKE_animdata_add_id(ID *id) +AnimData *BKE_animdata_ensure_id(ID *id) { - /* Only some ID-blocks have this info for now, so we cast the - * types that do to be of type IdAdtTemplate, and add the AnimData - * to it using the template - */ + /* In order for this to work, we assume that the #AnimData pointer is stored + * immediately after the given ID-block in the struct, as per IdAdtTemplate. */ + + /* Only some ID-blocks have this info for now, so we cast the types that do + * to be of type IdAdtTemplate, and add the AnimData to it using the template. */ if (id_can_have_animdata(id)) { IdAdtTemplate *iat = (IdAdtTemplate *)id; @@ -336,7 +336,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag) * BKE_id_copy_ex(). * So in case we do copy the ID and its sub-IDs in bmain, silence the 'no usercount' flag for * the sub-IDs copying. - * Note: This is a bit weak, as usually when it comes to recursive ID copy. Should work for + * NOTE: This is a bit weak, as usually when it comes to recursive ID copy. Should work for * now, but we may have to revisit this at some point and add a proper extra flag to deal with * that situation. Or refactor completely the way we handle such recursion, by flattening it * e.g. */ @@ -444,7 +444,7 @@ void BKE_animdata_merge_copy( return; } - // TODO: we must unset all "tweakmode" flags + /* TODO: we must unset all "tweak-mode" flags. */ if ((src->flag & ADT_NLA_EDIT_ON) || (dst->flag & ADT_NLA_EDIT_ON)) { CLOG_ERROR( &LOG, @@ -667,7 +667,7 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa /* get animdata from src, and create for destination (if needed) */ srcAdt = BKE_animdata_from_id(srcID); - dstAdt = BKE_animdata_add_id(dstID); + dstAdt = BKE_animdata_ensure_id(dstID); if (ELEM(NULL, srcAdt, dstAdt)) { if (G.debug & G_DEBUG) { @@ -1563,7 +1563,7 @@ void BKE_animdata_blend_write(BlendWriter *writer, struct AnimData *adt) BLO_write_string(writer, aor->rna_path); } - /* TODO write the remaps (if they are needed) */ + /* TODO: write the remaps (if they are needed). */ /* write NLA data */ BKE_nla_blend_write(writer, &adt->nla_tracks); @@ -1590,10 +1590,10 @@ void BKE_animdata_blend_read_data(BlendDataReader *reader, AnimData *adt) /* relink active track/strip - even though strictly speaking this should only be used * if we're in 'tweaking mode', we need to be able to have this loaded back for - * undo, but also since users may not exit tweakmode before saving (T24535) + * undo, but also since users may not exit tweak-mode before saving (T24535). */ /* TODO: it's not really nice that anyone should be able to save the file in this - * state, but it's going to be too hard to enforce this single case... */ + * state, but it's going to be too hard to enforce this single case. */ BLO_read_data_address(reader, &adt->act_track); BLO_read_data_address(reader, &adt->actstrip); } diff --git a/source/blender/blenkernel/intern/anim_path.c b/source/blender/blenkernel/intern/anim_path.c index e2c2708101b..de470a15041 100644 --- a/source/blender/blenkernel/intern/anim_path.c +++ b/source/blender/blenkernel/intern/anim_path.c @@ -216,7 +216,7 @@ static bool binary_search_anim_path(const float *accum_len_arr, if (UNLIKELY(cur_step == 0)) { /* This should never happen unless there is something horribly wrong. */ CLOG_ERROR(&LOG, "Couldn't find any valid point on the animation path!"); - BLI_assert(!"Couldn't find any valid point on the animation path!"); + BLI_assert_msg(0, "Couldn't find any valid point on the animation path!"); return false; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 08a3f3fcf4f..2879a995ad6 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -621,6 +621,115 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, } } +/* This function assumes that the quaternion is fully keyed, and is stored in array index order. */ +static void animsys_quaternion_evaluate_fcurves(PathResolvedRNA quat_rna, + FCurve *first_fcurve, + const AnimationEvalContext *anim_eval_context, + float r_quaternion[4]) +{ + FCurve *quat_curve_fcu = first_fcurve; + for (int prop_index = 0; prop_index < 4; ++prop_index, quat_curve_fcu = quat_curve_fcu->next) { + /* Big fat assumption that the quaternion is fully keyed, and stored in order. */ + BLI_assert(STREQ(quat_curve_fcu->rna_path, first_fcurve->rna_path) && + quat_curve_fcu->array_index == prop_index); + + quat_rna.prop_index = prop_index; + r_quaternion[prop_index] = calculate_fcurve(&quat_rna, quat_curve_fcu, anim_eval_context); + } +} + +/* This function assumes that the quaternion is fully keyed, and is stored in array index order. */ +static void animsys_blend_fcurves_quaternion(PathResolvedRNA *anim_rna, + FCurve *first_fcurve, + const AnimationEvalContext *anim_eval_context, + const float blend_factor) +{ + float current_quat[4]; + RNA_property_float_get_array(&anim_rna->ptr, anim_rna->prop, current_quat); + + float target_quat[4]; + animsys_quaternion_evaluate_fcurves(*anim_rna, first_fcurve, anim_eval_context, target_quat); + + float blended_quat[4]; + interp_qt_qtqt(blended_quat, current_quat, target_quat, blend_factor); + + RNA_property_float_set_array(&anim_rna->ptr, anim_rna->prop, blended_quat); +} + +/* LERP between current value (blend_factor=0.0) and the value from the FCurve (blend_factor=1.0) + */ +static void animsys_blend_in_fcurves(PointerRNA *ptr, + ListBase *fcurves, + const AnimationEvalContext *anim_eval_context, + const float blend_factor) +{ + char *channel_to_skip = NULL; + int num_channels_to_skip = 0; + LISTBASE_FOREACH (FCurve *, fcu, fcurves) { + + if (num_channels_to_skip) { + /* For skipping already-handled rotation channels. Rotation channels are handled per group, + * and not per individual channel. */ + BLI_assert(channel_to_skip != NULL); + if (STREQ(channel_to_skip, fcu->rna_path)) { + /* This is indeed the channel we want to skip. */ + num_channels_to_skip--; + continue; + } + } + + if (!is_fcurve_evaluatable(fcu)) { + continue; + } + + PathResolvedRNA anim_rna; + if (!BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { + continue; + } + + if (STREQ(RNA_property_identifier(anim_rna.prop), "rotation_quaternion")) { + animsys_blend_fcurves_quaternion(&anim_rna, fcu, anim_eval_context, blend_factor); + + /* Skip the next three channels, because those have already been handled here. */ + MEM_SAFE_FREE(channel_to_skip); + channel_to_skip = BLI_strdup(fcu->rna_path); + num_channels_to_skip = 3; + continue; + } + /* TODO(Sybren): do something similar as above for Euler and Axis/Angle representations. */ + + const float fcurve_value = calculate_fcurve(&anim_rna, fcu, anim_eval_context); + + float current_value; + float value_to_write; + if (BKE_animsys_read_from_rna_path(&anim_rna, ¤t_value)) { + value_to_write = (1 - blend_factor) * current_value + blend_factor * fcurve_value; + + switch (RNA_property_type(anim_rna.prop)) { + case PROP_BOOLEAN: + /* Without this, anything less than 1.0 is converted to 'False' by + * ANIMSYS_FLOAT_AS_BOOL(). This is probably not desirable for blends, where anything + * above a 50% blend should act more like the FCurve than like the current value. */ + case PROP_INT: + case PROP_ENUM: + value_to_write = roundf(value_to_write); + break; + default: + /* All other types are just handled as float, and value_to_write is already correct. */ + break; + } + } + else { + /* Unable to read the current value for blending, so just apply the FCurve value instead. */ + value_to_write = fcurve_value; + } + + BKE_animsys_write_to_rna_path(&anim_rna, value_to_write); + } + + MEM_SAFE_FREE(channel_to_skip); +} + /* ***************************************** */ /* Driver Evaluation */ @@ -769,6 +878,16 @@ void animsys_evaluate_action(PointerRNA *ptr, animsys_evaluate_fcurves(ptr, &act->curves, anim_eval_context, flush_to_original); } +/* Evaluate Action and blend it into the current values of the animated properties. */ +void animsys_blend_in_action(PointerRNA *ptr, + bAction *act, + const AnimationEvalContext *anim_eval_context, + const float blend_factor) +{ + action_idcode_patch_check(ptr->owner_id, act); + animsys_blend_in_fcurves(ptr, &act->curves, anim_eval_context, blend_factor); +} + /* ***************************************** */ /* NLA System - Evaluation */ @@ -1457,7 +1576,7 @@ static float nla_blend_value(const int blendmode, return influence * (lower_value * strip_value) + (1 - influence) * lower_value; case NLASTRIP_MODE_COMBINE: - BLI_assert(!"combine mode"); + BLI_assert_msg(0, "combine mode"); ATTR_FALLTHROUGH; default: @@ -1495,7 +1614,7 @@ static float nla_combine_value(const int mix_mode, return lower_value * powf(strip_value / base_value, influence); default: - BLI_assert(!"invalid mix mode"); + BLI_assert_msg(0, "invalid mix mode"); return lower_value; } } @@ -1546,7 +1665,7 @@ static bool nla_blend_get_inverted_strip_value(const int blendmode, return true; case NLASTRIP_MODE_COMBINE: - BLI_assert(!"combine mode"); + BLI_assert_msg(0, "combine mode"); ATTR_FALLTHROUGH; default: @@ -1602,7 +1721,7 @@ static bool nla_combine_get_inverted_strip_value(const int mix_mode, return true; default: - BLI_assert(!"invalid mix mode"); + BLI_assert_msg(0, "invalid mix mode"); return false; } } @@ -2746,7 +2865,7 @@ static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr, } } - /** Note: Although we early out, we can still keyframe to the non-pushed action since the + /** NOTE: Although we early out, we can still keyframe to the non-pushed action since the * keyframe remap function detects (r_context->strip.act == NULL) and will keyframe without * remapping. */ @@ -3033,7 +3152,7 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, NlaEvalChannel *nec = nlaevalchan_verify_key(eval_data, NULL, &key); BLI_assert(nec); if (nec->base_snapshot.length != count) { - BLI_assert(!"invalid value count"); + BLI_assert_msg(0, "invalid value count"); nlaeval_snapshot_free_data(&blended_snapshot); return false; } @@ -3126,7 +3245,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) * * 3) Drivers/expressions are evaluated on top of this, in an order where dependencies are * resolved nicely. - * Note: it may be necessary to have some tools to handle the cases where some higher-level + * NOTE: it may be necessary to have some tools to handle the cases where some higher-level * drivers are added and cause some problematic dependencies that * didn't exist in the local levels... * diff --git a/source/blender/blenkernel/intern/anim_visualization.c b/source/blender/blenkernel/intern/anim_visualization.c index ecd71ec08fe..56bd8e769bc 100644 --- a/source/blender/blenkernel/intern/anim_visualization.c +++ b/source/blender/blenkernel/intern/anim_visualization.c @@ -50,8 +50,8 @@ void animviz_settings_init(bAnimVizSettings *avs) /* path settings */ avs->path_bc = avs->path_ac = 10; - avs->path_sf = 1; /* xxx - take from scene instead? */ - avs->path_ef = 250; /* xxx - take from scene instead? */ + avs->path_sf = 1; /* XXX: Take from scene instead? */ + avs->path_ef = 250; /* XXX: Take from scene instead? */ avs->path_viewflag = (MOTIONPATH_VIEW_KFRAS | MOTIONPATH_VIEW_KFNOS); diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 579f671e2b0..eae331fc7d1 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -191,8 +191,7 @@ bool BKE_appdir_folder_documents(char *dir) { dir[0] = '\0'; - const char *documents_path = (const char *)GHOST_getUserSpecialDir( - GHOST_kUserSpecialDirDocuments); + const char *documents_path = GHOST_getUserSpecialDir(GHOST_kUserSpecialDirDocuments); /* Usual case: Ghost gave us the documents path. We're done here. */ if (documents_path && BLI_is_dir(documents_path)) { @@ -462,7 +461,7 @@ static bool get_path_user_ex(char *targetpath, } user_path[0] = '\0'; - user_base_path = (const char *)GHOST_getUserDir(version, blender_version_decimal(version)); + user_base_path = GHOST_getUserDir(version, blender_version_decimal(version)); if (user_base_path) { BLI_strncpy(user_path, user_base_path, FILE_MAX); } @@ -522,7 +521,7 @@ static bool get_path_system_ex(char *targetpath, } system_path[0] = '\0'; - system_base_path = (const char *)GHOST_getSystemDir(version, blender_version_decimal(version)); + system_base_path = GHOST_getSystemDir(version, blender_version_decimal(version)); if (system_base_path) { BLI_strncpy(system_path, system_base_path, FILE_MAX); } @@ -780,7 +779,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id, default: path[0] = '\0'; /* in case check_is_dir is false */ ok = false; - BLI_assert(!"incorrect ID"); + BLI_assert_msg(0, "incorrect ID"); break; } return ok ? path : NULL; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index d0604f4bfda..b8ed519e8d1 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2405,9 +2405,9 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected) BKE_pose_rest(frompose, false); /* copy over all of the proxy's bone groups */ - /* TODO for later + /* TODO: for later * - implement 'local' bone groups as for constraints - * Note: this isn't trivial, as bones reference groups by index not by pointer, + * NOTE: this isn't trivial, as bones reference groups by index not by pointer, * so syncing things correctly needs careful attention */ BLI_freelistN(&pose->agroups); BLI_duplicatelist(&pose->agroups, &frompose->agroups); @@ -2543,7 +2543,7 @@ static int rebuild_pose_bone( * (grand-(grand-(...)))-child (as processed by the recursive, depth-first nature of this * function) of the previous sibling. * - * Note: In most cases there is nothing to do here, but pose list may get out of order when some + * NOTE: In most cases there is nothing to do here, but pose list may get out of order when some * bones are added, removed or moved in the armature data. */ bPoseChannel *pchan_prev = pchan->prev; const Bone *last_visited_bone = *r_last_visited_bone_p; @@ -2843,7 +2843,7 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob) * hopefully this is OK. */ BKE_pose_ensure(NULL, ob, arm, true); - ctime = BKE_scene_frame_get(scene); /* not accurate... */ + ctime = BKE_scene_ctime_get(scene); /* not accurate... */ /* In edit-mode or rest-position we read the data from the bones. */ if (arm->edbo || (arm->flag & ARM_RESTPOS)) { diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c index bca5503c8d2..5f721b49361 100644 --- a/source/blender/blenkernel/intern/armature_deform.c +++ b/source/blender/blenkernel/intern/armature_deform.c @@ -47,6 +47,7 @@ #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_lattice.h" @@ -485,7 +486,7 @@ static void armature_deform_coords_impl(const Object *ob_arm, int defbase_len = 0; /* safety for vertexgroup index overflow */ int i, dverts_len = 0; /* safety for vertexgroup overflow */ bool use_dverts = false; - int armature_def_nr; + int armature_def_nr = -1; int cd_dvert_offset = -1; /* in editmode, or not an armature */ @@ -500,11 +501,11 @@ static void armature_deform_coords_impl(const Object *ob_arm, BLI_assert(0); } - /* get the def_nr for the overall armature vertex group if present */ - armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name); + if (BKE_object_supports_vertex_groups(ob_target)) { + /* get the def_nr for the overall armature vertex group if present */ + armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name); - if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { - defbase_len = BLI_listbase_count(&ob_target->defbase); + defbase_len = BKE_object_defgroup_count(ob_target); if (ob_target->type == OB_MESH) { if (em_target == NULL) { @@ -528,11 +529,9 @@ static void armature_deform_coords_impl(const Object *ob_arm, dverts_len = gps_target->totpoints; } } - } - /* get a vertex-deform-index to posechannel array */ - if (deformflag & ARM_DEF_VGROUP) { - if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { + /* get a vertex-deform-index to posechannel array */ + if (deformflag & ARM_DEF_VGROUP) { /* if we have a Mesh, only use dverts if it has them */ if (em_target) { cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT); @@ -551,7 +550,8 @@ static void armature_deform_coords_impl(const Object *ob_arm, * * - Check whether keeping this consistent across frames gives speedup. */ - for (i = 0, dg = ob_target->defbase.first; dg; i++, dg = dg->next) { + const ListBase *defbase = BKE_object_defgroup_list(ob_target); + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { pchan_from_defbase[i] = BKE_pose_channel_find_name(ob_arm->pose, dg->name); /* exclude non-deforming bones */ if (pchan_from_defbase[i]) { diff --git a/source/blender/blenkernel/intern/armature_pose.cc b/source/blender/blenkernel/intern/armature_pose.cc index ca11692372b..09e1c7d6615 100644 --- a/source/blender/blenkernel/intern/armature_pose.cc +++ b/source/blender/blenkernel/intern/armature_pose.cc @@ -26,6 +26,7 @@ #include "BKE_animsys.h" #include "BKE_armature.h" +#include "BLI_function_ref.hh" #include "BLI_set.hh" #include "DNA_action_types.h" @@ -38,16 +39,62 @@ namespace { using BoneNameSet = blender::Set<std::string>; +using ActionApplier = + blender::FunctionRef<void(PointerRNA *, bAction *, const AnimationEvalContext *)>; + // Forward declarations. BoneNameSet pose_apply_find_selected_bones(const bArmature *armature, const bPose *pose); void pose_apply_disable_fcurves_for_unselected_bones(bAction *action, const BoneNameSet &selected_bone_names); void pose_apply_restore_fcurves(bAction *action); + +void pose_apply(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context, + ActionApplier applier); + } // namespace -void BKE_pose_apply_action(struct Object *ob, - struct bAction *action, - struct AnimationEvalContext *anim_eval_context) +void BKE_pose_apply_action_selected_bones(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context) +{ + auto evaluate_and_apply = + [](PointerRNA *ptr, bAction *act, const AnimationEvalContext *anim_eval_context) { + animsys_evaluate_action(ptr, act, anim_eval_context, false); + }; + + pose_apply(ob, action, anim_eval_context, evaluate_and_apply); +} + +void BKE_pose_apply_action_all_bones(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context) +{ + PointerRNA pose_owner_ptr; + RNA_id_pointer_create(&ob->id, &pose_owner_ptr); + animsys_evaluate_action(&pose_owner_ptr, action, anim_eval_context, false); +} + +void BKE_pose_apply_action_blend(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context, + const float blend_factor) +{ + auto evaluate_and_blend = [blend_factor](PointerRNA *ptr, + bAction *act, + const AnimationEvalContext *anim_eval_context) { + animsys_blend_in_action(ptr, act, anim_eval_context, blend_factor); + }; + + pose_apply(ob, action, anim_eval_context, evaluate_and_blend); +} + +namespace { +void pose_apply(struct Object *ob, + struct bAction *action, + struct AnimationEvalContext *anim_eval_context, + ActionApplier applier) { bPose *pose = ob->pose; if (pose == nullptr) { @@ -67,14 +114,14 @@ void BKE_pose_apply_action(struct Object *ob, /* Apply the Action. */ PointerRNA pose_owner_ptr; RNA_id_pointer_create(&ob->id, &pose_owner_ptr); - animsys_evaluate_action(&pose_owner_ptr, action, anim_eval_context, false); + + applier(&pose_owner_ptr, action, anim_eval_context); if (limit_to_selected_bones) { pose_apply_restore_fcurves(action); } } -namespace { BoneNameSet pose_apply_find_selected_bones(const bArmature *armature, const bPose *pose) { BoneNameSet selected_bone_names; diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 0f8956a1a91..35ae2d2dbef 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -562,7 +562,7 @@ static void splineik_evaluate_bone( * spline dictates, while still maintaining roll control from the existing bone animation. */ mul_m3_m3m3(pose_mat, dmat, rmat); - /* Attempt to reduce shearing, though I doubt this'll really help too much now... */ + /* Attempt to reduce shearing, though I doubt this will really help too much now. */ normalize_m3(pose_mat); mul_m3_m3m3(base_pose_mat, dmat, base_pose_mat); @@ -828,7 +828,7 @@ void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *ob { DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); BLI_assert(object->type == OB_ARMATURE); - const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */ bArmature *armature = (bArmature *)object->data; if (armature->flag & ARM_RESTPOS) { return; @@ -869,7 +869,7 @@ void BKE_pose_eval_bone(struct Depsgraph *depsgraph, Scene *scene, Object *objec else { if ((pchan->flag & POSE_DONE) == 0) { /* TODO(sergey): Use time source node for time. */ - float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + float ctime = BKE_scene_ctime_get(scene); /* not accurate... */ BKE_pose_where_is_bone(depsgraph, scene, object, pchan, ctime, 1); } } @@ -897,7 +897,7 @@ void BKE_pose_constraints_evaluate(struct Depsgraph *depsgraph, } else { if ((pchan->flag & POSE_DONE) == 0) { - float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + float ctime = BKE_scene_ctime_get(scene); /* not accurate... */ BKE_pose_where_is_bone(depsgraph, scene, object, pchan, ctime, 1); } } @@ -981,7 +981,7 @@ void BKE_pose_iktree_evaluate(struct Depsgraph *depsgraph, DEG_debug_print_eval_subdata( depsgraph, __func__, object->id.name, object, "rootchan", rootchan->name, rootchan); BLI_assert(object->type == OB_ARMATURE); - const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */ if (armature->flag & ARM_RESTPOS) { return; } @@ -1002,7 +1002,7 @@ void BKE_pose_splineik_evaluate(struct Depsgraph *depsgraph, DEG_debug_print_eval_subdata( depsgraph, __func__, object->id.name, object, "rootchan", rootchan->name, rootchan); BLI_assert(object->type == OB_ARMATURE); - const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */ if (armature->flag & ARM_RESTPOS) { return; } @@ -1031,7 +1031,7 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph, Scene *scene, Object *ob bPose *pose = object->pose; BLI_assert(pose != NULL); UNUSED_VARS_NDEBUG(pose); - const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */ DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); BLI_assert(object->type == OB_ARMATURE); /* Release the IK tree. */ diff --git a/source/blender/blenkernel/intern/asset.cc b/source/blender/blenkernel/intern/asset.cc index b5a7f5e37a6..f74018b20c5 100644 --- a/source/blender/blenkernel/intern/asset.cc +++ b/source/blender/blenkernel/intern/asset.cc @@ -110,6 +110,11 @@ void BKE_asset_metadata_tag_remove(AssetMetaData *asset_data, AssetTag *tag) BLI_assert(BLI_listbase_count(&asset_data->tags) == asset_data->tot_tags); } +void BKE_asset_library_reference_init_default(AssetLibraryReference *library_ref) +{ + memcpy(library_ref, DNA_struct_default_get(AssetLibraryReference), sizeof(*library_ref)); +} + /* Queries -------------------------------------------- */ PreviewImage *BKE_asset_metadata_preview_get_from_id(const AssetMetaData *UNUSED(asset_data), diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c index 5db45471f0a..ad2be4ffe30 100644 --- a/source/blender/blenkernel/intern/attribute.c +++ b/source/blender/blenkernel/intern/attribute.c @@ -119,7 +119,7 @@ bool BKE_id_attribute_rename(ID *id, ReportList *reports) { if (BKE_id_attribute_required(id, layer)) { - BLI_assert(!"Required attribute name is not editable"); + BLI_assert_msg(0, "Required attribute name is not editable"); return false; } @@ -202,7 +202,7 @@ AttributeDomain BKE_id_attribute_domain(ID *id, CustomDataLayer *layer) } } - BLI_assert(!"Custom data layer not found in geometry"); + BLI_assert_msg(0, "Custom data layer not found in geometry"); return ATTR_DOMAIN_NUM; } @@ -218,7 +218,7 @@ int BKE_id_attribute_data_length(ID *id, CustomDataLayer *layer) } } - BLI_assert(!"Custom data layer not found in geometry"); + BLI_assert_msg(0, "Custom data layer not found in geometry"); return 0; } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index e84b485c466..97a54f289ee 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -127,7 +127,7 @@ static void blender_version_init(void) version_cycle = ""; } else { - BLI_assert(!"Invalid Blender version cycle"); + BLI_assert_msg(0, "Invalid Blender version cycle"); } BLI_snprintf(blender_version_string, diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index f31d8f5ade7..19721b4313d 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -128,7 +128,7 @@ static void setup_app_userdef(BlendFileData *bfd) } /** - * Context matching, handle no-ui case + * Context matching, handle no-UI case. * * \note this is called on Undo so any slow conversion functions here * should be avoided or check (mode != LOAD_UNDO). @@ -622,6 +622,7 @@ UserDef *BKE_blendfile_userdef_from_defaults(void) "io_scene_obj", "io_scene_x3d", "cycles", + "pose_library", }; for (int i = 0; i < ARRAY_SIZE(addons); i++) { bAddon *addon = BKE_addon_new(); diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index f26a9f06697..70274de8bff 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -18,7 +18,7 @@ * \ingroup bli */ -/* TODO, +/* TODO: * currently there are some cases we don't support. * - passing output paths to the visitor?, like render out. * - passing sequence strips with many images. diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index fdf9cf21b85..abf7bab7612 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -379,10 +379,10 @@ static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old) BKE_lib_id_swap(NULL, id_new, id_old); /* `id_new` now has content from `id_old`, we need to ensure those old ID pointers are valid. - * Note: Since we want to re-use all old pointers here, code is much simpler than for Scene. */ + * NOTE: Since we want to re-use all old pointers here, code is much simpler than for Scene. */ BKE_library_foreach_ID_link(NULL, id_new, brush_undo_preserve_cb, reader, IDWALK_NOP); - /* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be + /* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be * fairly delicate. */ SWAP(IDProperty *, id_new->properties, id_old->properties); } diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.cc index 4659c464099..164f921c7ac 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.cc @@ -21,9 +21,9 @@ * \ingroup bke */ -#include <math.h> -#include <stdio.h> -#include <string.h> +#include <cmath> +#include <cstdio> +#include <cstring> #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -46,15 +46,15 @@ /** \name BVHCache * \{ */ -typedef struct BVHCacheItem { +struct BVHCacheItem { bool is_filled; BVHTree *tree; -} BVHCacheItem; +}; -typedef struct BVHCache { +struct BVHCache { BVHCacheItem items[BVHTREE_MAX_ITEM]; ThreadMutex mutex; -} BVHCache; +}; /** * Queries a bvhcache for the cache bvhtree of the request type @@ -74,14 +74,14 @@ static bool bvhcache_find(BVHCache **bvh_cache_p, if (r_locked) { *r_locked = false; } - if (*bvh_cache_p == NULL) { + if (*bvh_cache_p == nullptr) { if (!do_lock) { /* Cache does not exist and no lock is requested. */ return false; } /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */ BLI_mutex_lock(mesh_eval_mutex); - if (*bvh_cache_p == NULL) { + if (*bvh_cache_p == nullptr) { *bvh_cache_p = bvhcache_init(); } BLI_mutex_unlock(mesh_eval_mutex); @@ -94,7 +94,7 @@ static bool bvhcache_find(BVHCache **bvh_cache_p, } if (do_lock) { BLI_mutex_lock(&bvh_cache->mutex); - bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, NULL, NULL); + bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, nullptr, nullptr); if (in_cache) { BLI_mutex_unlock(&bvh_cache->mutex); return in_cache; @@ -113,11 +113,11 @@ static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started) bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree) { - if (bvh_cache == NULL) { + if (bvh_cache == nullptr) { return false; } - for (BVHCacheType i = 0; i < BVHTREE_MAX_ITEM; i++) { + for (int i = 0; i < BVHTREE_MAX_ITEM; i++) { if (bvh_cache->items[i].tree == tree) { return true; } @@ -127,7 +127,7 @@ bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree) BVHCache *bvhcache_init(void) { - BVHCache *cache = MEM_callocN(sizeof(BVHCache), __func__); + BVHCache *cache = (BVHCache *)MEM_callocN(sizeof(BVHCache), __func__); BLI_mutex_init(&cache->mutex); return cache; } @@ -137,7 +137,7 @@ BVHCache *bvhcache_init(void) * as that will be done when the cache is freed. * * A call to this assumes that there was no previous cached tree of the given type - * \warning The #BVHTree can be NULL. + * \warning The #BVHTree can be nullptr. */ static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type) { @@ -152,10 +152,10 @@ static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType typ */ void bvhcache_free(BVHCache *bvh_cache) { - for (BVHCacheType index = 0; index < BVHTREE_MAX_ITEM; index++) { + for (int index = 0; index < BVHTREE_MAX_ITEM; index++) { BVHCacheItem *item = &bvh_cache->items[index]; BLI_bvhtree_free(item->tree); - item->tree = NULL; + item->tree = nullptr; } BLI_mutex_end(&bvh_cache->mutex); MEM_freeN(bvh_cache); @@ -197,9 +197,10 @@ float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, float dist; #ifdef USE_KDOPBVH_WATERTIGHT - if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, NULL)) + if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, nullptr)) #else - if (isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON)) + if (isect_ray_tri_epsilon_v3( + ray->origin, ray->direction, v0, v1, v2, &dist, nullptr, FLT_EPSILON)) #endif { return dist; @@ -247,7 +248,7 @@ static void mesh_faces_nearest_point(void *userdata, t0 = vert[face->v1].co; t1 = vert[face->v2].co; t2 = vert[face->v3].co; - t3 = face->v4 ? vert[face->v4].co : NULL; + t3 = face->v4 ? vert[face->v4].co : nullptr; do { float nearest_tmp[3], dist_sq; @@ -264,7 +265,7 @@ static void mesh_faces_nearest_point(void *userdata, t1 = t2; t2 = t3; - t3 = NULL; + t3 = nullptr; } while (t2); } @@ -300,7 +301,7 @@ static void editmesh_looptri_nearest_point(void *userdata, const float co[3], BVHTreeNearest *nearest) { - const BVHTreeFromEditMesh *data = userdata; + const BVHTreeFromEditMesh *data = (const BVHTreeFromEditMesh *)userdata; BMEditMesh *em = data->em; const BMLoop **ltri = (const BMLoop **)em->looptris[index]; @@ -339,7 +340,7 @@ static void mesh_faces_spherecast(void *userdata, t0 = vert[face->v1].co; t1 = vert[face->v2].co; t2 = vert[face->v3].co; - t3 = face->v4 ? vert[face->v4].co : NULL; + t3 = face->v4 ? vert[face->v4].co : nullptr; do { float dist; @@ -360,7 +361,7 @@ static void mesh_faces_spherecast(void *userdata, t1 = t2; t2 = t3; - t3 = NULL; + t3 = nullptr; } while (t2); } @@ -457,7 +458,7 @@ static void mesh_edges_nearest_point(void *userdata, } } -/* Helper, does all the point-spherecast work actually. */ +/* Helper, does all the point-sphere-cast work actually. */ static void mesh_verts_spherecast_do(int index, const float v[3], const BVHTreeRay *ray, @@ -484,7 +485,7 @@ static void editmesh_verts_spherecast(void *userdata, const BVHTreeRay *ray, BVHTreeRayHit *hit) { - const BVHTreeFromEditMesh *data = userdata; + const BVHTreeFromEditMesh *data = (const BVHTreeFromEditMesh *)userdata; BMVert *eve = BM_vert_at_index(data->em->bm, index); mesh_verts_spherecast_do(index, eve->co, ray, hit); @@ -600,7 +601,7 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon, const BLI_bitmap *verts_mask, int verts_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (verts_mask) { BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); @@ -637,9 +638,9 @@ static void bvhtree_from_mesh_verts_setup_data(BVHTreeFromMesh *data, data->tree = tree; data->cached = is_cached; - /* a NULL nearest callback works fine + /* a nullptr nearest callback works fine * remember the min distance to point is the same as the min distance to BV of point */ - data->nearest_callback = NULL; + data->nearest_callback = nullptr; data->raycast_callback = mesh_verts_spherecast; data->vert = vert; @@ -658,7 +659,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { bool lock_started = false; @@ -671,7 +672,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, bvhtree_balance(tree, true); /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(*bvh_cache_p, tree, bvh_cache_type); data->cached = true; } @@ -687,9 +688,9 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, memset(data, 0, sizeof(*data)); data->tree = tree; data->em = em; - data->nearest_callback = NULL; + data->nearest_callback = nullptr; data->raycast_callback = editmesh_verts_spherecast; - data->cached = bvh_cache_p != NULL; + data->cached = bvh_cache_p != nullptr; } return tree; @@ -699,11 +700,11 @@ BVHTree *bvhtree_from_editmesh_verts( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { return bvhtree_from_editmesh_verts_ex( - data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); + data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr); } /** - * Builds a bvh tree where nodes are the given vertices (note: does not copy given mverts!). + * Builds a bvh tree where nodes are the given vertices (NOTE: does not copy given `vert`!). * \param vert_allocated: if true, vert freeing will be done when freeing data. * \param verts_mask: if not null, true elements give which vert to add to BVH tree. * \param verts_num_active: if >= 0, number of active verts to add to BVH tree @@ -724,7 +725,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -732,11 +733,11 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, if (in_cache == false) { tree = bvhtree_from_mesh_verts_create_tree( epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active); - bvhtree_balance(tree, bvh_cache_p != NULL); + bvhtree_balance(tree, bvh_cache_p != nullptr); if (bvh_cache_p) { /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); in_cache = true; @@ -807,7 +808,7 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert, int tree_type, int axis) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (edges_mask) { BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num)); @@ -817,7 +818,7 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert, } if (edges_num_active) { - /* Create a bvh-tree of the given target */ + /* Create a BVH-tree of the given target */ tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); if (tree) { for (int i = 0; i < edge_num; i++) { @@ -871,7 +872,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { bool lock_started = false; @@ -883,7 +884,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, epsilon, tree_type, axis, em, edges_mask, edges_num_active); bvhtree_balance(tree, true); /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(bvh_cache, tree, bvh_cache_type); data->cached = true; } @@ -899,9 +900,9 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, memset(data, 0, sizeof(*data)); data->tree = tree; data->em = em; - data->nearest_callback = NULL; /* TODO */ - data->raycast_callback = NULL; /* TODO */ - data->cached = bvh_cache_p != NULL; + data->nearest_callback = nullptr; /* TODO */ + data->raycast_callback = nullptr; /* TODO */ + data->cached = bvh_cache_p != nullptr; } return tree; @@ -911,7 +912,7 @@ BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { return bvhtree_from_editmesh_edges_ex( - data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); + data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr); } /** @@ -939,7 +940,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -953,7 +954,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, BVHCache *bvh_cache = *bvh_cache_p; /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(bvh_cache, tree, bvh_cache_type); in_cache = true; } @@ -988,7 +989,7 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon, const BLI_bitmap *faces_mask, int faces_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (faces_num) { if (faces_mask) { @@ -998,8 +999,8 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon, faces_num_active = faces_num; } - /* Create a bvh-tree of the given target */ - /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */ + /* Create a BVH-tree of the given target. */ + // printf("%s: building BVH, total=%d\n", __func__, numFaces); tree = BLI_bvhtree_new(faces_num_active, epsilon, tree_type, axis); if (tree) { if (vert && face) { @@ -1050,7 +1051,7 @@ static void bvhtree_from_mesh_faces_setup_data(BVHTreeFromMesh *data, /** * Builds a bvh tree where nodes are the given tessellated faces - * (note: does not copy given mfaces!). + * (NOTE: does not copy given mfaces!). * \param vert_allocated: if true, vert freeing will be done when freeing data. * \param face_allocated: if true, face freeing will be done when freeing data. * \param faces_mask: if not null, true elements give which faces to add to BVH tree. @@ -1074,7 +1075,7 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -1082,11 +1083,11 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, if (in_cache == false) { tree = bvhtree_from_mesh_faces_create_tree( epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active); - bvhtree_balance(tree, bvh_cache_p != NULL); + bvhtree_balance(tree, bvh_cache_p != nullptr); if (bvh_cache_p) { /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); in_cache = true; @@ -1117,7 +1118,7 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon, const BLI_bitmap *looptri_mask, int looptri_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; const int looptri_num = em->tottri; if (looptri_num) { @@ -1128,11 +1129,11 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon, looptri_num_active = looptri_num; } - /* Create a bvh-tree of the given target */ - /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */ + /* Create a BVH-tree of the given target */ + // printf("%s: building BVH, total=%d\n", __func__, numFaces); tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis); if (tree) { - const struct BMLoop *(*looptris)[3] = (void *)em->looptris; + const BMLoop *(*looptris)[3] = (const BMLoop *(*)[3])em->looptris; /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden * and/or selected. Even if the faces themselves are not selected for the snapped @@ -1169,7 +1170,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon, const BLI_bitmap *looptri_mask, int looptri_num_active) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (looptri_mask) { BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptri_num)); @@ -1179,8 +1180,8 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon, } if (looptri_num_active) { - /* Create a bvh-tree of the given target */ - /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */ + /* Create a BVH-tree of the given target */ + // printf("%s: building BVH, total=%d\n", __func__, numFaces); tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis); if (tree) { if (vert && looptri) { @@ -1247,7 +1248,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, /* BMESH specific check that we have tessfaces, * we _could_ tessellate here but rather not - campbell */ - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { bool lock_started = false; bool in_cache = bvhcache_find( @@ -1260,7 +1261,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, epsilon, tree_type, axis, em, looptri_mask, looptri_num_active); /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ + // printf("BVHTree built and saved on cache\n"); bvhcache_insert(bvh_cache, tree, bvh_cache_type); } bvhcache_unlock(bvh_cache, lock_started); @@ -1276,7 +1277,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, data->nearest_callback = editmesh_looptri_nearest_point; data->raycast_callback = editmesh_looptri_spherecast; data->em = em; - data->cached = bvh_cache_p != NULL; + data->cached = bvh_cache_p != nullptr; } return tree; } @@ -1285,13 +1286,13 @@ BVHTree *bvhtree_from_editmesh_looptri( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { return bvhtree_from_editmesh_looptri_ex( - data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); + data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr); } /** - * Builds a bvh tree where nodes are the looptri faces of the given dm + * Builds a BVH-tree where nodes are the looptri faces of the given mesh. * - * \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces_ex + * \note for edit-mesh this is currently a duplicate of #bvhtree_from_mesh_faces_ex */ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, const struct MVert *vert, @@ -1312,7 +1313,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, { bool in_cache = false; bool lock_started = false; - BVHTree *tree = NULL; + BVHTree *tree = nullptr; if (bvh_cache_p) { in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } @@ -1329,7 +1330,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, looptri_mask, looptri_num_active); - bvhtree_balance(tree, bvh_cache_p != NULL); + bvhtree_balance(tree, bvh_cache_p != nullptr); if (bvh_cache_p) { BVHCache *bvh_cache = *bvh_cache_p; @@ -1437,19 +1438,22 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly, /** * Builds or queries a bvhcache for the cache bvhtree of the request type. + * + * \note This function only fills a cache, and therefore the mesh argument can + * be considered logically const. Concurrent access is protected by a mutex. */ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, - struct Mesh *mesh, + const struct Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache; ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex; - bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL); + const bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, nullptr, nullptr); - if (is_cached && tree == NULL) { + if (is_cached && tree == nullptr) { memset(data, 0, sizeof(*data)); return tree; } @@ -1458,7 +1462,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, case BVHTREE_FROM_VERTS: case BVHTREE_FROM_LOOSEVERTS: if (is_cached == false) { - BLI_bitmap *loose_verts_mask = NULL; + BLI_bitmap *loose_verts_mask = nullptr; int loose_vert_len = -1; int verts_len = mesh->totvert; @@ -1480,7 +1484,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, bvh_cache_p, mesh_eval_mutex); - if (loose_verts_mask != NULL) { + if (loose_verts_mask != nullptr) { MEM_freeN(loose_verts_mask); } } @@ -1493,7 +1497,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, case BVHTREE_FROM_EDGES: case BVHTREE_FROM_LOOSEEDGES: if (is_cached == false) { - BLI_bitmap *loose_edges_mask = NULL; + BLI_bitmap *loose_edges_mask = nullptr; int loose_edges_len = -1; int edges_len = mesh->totedge; @@ -1516,7 +1520,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, bvh_cache_p, mesh_eval_mutex); - if (loose_edges_mask != NULL) { + if (loose_edges_mask != nullptr) { MEM_freeN(loose_edges_mask); } } @@ -1538,7 +1542,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, mesh->mface, num_faces, false, - NULL, + nullptr, -1, 0.0, tree_type, @@ -1561,7 +1565,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, int looptri_len = BKE_mesh_runtime_looptri_len(mesh); int looptri_mask_active_len = -1; - BLI_bitmap *looptri_mask = NULL; + BLI_bitmap *looptri_mask = nullptr; if (bvh_cache_type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) { looptri_mask = looptri_no_hidden_map_get( mesh->mpoly, looptri_len, &looptri_mask_active_len); @@ -1584,7 +1588,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, bvh_cache_p, mesh_eval_mutex); - if (looptri_mask != NULL) { + if (looptri_mask != nullptr) { MEM_freeN(looptri_mask); } } @@ -1603,7 +1607,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, break; } - if (data->tree != NULL) { + if (data->tree != nullptr) { #ifdef DEBUG if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) { printf("tree_type %d obtained instead of %d\n", @@ -1631,15 +1635,15 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex) { - BVHTree *tree = NULL; + BVHTree *tree = nullptr; bool is_cached = false; memset(data, 0, sizeof(*data)); if (bvh_cache_p) { - is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL); + is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, nullptr, nullptr); - if (is_cached && tree == NULL) { + if (is_cached && tree == nullptr) { return tree; } } @@ -1650,31 +1654,55 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, switch (bvh_cache_type) { case BVHTREE_FROM_EM_VERTS: if (is_cached == false) { - tree = bvhtree_from_editmesh_verts_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); + tree = bvhtree_from_editmesh_verts_ex(data, + em, + nullptr, + -1, + 0.0f, + tree_type, + 6, + bvh_cache_type, + bvh_cache_p, + mesh_eval_mutex); } else { - data->nearest_callback = NULL; + data->nearest_callback = nullptr; data->raycast_callback = editmesh_verts_spherecast; } break; case BVHTREE_FROM_EM_EDGES: if (is_cached == false) { - tree = bvhtree_from_editmesh_edges_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); + tree = bvhtree_from_editmesh_edges_ex(data, + em, + nullptr, + -1, + 0.0f, + tree_type, + 6, + bvh_cache_type, + bvh_cache_p, + mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ - data->nearest_callback = NULL; /* TODO */ - data->raycast_callback = NULL; /* TODO */ + data->nearest_callback = nullptr; /* TODO */ + data->raycast_callback = nullptr; /* TODO */ } break; case BVHTREE_FROM_EM_LOOPTRI: if (is_cached == false) { - tree = bvhtree_from_editmesh_looptri_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); + tree = bvhtree_from_editmesh_looptri_ex(data, + em, + nullptr, + -1, + 0.0f, + tree_type, + 6, + bvh_cache_type, + bvh_cache_p, + mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ @@ -1694,7 +1722,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, break; } - if (data->tree != NULL) { + if (data->tree != nullptr) { #ifdef DEBUG if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) { printf("tree_type %d obtained instead of %d\n", @@ -1763,7 +1791,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data, { BVHTree *tree = BLI_bvhtree_new(pointcloud->totpoint, 0.0f, tree_type, 6); if (!tree) { - return NULL; + return nullptr; } for (int i = 0; i < pointcloud->totpoint; i++) { @@ -1774,7 +1802,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data, data->coords = pointcloud->co; data->tree = tree; - data->nearest_callback = NULL; + data->nearest_callback = nullptr; return tree; } diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index 30e9ae39b67..eaba5d33a20 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -314,7 +314,7 @@ bool BKE_cachefile_filepath_get(const Main *bmain, if (cache_file->is_sequence && BLI_path_frame_get(r_filepath, &fframe, &frame_len)) { Scene *scene = DEG_get_evaluated_scene(depsgraph); - const float ctime = BKE_scene_frame_get(scene); + const float ctime = BKE_scene_ctime_get(scene); const float fps = (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base); const float frame = BKE_cachefile_time_offset(cache_file, ctime, fps); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 879313783d9..039a971fe2c 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -289,7 +289,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) { dm->dirty |= DM_DIRTY_NORMALS; } - /* TODO DM_DIRTY_TESS_CDLAYERS ? Maybe not though, + /* TODO: DM_DIRTY_TESS_CDLAYERS ? Maybe not though, * since we probably want to switch to looptris? */ CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 09bd397cc78..0fa58a74f2b 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -96,7 +96,7 @@ static BVHTree *bvhtree_build_from_cloth(ClothModifierData *clmd, float epsilon) return NULL; } - /* create quadtree with k=26 */ + /* Create quad-tree with k=26. */ BVHTree *bvhtree = BLI_bvhtree_new(cloth->primitive_num, epsilon, 4, 26); /* fill tree */ @@ -262,17 +262,19 @@ static bool do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int static int do_step_cloth( Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr) { + /* simulate 1 frame forward */ ClothVertex *verts = NULL; Cloth *cloth; ListBase *effectors = NULL; MVert *mvert; unsigned int i = 0; int ret = 0; + bool vert_mass_changed = false; - /* simulate 1 frame forward */ cloth = clmd->clothObject; verts = cloth->verts; mvert = result->mvert; + vert_mass_changed = verts->mass != clmd->sim_parms->mass; /* force any pinned verts to their constrained location. */ for (i = 0; i < clmd->clothObject->mvert_num; i++, verts++) { @@ -283,6 +285,11 @@ static int do_step_cloth( /* Get the current position. */ copy_v3_v3(verts->xconst, mvert[i].co); mul_m4_v3(ob->obmat, verts->xconst); + + if (vert_mass_changed) { + verts->mass = clmd->sim_parms->mass; + SIM_mass_spring_set_implicit_vertex_mass(cloth->implicit, i, verts->mass); + } } effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights, false); @@ -597,7 +604,7 @@ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexC Cloth *cloth = clmd->clothObject; if (clmd->clothObject) { - /* inverse matrix is not uptodate... */ + /* Inverse matrix is not up to date. */ invert_m4_m4(ob->imat, ob->obmat); for (i = 0; i < cloth->mvert_num; i++) { @@ -991,7 +998,7 @@ static void cloth_hair_update_bending_targets(ClothModifierData *clmd) return; } - /* XXX Note: we need to propagate frames from the root up, + /* XXX NOTE: we need to propagate frames from the root up, * but structural hair springs are stored in reverse order. * The bending springs however are then inserted in the same * order as vertices again ... @@ -1049,7 +1056,7 @@ static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd) return; } - /* XXX Note: we need to propagate frames from the root up, + /* XXX NOTE: we need to propagate frames from the root up, * but structural hair springs are stored in reverse order. * The bending springs however are then inserted in the same * order as vertices again ... @@ -1883,7 +1890,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) cloth_hair_update_bending_rest_targets(clmd); } - /* note: the edges may already exist so run reinsert */ + /* NOTE: the edges may already exist so run reinsert. */ /* insert other near springs in edgeset AFTER bending springs are calculated (for selfcolls) */ for (int i = 0; i < numedges; i++) { /* struct springs */ diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 24266dc6bea..c354115e030 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -115,7 +115,7 @@ static void collection_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons ((collection_src->id.flag & LIB_EMBEDDED_DATA) != 0)); /* Do not copy collection's preview (same behavior as for objects). */ - if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO: temp hack. */ BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id); } else { @@ -191,7 +191,7 @@ static ID *collection_owner_get(Main *bmain, ID *id) } } - BLI_assert(!"Embedded collection with no owner. Critical Main inconsistency."); + BLI_assert_msg(0, "Embedded collection with no owner. Critical Main inconsistency."); return NULL; } @@ -522,7 +522,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy) { /* Master collection is not real datablock, can't be removed. */ if (collection->flag & COLLECTION_IS_MASTER) { - BLI_assert(!"Scene master collection can't be deleted"); + BLI_assert_msg(0, "Scene master collection can't be deleted"); return false; } @@ -888,7 +888,7 @@ Collection *BKE_collection_master_add() { /* Not an actual datablock, but owned by scene. */ Collection *master_collection = BKE_libblock_alloc( - NULL, ID_GR, "Master Collection", LIB_ID_CREATE_NO_MAIN); + NULL, ID_GR, BKE_SCENE_COLLECTION_NAME, LIB_ID_CREATE_NO_MAIN); master_collection->id.flag |= LIB_EMBEDDED_DATA; master_collection->flag |= COLLECTION_IS_MASTER; master_collection->color_tag = COLLECTION_COLOR_NONE; @@ -1706,7 +1706,7 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain) for (Collection *collection = bmain->collections.first; collection != NULL; collection = collection->id.next) { if (collection->tag & COLLECTION_TAG_RELATION_REBUILD) { - /* Note: we do not have easy access to 'which collections is root' info in that case, which + /* NOTE: we do not have easy access to 'which collections is root' info in that case, which * means test for cycles in collection relationships may fail here. I don't think that is an * issue in practice here, but worth keeping in mind... */ collection_parents_rebuild_recursive(collection); @@ -1896,7 +1896,7 @@ static void layer_collection_flags_restore_recursive(LayerCollection *layer_coll * and now we moved a new collection to be part of the background this collection should * probably be disabled. * - * Note: If we were to also keep the exclude flag we would need to re-sync the collections. + * NOTE: If we were to also keep the exclude flag we would need to re-sync the collections. */ layer_collection->flag = flag->flag | (layer_collection->flag & LAYER_COLLECTION_EXCLUDE); } @@ -2203,8 +2203,8 @@ void BKE_scene_objects_iterator_end(BLI_Iterator *iter) * Generate a new GSet (or extend given `objects_gset` if not NULL) with all objects referenced by * all collections of given `scene`. * - * \note: This will include objects without a base currently (because they would belong to excluded - * collections only e.g.). + * \note This will include objects without a base currently + * (because they would belong to excluded collections only e.g.). */ GSet *BKE_scene_objects_as_gset(Scene *scene, GSet *objects_gset) { diff --git a/source/blender/blenkernel/intern/colorband.c b/source/blender/blenkernel/intern/colorband.c index d6b318caa5e..52a599a0361 100644 --- a/source/blender/blenkernel/intern/colorband.c +++ b/source/blender/blenkernel/intern/colorband.c @@ -295,7 +295,7 @@ void BKE_colorband_init_from_table_rgba(ColorBand *coba, const int array_len, bool filter_samples) { - /* Note, we could use MAXCOLORBAND here, but results of re-sampling are nicer, + /* NOTE: we could use MAXCOLORBAND here, but results of re-sampling are nicer, * avoid different behavior when limit is hit. */ if (array_len < 2) { /* No Re-sample, just de-duplicate. */ @@ -420,7 +420,7 @@ bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4]) cbd1 = coba->data; - /* Note: when ipotype >= COLBAND_INTERP_B_SPLINE, + /* NOTE: when ipotype >= COLBAND_INTERP_B_SPLINE, * we cannot do early-out with a constant color before first color stop and after last one, * because interpolation starts before and ends after those... */ ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 1484021cb9d..a9f0f69b855 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -873,7 +873,7 @@ static int sort_curvepoints(const void *a1, const void *a2) /* ************************ more CurveMapping calls *************** */ -/* note; only does current curvemap! */ +/* NOTE: only does current curvemap! */ void BKE_curvemapping_changed(CurveMapping *cumap, const bool rem_doubles) { CurveMap *cuma = cumap->cm + cumap->cur; @@ -1267,9 +1267,9 @@ void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap) BLI_INLINE int get_bin_float(float f) { - int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantisation differences */ + int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantization differences */ - /* note: clamp integer instead of float to avoid problems with NaN */ + /* NOTE: clamp integer instead of float to avoid problems with NaN. */ CLAMP(bin, 0, 255); return bin; @@ -1497,7 +1497,7 @@ static void scopes_update_cb(void *__restrict userdata, mul_v3_fl(ycc, INV_255); minmax_v3v3_v3(min, max, ycc); } - /* Increment count for histo. */ + /* Increment count for histogram. */ bin_lum[get_bin_float(luma)]++; bin_r[get_bin_float(rgba[0])]++; bin_g[get_bin_float(rgba[1])]++; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index ca03c9c3de4..47df31e3a2c 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -299,7 +299,10 @@ void BKE_constraint_mat_convertspace(Object *ob, mul_m4_m4m4(mat, imat, mat); /* Use pose-space as stepping stone for other spaces. */ - if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { + if (ELEM(to, + CONSTRAINT_SPACE_LOCAL, + CONSTRAINT_SPACE_PARLOCAL, + CONSTRAINT_SPACE_OWNLOCAL)) { /* Call self with slightly different values. */ BKE_constraint_mat_convertspace( ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); @@ -315,6 +318,17 @@ void BKE_constraint_mat_convertspace(Object *ob, BKE_armature_mat_pose_to_bone(pchan, mat, mat); } } + /* pose to owner local */ + else if (to == CONSTRAINT_SPACE_OWNLOCAL) { + /* pose to local */ + if (pchan->bone) { + BKE_armature_mat_pose_to_bone(pchan, mat, mat); + } + + /* local to owner local (recursive) */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale); + } /* pose to local with parent */ else if (to == CONSTRAINT_SPACE_PARLOCAL) { if (pchan->bone) { @@ -336,17 +350,59 @@ void BKE_constraint_mat_convertspace(Object *ob, } case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */ { + /* local to owner local */ + if (to == CONSTRAINT_SPACE_OWNLOCAL) { + if (pchan->bone) { + copy_m4_m4(diff_mat, pchan->bone->arm_mat); + + if (cob && cob->pchan && cob->pchan->bone) { + invert_m4_m4(imat, cob->pchan->bone->arm_mat); + mul_m4_m4m4(diff_mat, imat, diff_mat); + } + + zero_v3(diff_mat[3]); + invert_m4_m4(imat, diff_mat); + mul_m4_series(mat, diff_mat, mat, imat); + } + } /* local to pose - do inverse procedure that was done for pose to local */ + else { + if (pchan->bone) { + /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ + BKE_armature_mat_bone_to_pose(pchan, mat, mat); + } + + /* use pose-space as stepping stone for other spaces */ + if (ELEM(to, + CONSTRAINT_SPACE_WORLD, + CONSTRAINT_SPACE_PARLOCAL, + CONSTRAINT_SPACE_CUSTOM)) { + /* call self with slightly different values */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + } + } + break; + } + case CONSTRAINT_SPACE_OWNLOCAL: { /* -------------- FROM OWNER LOCAL ---------- */ + /* owner local to local */ if (pchan->bone) { - /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ - BKE_armature_mat_bone_to_pose(pchan, mat, mat); + copy_m4_m4(diff_mat, pchan->bone->arm_mat); + + if (cob && cob->pchan && cob->pchan->bone) { + invert_m4_m4(imat, cob->pchan->bone->arm_mat); + mul_m4_m4m4(diff_mat, imat, diff_mat); + } + + zero_v3(diff_mat[3]); + invert_m4_m4(imat, diff_mat); + mul_m4_series(mat, imat, mat, diff_mat); } - /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_CUSTOM)) { + if (to != CONSTRAINT_SPACE_LOCAL) { /* call self with slightly different values */ BKE_constraint_mat_convertspace( - ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale); } break; } @@ -358,7 +414,11 @@ void BKE_constraint_mat_convertspace(Object *ob, } /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_CUSTOM)) { + if (ELEM(to, + CONSTRAINT_SPACE_WORLD, + CONSTRAINT_SPACE_LOCAL, + CONSTRAINT_SPACE_OWNLOCAL, + CONSTRAINT_SPACE_CUSTOM)) { /* call self with slightly different values */ BKE_constraint_mat_convertspace( ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); @@ -470,7 +530,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ /* when not in EditMode, use the 'final' evaluated mesh, depsgraph * ensures we build with CD_MDEFORMVERT layer */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); BMEditMesh *em = BKE_editmesh_from_object(ob); float plane[3]; float imat[3][3], tmat[3][3]; @@ -488,17 +548,17 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ float normal[3] = {0.0f, 0.0f, 0.0f}; float weightsum = 0.0f; if (me_eval) { - MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT); + const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT); int numVerts = me_eval->totvert; /* check that dvert is a valid pointers (just in case) */ if (dvert) { - MDeformVert *dv = dvert; - MVert *mv = me_eval->mvert; /* get the average of all verts with that are in the vertex-group */ - for (int i = 0; i < numVerts; i++, dv++, mv++) { - MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup); + for (int i = 0; i < numVerts; i++) { + const MDeformVert *dv = &dvert[i]; + const MVert *mv = &me_eval->mvert[i]; + const MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup); if (dw && dw->weight > 0.0f) { float nor[3]; @@ -867,7 +927,7 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph), /* This following macro should be used for all standard single-target *_flush_tars functions * to save typing and reduce maintenance woes. - * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed) + * NOTE: the pointer to ct will be changed to point to the next in the list (as it gets removed) * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ @@ -889,7 +949,7 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph), /* This following macro should be used for all standard single-target *_flush_tars functions * to save typing and reduce maintenance woes. It does not do the subtarget related operations. - * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed) + * NOTE: the pointer to ct will be changed to point to the next in the list (as it gets removed) * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ @@ -1088,7 +1148,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar } } -/* XXX note, con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in readfile.c */ +/* XXX NOTE: con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in `readfile.c`. */ static bConstraintTypeInfo CTI_CHILDOF = { CONSTRAINT_TYPE_CHILDOF, /* type */ sizeof(bChildOfConstraint), /* size */ @@ -1205,7 +1265,7 @@ static void vectomat(const float vec[3], u[2] = 1; } - /* note: even though 'n' is normalized, don't use 'project_v3_v3v3_normalized' below + /* NOTE: even though 'n' is normalized, don't use 'project_v3_v3v3_normalized' below * because precision issues cause a problem in near degenerate states, see: T53455. */ /* project the up vector onto the plane specified by n */ @@ -1459,7 +1519,7 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph), unit_m4(ct->matrix); - /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, + /* NOTE: when creating constraints that follow path, the curve gets the CU_PATH set now, * currently for paths to work it needs to go through the bevlist/displist system (ton) */ @@ -1543,8 +1603,8 @@ static void followpath_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /* un-apply scaling caused by path */ if ((data->followflag & FOLLOWPATH_RADIUS) == 0) { - /* XXX: Assume that scale correction means that radius - * will have some scale error in it - Campbell. */ + /* XXX(campbell): Assume that scale correction means that radius + * will have some scale error in it. */ float obsize[3]; mat4_to_size(obsize, cob->matrix); @@ -2235,21 +2295,51 @@ static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t bConstraintTarget *ct = targets->first; if (VALID_CONS_TARGET(ct)) { + float target_mat[4][4]; + + copy_m4_m4(target_mat, ct->matrix); + + /* Remove the shear of the target matrix if enabled. + * Use Y as the axis since it's the natural default for bones. */ + if (data->flag & TRANSLIKE_REMOVE_TARGET_SHEAR) { + orthogonalize_m4_stable(target_mat, 1, false); + } + + /* Finally, combine the matrices. */ switch (data->mix_mode) { case TRANSLIKE_MIX_REPLACE: - copy_m4_m4(cob->matrix, ct->matrix); + copy_m4_m4(cob->matrix, target_mat); break; + /* Simple matrix multiplication. */ + case TRANSLIKE_MIX_BEFORE_FULL: + mul_m4_m4m4(cob->matrix, target_mat, cob->matrix); + break; + + case TRANSLIKE_MIX_AFTER_FULL: + mul_m4_m4m4(cob->matrix, cob->matrix, target_mat); + break; + + /* Aligned Inherit Scale emulation. */ case TRANSLIKE_MIX_BEFORE: - mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix); + mul_m4_m4m4_aligned_scale(cob->matrix, target_mat, cob->matrix); break; case TRANSLIKE_MIX_AFTER: - mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix); + mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, target_mat); + break; + + /* Fully separate handling of channels. */ + case TRANSLIKE_MIX_BEFORE_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, target_mat, cob->matrix); + break; + + case TRANSLIKE_MIX_AFTER_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, target_mat); break; default: - BLI_assert(!"Unknown Copy Transforms mix mode"); + BLI_assert_msg(0, "Unknown Copy Transforms mix mode"); } } } @@ -2901,7 +2991,7 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ break; default: - BLI_assert(!"Unknown Action mix mode"); + BLI_assert_msg(0, "Unknown Action mix mode"); } } } @@ -3791,7 +3881,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar unit_m4(targetMatrix); INIT_MINMAX(curveMin, curveMax); - /* XXX - don't think this is good calling this here - campbell */ + /* XXX(campbell): don't think this is good calling this here. */ BKE_object_minmax(ct->tar, curveMin, curveMax, true); /* get targetmatrix */ @@ -4242,7 +4332,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph), float mat[4][4]; float no[3] = {0.0f, 0.0f, 0.0f}; - /* TODO should use FLT_MAX.. but normal projection doenst yet supports it */ + /* TODO: should use FLT_MAX.. but normal projection doesn't yet supports it. */ hit.index = -1; hit.dist = (scon->projLimit == 0.0f) ? BVH_RAYCAST_DIST_MAX : scon->projLimit; @@ -5009,7 +5099,7 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co } Object *depth_object = context->depth_object; - Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object); + const Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object); if (depth_mesh == NULL) { return; } @@ -6269,7 +6359,7 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, * (T26014 and T25725), since some constraints may not convert the solution back to the input * space before blending but all are guaranteed to end up in good "world-space" result. */ - /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, + /* NOTE: all kind of stuff here before (caused trouble), much easier to just interpolate, * or did I miss something? -jahka (r.32105) */ if (enf < 1.0f) { float solution[4][4]; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 1028790856c..dced945bea0 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -1448,6 +1448,36 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list) return ctx_data_collection_get(C, "editable_gpencil_strokes", list); } +const AssetLibraryReference *CTX_wm_asset_library(const bContext *C) +{ + return ctx_data_pointer_get(C, "asset_library"); +} + +AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid) +{ + AssetHandle *asset_handle_p = + (AssetHandle *)CTX_data_pointer_get_type(C, "asset_handle", &RNA_AssetHandle).data; + if (asset_handle_p) { + *r_is_valid = true; + return *asset_handle_p; + } + + /* If the asset handle was not found in context directly, try if there's an active file with + * asset data there instead. Not nice to have this here, would be better to have this in + * `ED_asset.h`, but we can't include that in BKE. Even better would be not needing this at all + * and being able to have editors return this in the usual `context` callback. But that would + * require returning a non-owning pointer, which we don't have in the Asset Browser (yet). */ + FileDirEntry *file = + (FileDirEntry *)CTX_data_pointer_get_type(C, "active_file", &RNA_FileSelectEntry).data; + if (file && file->asset_data) { + *r_is_valid = true; + return (AssetHandle){.file_data = file}; + } + + *r_is_valid = false; + return (AssetHandle){0}; +} + Depsgraph *CTX_data_depsgraph_pointer(const bContext *C) { Main *bmain = CTX_data_main(C); diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 4e1ec9ba35e..26894495777 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -398,8 +398,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, if (crazyspace_modifier_supports_deform_matrices(md)) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (defmats == NULL) { - /* NOTE: Evaluated object si re-set to its original undeformed - * state. */ + /* NOTE: Evaluated object is re-set to its original un-deformed state. */ Mesh *me = object_eval.data; me_eval = BKE_mesh_copy_for_eval(me, true); crazyspace_init_verts_and_matrices(me_eval, &defmats, &deformedVerts); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index a5538453248..24615dd8c2b 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -2123,8 +2123,8 @@ static void tilt_bezpart(const BezTriple *prevbezt, if (radius_array) { if (nu->radius_interp == KEY_CU_EASE) { /* Support 2.47 ease interp - * Note! - this only takes the 2 points into account, - * giving much more localized results to changes in radius, sometimes you want that */ + * NOTE: this only takes the 2 points into account, + * giving much more localized results to changes in radius, sometimes you want that. */ *radius_array = prevbezt->radius + (bezt->radius - prevbezt->radius) * (3.0f * fac * fac - 2.0f * fac * fac * fac); } @@ -2490,7 +2490,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) cross_v3_v3v3(cross_tmp, bevp1->tan, bevp1->dir); normalize_v3(cross_tmp); - tri_to_quat(bevp1->quat, zero, cross_tmp, bevp1->tan); /* XXX - could be faster */ + tri_to_quat(bevp1->quat, zero, cross_tmp, bevp1->tan); /* XXX: could be faster. */ /* bevp0 = bevp1; */ /* UNUSED */ bevp1 = bevp2; @@ -2559,8 +2559,8 @@ static void make_bevel_list_segment_2D(BevList *bl) static void make_bevel_list_2D(BevList *bl) { - /* note: bevp->dir and bevp->quat are not needed for beveling but are - * used when making a path from a 2D curve, therefore they need to be set - Campbell */ + /* NOTE(campbell): `bevp->dir` and `bevp->quat` are not needed for beveling but are + * used when making a path from a 2D curve, therefore they need to be set. */ BevPoint *bevp0, *bevp1, *bevp2; int nr; @@ -3658,7 +3658,7 @@ static bool tridiagonal_solve_with_limits(float *a, * is affected by all other points of the curve segment, in practice the influence * decreases exponentially with distance. * - * Note: this algorithm assumes that the handle horizontal size is always 1/3 of the + * NOTE: this algorithm assumes that the handle horizontal size is always 1/3 of the * of the interval to the next point. This rule ensures linear interpolation of time. * * ^ height (co 1) diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c index 7deac4e4f19..28b7c2dfba0 100644 --- a/source/blender/blenkernel/intern/curve_deform.c +++ b/source/blender/blenkernel/intern/curve_deform.c @@ -168,7 +168,7 @@ static bool calc_curve_deform( * * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell * - * note: moved functions into quat_apply_track/vec_apply_track + * NOTE: moved functions into quat_apply_track/vec_apply_track */ copy_qt_qt(quat, new_quat); copy_v3_v3(cent, co); diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc index 72ee2587c8a..8e1577ab072 100644 --- a/source/blender/blenkernel/intern/curve_eval.cc +++ b/source/blender/blenkernel/intern/curve_eval.cc @@ -335,4 +335,4 @@ void CurveEval::assert_valid_point_attributes() const ATTR_DOMAIN_POINT); } #endif -}
\ No newline at end of file +} diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 08d0af45e92..7aa9d1958eb 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -105,8 +105,10 @@ typedef struct LayerTypeInfo { /** * default layer name. - * note! when NULL this is a way to ensure there is only ever one item - * see: CustomData_layertype_is_singleton() */ + * + * \note when NULL this is a way to ensure there is only ever one item + * see: CustomData_layertype_is_singleton(). + */ const char *defaultname; /** @@ -329,7 +331,7 @@ static void layerInterp_normal(const void **sources, int count, void *dest) { - /* Note: This is linear interpolation, which is not optimal for vectors. + /* NOTE: This is linear interpolation, which is not optimal for vectors. * Unfortunately, spherical interpolation of more than two values is hairy, * so for now it will do... */ float no[3] = {0.0f}; @@ -1594,7 +1596,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 14: CD_ORCO */ {sizeof(float[3]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 15: CD_MTEXPOLY */ /* DEPRECATED */ - /* note, when we expose the UV Map / TexFace split to the user, + /* NOTE: when we expose the UV Map / TexFace split to the user, * change this back to face Texture. */ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 16: CD_MLOOPUV */ @@ -3555,7 +3557,7 @@ bool CustomData_bmesh_merge(const CustomData *source, totelem = bm->totface; break; default: /* should never happen */ - BLI_assert(!"invalid type given"); + BLI_assert_msg(0, "invalid type given"); iter_type = BM_VERTS_OF_MESH; totelem = bm->totvert; break; @@ -3805,7 +3807,7 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int return POINTER_OFFSET(block, data->layers[layer_index + n].offset); } -/* Gets from the layer at physical index n, note: doesn't check type. */ +/* Gets from the layer at physical index n, NOTE: doesn't check type. */ void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) { if (n < 0 || n >= data->totlayer) { @@ -4974,7 +4976,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap, size_t tmp_buff_size = 32; const void **tmp_data_src = NULL; - /* Note: NULL data_src may happen and be valid (see vgroups...). */ + /* NOTE: NULL data_src may happen and be valid (see vgroups...). */ if (!data_dst) { return; } @@ -4991,7 +4993,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap, else { const LayerTypeInfo *type_info = layerType_getInfo(data_type); - /* Note: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/ */ + /* NOTE: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/. */ data_size = (size_t)type_info->size; data_step = laymap->elem_size ? laymap->elem_size : data_size; data_offset = laymap->data_offset; diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c index 314d5f4ff82..ef86a65f47d 100644 --- a/source/blender/blenkernel/intern/customdata_file.c +++ b/source/blender/blenkernel/intern/customdata_file.c @@ -361,9 +361,9 @@ bool cdf_write_open(CDataFile *cdf, const char *filename) cdf->writef = f; - /* fill header */ + /* Fill header. */ header = &cdf->header; - /* strcpy(, "BCDF"); // terminator out of range */ + /* Copy "BCDF" (string terminator out of range). */ header->ID[0] = 'B'; header->ID[1] = 'C'; header->ID[2] = 'D'; diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 12269cf0d51..605061570b8 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -691,7 +691,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map } if (data_dst_to_delete) { - /* Note: + /* NOTE: * This won't affect newly created layers, if any, since tot_dst has not been updated! * Also, looping backward ensures us we do not suffer * from index shifting when deleting a layer. */ @@ -764,7 +764,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, } } else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) { - /* Note: use_delete has not much meaning in this case, ignored. */ + /* NOTE: use_delete has not much meaning in this case, ignored. */ if (fromlayers >= 0) { /* Real-layer index */ idx_src = fromlayers; @@ -1437,7 +1437,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (vgroup_name) { mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT); if (mdef) { - vg_idx = BKE_object_defgroup_name_index(ob_dst, vgroup_name); + vg_idx = BKE_id_defgroup_name_index(&me_dst->id, vgroup_name); } } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index e6ef569d4b9..f7ef84728b6 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -29,6 +29,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_gpencil_types.h" +#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -64,7 +66,9 @@ bDeformGroup *BKE_object_defgroup_new(Object *ob, const char *name) BLI_strncpy(defgroup->name, name, sizeof(defgroup->name)); - BLI_addtail(&ob->defbase, defgroup); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + BLI_addtail(defbase, defgroup); BKE_object_defgroup_unique_name(defgroup, ob); BKE_object_batch_cache_dirty_tag(ob); @@ -484,18 +488,120 @@ void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int } } +bool BKE_object_supports_vertex_groups(const Object *ob) +{ + const ID *id = (const ID *)ob->data; + if (id == NULL) { + return false; + } + + return ELEM(GS(id->name), ID_ME, ID_LT, ID_GD); +} + +const ListBase *BKE_id_defgroup_list_get(const ID *id) +{ + switch (GS(id->name)) { + case ID_ME: { + const Mesh *me = (const Mesh *)id; + return &me->vertex_group_names; + } + case ID_LT: { + const Lattice *lt = (const Lattice *)id; + return <->vertex_group_names; + } + case ID_GD: { + const bGPdata *gpd = (const bGPdata *)id; + return &gpd->vertex_group_names; + } + default: { + BLI_assert_unreachable(); + } + } + return NULL; +} + +static const int *object_defgroup_active_index_get_p(const Object *ob) +{ + BLI_assert(BKE_object_supports_vertex_groups(ob)); + switch (ob->type) { + case OB_MESH: { + const Mesh *mesh = (const Mesh *)ob->data; + return &mesh->vertex_group_active_index; + } + case OB_LATTICE: { + const Lattice *lattice = (const Lattice *)ob->data; + return &lattice->vertex_group_active_index; + } + case OB_GPENCIL: { + const bGPdata *gpd = (const bGPdata *)ob->data; + return &gpd->vertex_group_active_index; + } + } + return NULL; +} + +ListBase *BKE_id_defgroup_list_get_mutable(ID *id) +{ + /* Cast away const just for the accessor. */ + return (ListBase *)BKE_id_defgroup_list_get(id); +} + bDeformGroup *BKE_object_defgroup_find_name(const Object *ob, const char *name) { - return (name && name[0] != '\0') ? - BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name)) : - NULL; + if (name == NULL || name[0] == '\0') { + return NULL; + } + const ListBase *defbase = BKE_object_defgroup_list(ob); + return BLI_findstring(defbase, name, offsetof(bDeformGroup, name)); +} + +int BKE_id_defgroup_name_index(const ID *id, const char *name) +{ + if (name == NULL || name[0] == '\0') { + return -1; + } + const ListBase *defbase = BKE_id_defgroup_list_get(id); + return BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name)); +} + +const ListBase *BKE_object_defgroup_list(const Object *ob) +{ + BLI_assert(BKE_object_supports_vertex_groups(ob)); + return BKE_id_defgroup_list_get((const ID *)ob->data); } int BKE_object_defgroup_name_index(const Object *ob, const char *name) { - return (name && name[0] != '\0') ? - BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) : - -1; + return BKE_id_defgroup_name_index((ID *)ob->data, name); +} + +ListBase *BKE_object_defgroup_list_mutable(Object *ob) +{ + BLI_assert(BKE_object_supports_vertex_groups(ob)); + return BKE_id_defgroup_list_get_mutable((ID *)ob->data); +} + +int BKE_object_defgroup_count(const Object *ob) +{ + return BLI_listbase_count(BKE_object_defgroup_list(ob)); +} + +/** + * \note For historical reasons, the index starts at 1 rather than 0. + */ +int BKE_object_defgroup_active_index_get(const Object *ob) +{ + return *object_defgroup_active_index_get_p(ob); +} + +/** + * \note For historical reasons, the index starts at 1 rather than 0. + */ +void BKE_object_defgroup_active_index_set(Object *ob, const int new_index) +{ + /* Cast away const just for the accessor. */ + int *index = (int *)object_defgroup_active_index_get_p(ob); + *index = new_index; } /** @@ -503,7 +609,8 @@ int BKE_object_defgroup_name_index(const Object *ob, const char *name) */ int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default) { - int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + int defbase_tot = *flip_map_len = BLI_listbase_count(defbase); if (defbase_tot == 0) { return NULL; @@ -517,7 +624,7 @@ int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const boo map[i] = -1; } - for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { if (map[i] == -1) { /* may be calculated previously */ /* in case no valid value is found, use this */ @@ -547,7 +654,8 @@ int *BKE_object_defgroup_flip_map_single(const Object *ob, const bool use_default, int defgroup) { - int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + int defbase_tot = *flip_map_len = BLI_listbase_count(defbase); if (defbase_tot == 0) { return NULL; @@ -561,7 +669,7 @@ int *BKE_object_defgroup_flip_map_single(const Object *ob, map[i] = use_default ? i : -1; } - dg = BLI_findlink(&ob->defbase, defgroup); + dg = BLI_findlink(defbase, defgroup); BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip)); if (!STREQ(name_flip, dg->name)) { @@ -578,7 +686,8 @@ int *BKE_object_defgroup_flip_map_single(const Object *ob, int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_default) { - bDeformGroup *dg = BLI_findlink(&ob->defbase, index); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, index); int flip_index = -1; if (dg) { @@ -595,9 +704,10 @@ int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_d static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob) { + const ListBase *defbase = BKE_object_defgroup_list(ob); bDeformGroup *curdef; - for (curdef = ob->defbase.first; curdef; curdef = curdef->next) { + for (curdef = defbase->first; curdef; curdef = curdef->next) { if (dg != curdef) { if (STREQ(curdef->name, name)) { return true; @@ -716,7 +826,7 @@ MDeformWeight *BKE_defvert_ensure_index(MDeformVert *dvert, const int defgroup) return dw_new; } -/* TODO. merge with code above! */ +/* TODO: merge with code above! */ /** * Adds the given vertex to the specified vertex group, with given weight. @@ -1189,7 +1299,10 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, { int idx_src; int idx_dst; - int tot_dst = BLI_listbase_count(&ob_dst->defbase); + const ListBase *src_list = BKE_object_defgroup_list(ob_src); + ListBase *dst_defbase = BKE_object_defgroup_list_mutable(ob_dst); + + int tot_dst = BLI_listbase_count(dst_defbase); const size_t elem_size = sizeof(*((MDeformVert *)NULL)); @@ -1218,7 +1331,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, } else if (use_delete && idx_dst > idx_src) { while (idx_dst-- > idx_src) { - BKE_object_defgroup_remove(ob_dst, ob_dst->defbase.last); + BKE_object_defgroup_remove(ob_dst, dst_defbase->last); } } if (r_map) { @@ -1255,7 +1368,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, if (use_delete) { /* Remove all unused dst vgroups first, simpler in this case. */ - for (dg_dst = ob_dst->defbase.first; dg_dst;) { + for (dg_dst = dst_defbase->first; dg_dst;) { bDeformGroup *dg_dst_next = dg_dst->next; if (BKE_object_defgroup_name_index(ob_src, dg_dst->name) == -1) { @@ -1265,7 +1378,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, } } - for (idx_src = 0, dg_src = ob_src->defbase.first; idx_src < num_layers_src; + for (idx_src = 0, dg_src = src_list->first; idx_src < num_layers_src; idx_src++, dg_src = dg_src->next) { if (!use_layers_src[idx_src]) { continue; @@ -1274,7 +1387,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, if ((idx_dst = BKE_object_defgroup_name_index(ob_dst, dg_src->name)) == -1) { if (use_create) { BKE_object_defgroup_add_name(ob_dst, dg_src->name); - idx_dst = ob_dst->actdef - 1; + idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1; } else { /* If we are not allowed to create missing dst vgroups, just skip matching src one. */ @@ -1334,14 +1447,18 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map, const size_t elem_size = sizeof(*((MDeformVert *)NULL)); - /* Note: + /* NOTE: * VGroups are a bit hairy, since their layout is defined on object level (ob->defbase), * while their actual data is a (mesh) CD layer. * This implies we may have to handle data layout itself while having NULL data itself, * and even have to support NULL data_src in transfer data code * (we always create a data_dst, though). + * + * Note: Above comment is outdated, but this function was written when that was true. */ - if (BLI_listbase_is_empty(&ob_src->defbase)) { + + const ListBase *src_defbase = BKE_object_defgroup_list(ob_src); + if (BLI_listbase_is_empty(src_defbase)) { if (use_delete) { BKE_object_defgroup_remove_all(ob_dst); } @@ -1357,39 +1474,41 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map, } if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) { - /* Note: use_delete has not much meaning in this case, ignored. */ + /* NOTE: use_delete has not much meaning in this case, ignored. */ if (fromlayers >= 0) { idx_src = fromlayers; - if (idx_src >= BLI_listbase_count(&ob_src->defbase)) { + if (idx_src >= BLI_listbase_count(src_defbase)) { /* This can happen when vgroups are removed from source object... * Remapping would be really tricky here, we'd need to go over all objects in * Main every time we delete a vgroup... for now, simpler and safer to abort. */ return false; } } - else if ((idx_src = ob_src->actdef - 1) == -1) { + else if ((idx_src = BKE_object_defgroup_active_index_get(ob_src) - 1) == -1) { return false; } if (tolayers >= 0) { - /* Note: in this case we assume layer exists! */ + /* NOTE: in this case we assume layer exists! */ idx_dst = tolayers; - BLI_assert(idx_dst < BLI_listbase_count(&ob_dst->defbase)); + const ListBase *dst_defbase = BKE_object_defgroup_list(ob_dst); + BLI_assert(idx_dst < BLI_listbase_count(dst_defbase)); + UNUSED_VARS_NDEBUG(dst_defbase); } else if (tolayers == DT_LAYERS_ACTIVE_DST) { - if ((idx_dst = ob_dst->actdef - 1) == -1) { + if ((idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1) == -1) { bDeformGroup *dg_src; if (!use_create) { return true; } - dg_src = BLI_findlink(&ob_src->defbase, idx_src); + dg_src = BLI_findlink(src_defbase, idx_src); BKE_object_defgroup_add_name(ob_dst, dg_src->name); - idx_dst = ob_dst->actdef - 1; + idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1; } } else if (tolayers == DT_LAYERS_INDEX_DST) { - int num = BLI_listbase_count(&ob_src->defbase); + int num = BLI_listbase_count(src_defbase); idx_dst = idx_src; if (num <= idx_dst) { if (!use_create) { @@ -1402,13 +1521,13 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map, } } else if (tolayers == DT_LAYERS_NAME_DST) { - bDeformGroup *dg_src = BLI_findlink(&ob_src->defbase, idx_src); + bDeformGroup *dg_src = BLI_findlink(src_defbase, idx_src); if ((idx_dst = BKE_object_defgroup_name_index(ob_dst, dg_src->name)) == -1) { if (!use_create) { return true; } BKE_object_defgroup_add_name(ob_dst, dg_src->name); - idx_dst = ob_dst->actdef - 1; + idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1; } } else { @@ -1531,6 +1650,13 @@ void BKE_defvert_weight_to_rgb(float r_rgb[3], const float weight) /** \name .blend file I/O * \{ */ +void BKE_defbase_blend_write(BlendWriter *writer, const ListBase *defbase) +{ + LISTBASE_FOREACH (bDeformGroup *, defgroup, defbase) { + BLO_write_struct(writer, bDeformGroup, defgroup); + } +} + void BKE_defvert_blend_write(BlendWriter *writer, int count, MDeformVert *dvlist) { if (dvlist == NULL) { diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index cfe4701fb69..a4ffaa8b10b 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -1694,7 +1694,7 @@ static void boundbox_displist_object(Object *ob) ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__); } - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval) { BKE_object_boundbox_calc_from_mesh(ob, mesh_eval); } diff --git a/source/blender/blenkernel/intern/displist_tangent.c b/source/blender/blenkernel/intern/displist_tangent.c index 88fef1a4cfd..5c969d52aea 100644 --- a/source/blender/blenkernel/intern/displist_tangent.c +++ b/source/blender/blenkernel/intern/displist_tangent.c @@ -171,7 +171,7 @@ static void dlsurf_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext, int idx = face_to_vert_index(dlt, face_num, vert_index); - /* Note: For some reason the shading U and V are swapped compared to the + /* NOTE: For some reason the shading U and V are swapped compared to the * one described in the surface format. */ r_uv[0] = (idx / dlt->dl->nr) / (float)(dlt->v_len); r_uv[1] = (idx % dlt->dl->nr) / (float)(dlt->u_len); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 2eb18a06799..52996e3bcc7 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -248,7 +248,7 @@ typedef struct PaintAdjData { int *n_target; /** Index to start reading n_target for each point. */ int *n_index; - /** Num of neighs for each point. */ + /** Number of neighbors for each point. */ int *n_num; /** Vertex adjacency flags. */ int *flags; @@ -2288,7 +2288,8 @@ static void dynamic_paint_create_uv_surface_direct_cb( /* Loop through samples, starting from middle point */ for (int sample = 0; sample < 5; sample++) { /* Loop through every face in the mesh */ - /* XXX TODO This is *horrible* with big meshes, should use a 2D BVHTree over UV tris here! */ + /* XXX TODO: This is *horrible* with big meshes, should use a 2D BVHTree over UV tris here! + */ for (int i = 0; i < tottri; i++) { /* Check uv bb */ if ((faceBB[i].min[0] > point[sample][0]) || (faceBB[i].min[1] > point[sample][1]) || @@ -2476,7 +2477,7 @@ static int dynamic_paint_find_neighbor_pixel(const DynamicPaintCreateUVSurfaceDa const int py, const int n_index) { - /* Note: Current method only uses polygon edges to detect neighboring pixels. + /* NOTE: Current method only uses polygon edges to detect neighboring pixels. * -> It doesn't always lead to the optimum pixel but is accurate enough * and faster/simpler than including possible face tip point links) */ @@ -3817,7 +3818,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph, ob, true, SUBFRAME_RECURSION, - BKE_scene_frame_get(scene), + BKE_scene_ctime_get(scene), eModifierType_DynamicPaint); mesh_p = BKE_mesh_copy_for_eval(dynamicPaint_brush_mesh_get(brush), false); numOfVerts_p = mesh_p->totvert; @@ -3833,7 +3834,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph, ob, true, SUBFRAME_RECURSION, - BKE_scene_frame_get(scene), + BKE_scene_ctime_get(scene), eModifierType_DynamicPaint); mesh_c = dynamicPaint_brush_mesh_get(brush); numOfVerts_c = mesh_c->totvert; @@ -3893,7 +3894,7 @@ static void dynamicPaint_brushObjectCalculateVelocity( ob, false, SUBFRAME_RECURSION, - BKE_scene_frame_get(scene), + BKE_scene_ctime_get(scene), eModifierType_DynamicPaint); copy_m4_m4(prev_obmat, ob->obmat); @@ -3905,7 +3906,7 @@ static void dynamicPaint_brushObjectCalculateVelocity( ob, false, SUBFRAME_RECURSION, - BKE_scene_frame_get(scene), + BKE_scene_ctime_get(scene), eModifierType_DynamicPaint); /* calculate speed */ @@ -4190,8 +4191,8 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( /* calculate barycentric weights for hit point */ interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, hitCoord); - /* simple check based on brush surface velocity, - * todo: perhaps implement something that handles volume movement as well. */ + /* Simple check based on brush surface velocity, + * TODO: perhaps implement something that handles volume movement as well. */ /* interpolate vertex speed vectors to get hit point velocity */ interp_v3_v3v3v3(brushPointVelocity, @@ -4881,7 +4882,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, cons 0, sData->total_points, sData, dynamic_paint_prepare_adjacency_cb, &settings); /* calculate average values (single thread). - * Note: tried to put this in threaded callback (using _reduce feature), + * NOTE: tried to put this in threaded callback (using _reduce feature), * but gave ~30% slower result! */ bData->average_dist = 0.0; for (index = 0; index < sData->total_points; index++) { @@ -5521,7 +5522,7 @@ static void dynamicPaint_doEffectStep( if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force) { const float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * timescale / 2.0f; - /* Same as BLI_bitmask, but handled atomicaly as 'ePoint' locks. */ + /* Same as #BLI_bitmask, but handled atomically as 'ePoint' locks. */ const size_t point_locks_size = (sData->total_points / 8) + 1; uint8_t *point_locks = MEM_callocN(sizeof(*point_locks) * point_locks_size, __func__); @@ -6069,7 +6070,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface, if (bData) { const bool surface_moved = dynamicPaint_surfaceHasMoved(surface, ob); - /* get previous speed for accelertaion */ + /* Get previous speed for acceleration. */ if (do_accel_data && bData->prev_velocity && bData->velocity) { memcpy(bData->prev_velocity, bData->velocity, sData->total_points * sizeof(Vec3f)); } @@ -6270,7 +6271,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph, brushObj, true, SUBFRAME_RECURSION, - BKE_scene_frame_get(scene), + BKE_scene_ctime_get(scene), eModifierType_DynamicPaint); } @@ -6311,7 +6312,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph, brushObj, true, SUBFRAME_RECURSION, - BKE_scene_frame_get(scene), + BKE_scene_ctime_get(scene), eModifierType_DynamicPaint); } diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 49c2a2cbd89..9cae74e4e9a 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -39,15 +39,14 @@ #include "BKE_mesh_wrapper.h" #include "BKE_object.h" -BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate) +/** + * \note The caller is responsible for ensuring triangulation data, + * typically by calling #BKE_editmesh_looptri_calc. + */ +BMEditMesh *BKE_editmesh_create(BMesh *bm) { BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__); - em->bm = bm; - if (do_tessellate) { - BKE_editmesh_looptri_calc(em); - } - return em; } @@ -209,7 +208,7 @@ void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em, }); } -void BKE_editmesh_free_derivedmesh(BMEditMesh *em) +void BKE_editmesh_free_derived_caches(BMEditMesh *em) { if (em->mesh_eval_cage) { BKE_id_free(NULL, em->mesh_eval_cage); @@ -223,9 +222,9 @@ void BKE_editmesh_free_derivedmesh(BMEditMesh *em) } /* Does not free the #BMEditMesh struct itself. */ -void BKE_editmesh_free(BMEditMesh *em) +void BKE_editmesh_free_data(BMEditMesh *em) { - BKE_editmesh_free_derivedmesh(em); + BKE_editmesh_free_derived_caches(em); if (em->looptris) { MEM_freeN(em->looptris); @@ -330,7 +329,7 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me) * otherwise there is no way to edit them. * Similar code to #MESH_OT_customdata_custom_splitnormals_add operator, * we want to keep same shading in case we were using auto-smooth so far. - * Note: there is a problem here, which is that if someone starts a normal editing operation on + * NOTE: there is a problem here, which is that if someone starts a normal editing operation on * previously auto-smooth-ed mesh, and cancel that operation, generated CLNORS data remain, * with related sharp edges (and hence auto-smooth is 'lost'). * Not sure how critical this is, and how to fix that issue? */ diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index 9e0e1933a00..087481b1b5d 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -117,7 +117,7 @@ BMBVHTree *BKE_bmbvh_new_ex(BMesh *bm, for (int i = 0; i < looptris_tot; i++) { if (test_fn) { - /* Note: the arrays won't align now! Take care. */ + /* NOTE: the arrays won't align now! Take care. */ f_test = looptris[i][0]->f; if (f_test != f_test_prev) { test_fn_ret = test_fn(f_test, user_data); diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c index d849f4ab37d..da4ea742656 100644 --- a/source/blender/blenkernel/intern/editmesh_tangent.c +++ b/source/blender/blenkernel/intern/editmesh_tangent.c @@ -25,6 +25,7 @@ #include "DNA_defs.h" #include "DNA_meshdata_types.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_editmesh_tangent.h" #include "BKE_mesh.h" @@ -381,7 +382,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; #endif mesh2tangent->precomputedFaceNormals = poly_normals; - /* Note, we assume we do have tessellated loop normals at this point + /* NOTE: we assume we do have tessellated loop normals at this point * (in case it is object-enabled), have to check this is valid. */ mesh2tangent->precomputedLoopNormals = loop_normals; mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 97aba5e787d..1b628b16802 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -716,7 +716,7 @@ int get_effector_data(EffectorCache *eff, } else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) { /* TODO: hair and points object support */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); if (me_eval != NULL) { copy_v3_v3(efd->loc, me_eval->mvert[*efd->index].co); normal_short_to_float_v3(efd->nor, me_eval->mvert[*efd->index].no); @@ -830,7 +830,7 @@ static void get_effector_tot( if (eff->pd->shape == PFIELD_SHAPE_POINTS) { /* TODO: hair and points object support */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); *tot = me_eval != NULL ? me_eval->totvert : 1; if (*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) { diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 7fe7b38e120..8f47a7e75d4 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2147,7 +2147,7 @@ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime) * \{ */ /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") - * Note: this is also used for drivers. + * NOTE: this is also used for drivers. */ static float evaluate_fcurve_ex(FCurve *fcu, float evaltime, float cvalue) { @@ -2194,9 +2194,9 @@ float evaluate_fcurve(FCurve *fcu, float evaltime) float evaluate_fcurve_only_curve(FCurve *fcu, float evaltime) { - /* Can be used to evaluate the (keyframed) fcurve only. - * Also works for driver-fcurves when the driver itself is not relevant. - * E.g. when inserting a keyframe in a driver fcurve. */ + /* Can be used to evaluate the (key-framed) f-curve only. + * Also works for driver-f-curves when the driver itself is not relevant. + * E.g. when inserting a keyframe in a driver f-curve. */ return evaluate_fcurve_ex(fcu, evaltime, 0.0); } diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 947417af55d..2b48683a3a8 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -1283,10 +1283,10 @@ static void compute_obstaclesemission(Scene *scene, # endif /* Update frame time, this is considering current subframe fraction * BLI_mutex_lock() called in manta_step(), so safe to update subframe here - * TODO(sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph) + * TODO(sebbas): Using BKE_scene_ctime_get(scene) instead of new DEG_get_ctime(depsgraph) * as subframes don't work with the latter yet. */ BKE_object_modifier_update_subframe( - depsgraph, scene, effecobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid); + depsgraph, scene, effecobj, true, 5, BKE_scene_ctime_get(scene), eModifierType_Fluid); if (subframes) { obstacles_from_mesh(effecobj, fds, fes, &bb_temp, subframe_dt); @@ -1616,7 +1616,7 @@ static void emit_from_particles(Object *flow_ob, } /* `DEG_get_ctime(depsgraph)` does not give sub-frame time. */ - state.time = BKE_scene_frame_get(scene); + state.time = BKE_scene_ctime_get(scene); if (psys_get_particle_state(&sim, p, &state, 0) == 0) { continue; @@ -2820,10 +2820,10 @@ static void compute_flowsemission(Scene *scene, # endif /* Update frame time, this is considering current subframe fraction * BLI_mutex_lock() called in manta_step(), so safe to update subframe here - * TODO(sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph) + * TODO(sebbas): Using BKE_scene_ctime_get(scene) instead of new DEG_get_ctime(depsgraph) * as subframes don't work with the latter yet. */ BKE_object_modifier_update_subframe( - depsgraph, scene, flowobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid); + depsgraph, scene, flowobj, true, 5, BKE_scene_ctime_get(scene), eModifierType_Fluid); /* Emission from particles. */ if (ffs->source == FLUID_FLOW_SOURCE_PARTICLES) { diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index b9f0b97ab46..641c003d456 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -604,7 +604,7 @@ int BKE_fcm_envelope_find_index(FCM_EnvelopeData array[], * NOTE: this needs to be at the start of the stack to be of use, * as it needs to know the extents of the keyframes/sample-data. * - * Possible TODO - store length of cycle information that can be initialized from the extents of + * Possible TODO: store length of cycle information that can be initialized from the extents of * the keyframes/sample-data, and adjusted as appropriate. */ @@ -688,7 +688,7 @@ static float fcm_cycles_time( ofs = lastkey[0]; } } - if ((ELEM(0, side, mode))) { + if (ELEM(0, side, mode)) { return evaltime; } diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 8bb2c401b03..d0b9aeefa55 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -984,7 +984,7 @@ static bool vfont_to_curve(Object *ob, } if (dobreak) { if (tb_scale.h == 0.0f) { - /* Note: If underlined text is truncated away, the extra space is also truncated. */ + /* NOTE: If underlined text is truncated away, the extra space is also truncated. */ custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW; } goto makebreak; @@ -1032,7 +1032,7 @@ static bool vfont_to_curve(Object *ob, current_line_length = 0.0f; } - /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */ + /* XXX(campbell): has been unused for years, need to check if this is useful, r4613 r5282. */ #if 0 if (ascii == '\n') { xof = xof_scale; diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 28e46aab732..ef93a3f9b3f 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -53,7 +53,6 @@ GeometryComponent *MeshComponent::copy() const if (mesh_ != nullptr) { new_component->mesh_ = BKE_mesh_copy_for_eval(mesh_, false); new_component->ownership_ = GeometryOwnershipType::Owned; - new_component->vertex_group_names_ = blender::Map(vertex_group_names_); } return new_component; } @@ -67,7 +66,6 @@ void MeshComponent::clear() } mesh_ = nullptr; } - vertex_group_names_.clear(); } bool MeshComponent::has_mesh() const @@ -84,23 +82,6 @@ void MeshComponent::replace(Mesh *mesh, GeometryOwnershipType ownership) ownership_ = ownership; } -/* This function exists for the same reason as #vertex_group_names_. Non-nodes modifiers need to - * be able to replace the mesh data without losing the vertex group names, which may have come - * from another object. */ -void MeshComponent::replace_mesh_but_keep_vertex_group_names(Mesh *mesh, - GeometryOwnershipType ownership) -{ - BLI_assert(this->is_mutable()); - if (mesh_ != nullptr) { - if (ownership_ == GeometryOwnershipType::Owned) { - BKE_id_free(nullptr, mesh_); - } - mesh_ = nullptr; - } - mesh_ = mesh; - ownership_ = ownership; -} - /* Return the mesh and clear the component. The caller takes over responsibility for freeing the * mesh (if the component was responsible before). */ Mesh *MeshComponent::release() @@ -111,28 +92,6 @@ Mesh *MeshComponent::release() return mesh; } -void MeshComponent::copy_vertex_group_names_from_object(const Object &object) -{ - BLI_assert(this->is_mutable()); - vertex_group_names_.clear(); - int index = 0; - LISTBASE_FOREACH (const bDeformGroup *, group, &object.defbase) { - vertex_group_names_.add(group->name, index); - index++; - } -} - -const blender::Map<std::string, int> &MeshComponent::vertex_group_names() const -{ - return vertex_group_names_; -} - -/* This is only exposed for the internal attribute API. */ -blender::Map<std::string, int> &MeshComponent::vertex_group_names() -{ - return vertex_group_names_; -} - /* Get the mesh from this component. This method can be used by multiple threads at the same * time. Therefore, the returned mesh should not be modified. No ownership is transferred. */ const Mesh *MeshComponent::get_for_read() const @@ -864,12 +823,15 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH); const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); const Mesh *mesh = mesh_component.get_for_read(); - const int vertex_group_index = mesh_component.vertex_group_names().lookup_default_as( - attribute_name, -1); + if (mesh == nullptr) { + return {}; + } + const int vertex_group_index = BLI_findstringindex( + &mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name)); if (vertex_group_index < 0) { return {}; } - if (mesh == nullptr || mesh->dvert == nullptr) { + if (mesh->dvert == nullptr) { static const float default_value = 0.0f; return {std::make_unique<fn::GVArray_For_SingleValueRef>( CPPType::get<float>(), mesh->totvert, &default_value), @@ -889,8 +851,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { if (mesh == nullptr) { return {}; } - const int vertex_group_index = mesh_component.vertex_group_names().lookup_default_as( - attribute_name, -1); + + const int vertex_group_index = BLI_findstringindex( + &mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name)); if (vertex_group_index < 0) { return {}; } @@ -913,16 +876,16 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { { BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH); MeshComponent &mesh_component = static_cast<MeshComponent &>(component); - - const int vertex_group_index = mesh_component.vertex_group_names().pop_default_as( - attribute_name, -1); - if (vertex_group_index < 0) { - return false; - } Mesh *mesh = mesh_component.get_for_write(); if (mesh == nullptr) { return true; } + + const int vertex_group_index = BLI_findstringindex( + &mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name)); + if (vertex_group_index < 0) { + return false; + } if (mesh->dvert == nullptr) { return true; } @@ -938,14 +901,14 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { { BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH); const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); - for (const auto item : mesh_component.vertex_group_names().items()) { - const StringRefNull name = item.key; - const int vertex_group_index = item.value; - if (vertex_group_index >= 0) { - AttributeMetaData meta_data{ATTR_DOMAIN_POINT, CD_PROP_FLOAT}; - if (!callback(name, meta_data)) { - return false; - } + const Mesh *mesh = mesh_component.get_for_read(); + if (mesh == nullptr) { + return true; + } + + LISTBASE_FOREACH (const bDeformGroup *, group, &mesh->vertex_group_names) { + if (!callback(group->name, {ATTR_DOMAIN_POINT, CD_PROP_FLOAT})) { + return false; } } return true; diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 01b51d552a9..90a97264c8f 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -48,7 +48,6 @@ static void add_final_mesh_as_geometry_component(const Object &object, GeometryS MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); - mesh_component.copy_vertex_group_names_from_object(object); } } @@ -566,6 +565,7 @@ static PointCloud *join_pointcloud_position_attribute(Span<GeometryInstanceGroup } PointCloud *new_pointcloud = BKE_pointcloud_new_nomain(totpoint); + MutableSpan new_positions{(float3 *)new_pointcloud->co, new_pointcloud->totpoint}; /* Transform each instance's point locations into the new point cloud. */ int offset = 0; @@ -577,9 +577,7 @@ static PointCloud *join_pointcloud_position_attribute(Span<GeometryInstanceGroup } for (const float4x4 &transform : set_group.transforms) { for (const int i : IndexRange(pointcloud->totpoint)) { - const float3 old_position = pointcloud->co[i]; - const float3 new_position = transform * old_position; - copy_v3_v3(new_pointcloud->co[offset + i], new_position); + new_positions[offset + i] = transform * float3(pointcloud->co[i]); } offset += pointcloud->totpoint; } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 459fc5e4c68..38397f8f307 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -87,12 +87,14 @@ static void greasepencil_copy_data(Main *UNUSED(bmain), gpd_dst->mat = MEM_dupallocN(gpd_src->mat); } + BKE_defgroup_copy_list(&gpd_dst->vertex_group_names, &gpd_src->vertex_group_names); + /* copy layers */ BLI_listbase_clear(&gpd_dst->layers); LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) { /* make a copy of source layer and its data */ - /* TODO here too could add unused flags... */ + /* TODO: here too could add unused flags... */ bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src, true, true); /* Apply local layer transform to all frames. Calc the active frame is not enough @@ -165,6 +167,8 @@ static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id BKE_animdata_blend_write(writer, gpd->adt); } + BKE_defbase_blend_write(writer, &gpd->vertex_group_names); + BLO_write_pointer_array(writer, gpd->totcol, gpd->mat); /* write grease-pencil layers to file */ @@ -227,6 +231,8 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd) } } + BLO_read_list(reader, &gpd->vertex_group_names); + /* Materials. */ BLO_read_pointer_array(reader, (void **)&gpd->mat); @@ -498,6 +504,8 @@ void BKE_gpencil_free(bGPdata *gpd, bool free_all) /* materials */ MEM_SAFE_FREE(gpd->mat); + BLI_freelistN(&gpd->vertex_group_names); + /* free all data */ if (free_all) { /* clear cache */ @@ -798,32 +806,6 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[]) /* Utilities for easier bulk-creation of geometry */ /** - * Populate stroke with point data from data buffers. - * \param gps: Grease pencil stroke - * \param array: Flat array of point data values. Each entry has #GP_PRIM_DATABUF_SIZE values. - * \param totpoints: Total of points - * \param mat: 4x4 transform matrix to transform points into the right coordinate space. - */ -void BKE_gpencil_stroke_add_points(bGPDstroke *gps, - const float *array, - const int totpoints, - const float mat[4][4]) -{ - for (int i = 0; i < totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - const int x = GP_PRIM_DATABUF_SIZE * i; - - pt->x = array[x]; - pt->y = array[x + 1]; - pt->z = array[x + 2]; - mul_m4_v3(mat, &pt->x); - - pt->pressure = array[x + 3]; - pt->strength = array[x + 4]; - } -} - -/** * Create a new stroke, with pre-allocated data buffers. * \param mat_idx: Index of the material * \param totpoints: Total points @@ -2087,8 +2069,9 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup) { bGPdata *gpd = ob->data; MDeformVert *dvert = NULL; - const int def_nr = BLI_findindex(&ob->defbase, defgroup); - const int totgrp = BLI_listbase_count(&ob->defbase); + + const int def_nr = BLI_findindex(&gpd->vertex_group_names, defgroup); + const int totgrp = BLI_listbase_count(&gpd->vertex_group_names); /* Remove points data */ if (gpd) { @@ -2117,7 +2100,7 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup) } /* Remove the group */ - BLI_freelinkN(&ob->defbase, defgroup); + BLI_freelinkN(&gpd->vertex_group_names, defgroup); DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); } @@ -2694,22 +2677,60 @@ static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer } /* -------------------------------------------------------------------- */ -/** \name Iterators +/** \name Iterator * - * Iterate over all visible stroke of all visible layers inside a gpObject. - * Also take into account onion-skinning. + * Iterate over all visible stroke of all visible layers inside a grease pencil datablock. * \{ */ -void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, - Object *ob, +void BKE_gpencil_visible_stroke_iter(bGPdata *gpd, gpIterCb layer_cb, gpIterCb stroke_cb, - void *thunk, - bool do_onion, - int cfra) + void *thunk) +{ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + /* If scale to 0 the layer must be invisible. */ + if (is_zero_v3(gpl->scale)) { + continue; + } + + bGPDframe *act_gpf = gpl->actframe; + if (layer_cb) { + layer_cb(gpl, act_gpf, NULL, thunk); + } + + if (act_gpf) { + LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) { + if (gps->totpoints == 0) { + continue; + } + stroke_cb(gpl, act_gpf, gps, thunk); + } + } + } +} + +/* -------------------------------------------------------------------- */ +/** \name Advanced Iterator + * + * Iterate over all visible stroke of all visible layers inside a gpObject. + * Also take into account onion-skinning. + * \{ */ + +void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer, + Object *ob, + gpIterCb layer_cb, + gpIterCb stroke_cb, + void *thunk, + bool do_onion, + int cfra) { bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd))); + const bool is_multiedit = (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) && (!GPENCIL_PLAY_ON(gpd))); const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0); const bool is_drawing = (gpd->runtime.sbuffer_used > 0); diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.cc index 53939da08e2..785f63a7ba2 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -21,22 +21,24 @@ * \ingroup bke */ -#include <math.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> +#include <cmath> +#include <cstddef> +#include <cstdio> +#include <cstdlib> +#include <cstring> #include "CLG_log.h" #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_float3.hh" #include "BLI_ghash.h" #include "BLI_hash.h" #include "BLI_heap.h" #include "BLI_math_vector.h" #include "BLI_polyfill_2d.h" +#include "BLI_span.hh" #include "BLT_translation.h" @@ -61,6 +63,9 @@ #include "DEG_depsgraph_query.h" +using blender::float3; +using blender::Span; + /* GP Object - Boundbox Support */ /** *Get min/max coordinate bounds for single stroke. @@ -75,20 +80,26 @@ bool BKE_gpencil_stroke_minmax(const bGPDstroke *gps, float r_min[3], float r_max[3]) { - const bGPDspoint *pt; - int i; - bool changed = false; - - if (ELEM(NULL, gps, r_min, r_max)) { + if (gps == nullptr) { return false; } - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) { - minmax_v3v3_v3(r_min, r_max, &pt->x); + bool changed = false; + if (use_select) { + for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) { + if (pt.flag & GP_SPOINT_SELECT) { + minmax_v3v3_v3(r_min, r_max, &pt.x); + changed = true; + } + } + } + else { + for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) { + minmax_v3v3_v3(r_min, r_max, &pt.x); changed = true; } } + return changed; } @@ -105,14 +116,14 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3]) INIT_MINMAX(r_min, r_max); - if (gpd == NULL) { + if (gpd == nullptr) { return changed; } LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bGPDframe *gpf = gpl->actframe; - if (gpf != NULL) { + if (gpf != nullptr) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { changed |= BKE_gpencil_stroke_minmax(gps, false, r_min, r_max); } @@ -129,11 +140,11 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3]) */ void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3]) { - float min[3], max[3], tot[3]; - + float3 min; + float3 max; BKE_gpencil_data_minmax(gpd, min, max); - add_v3_v3v3(tot, min, max); + const float3 tot = min + max; mul_v3_v3fl(r_centroid, tot, 0.5f); } @@ -153,20 +164,18 @@ void BKE_gpencil_stroke_boundingbox_calc(bGPDstroke *gps) */ static void boundbox_gpencil(Object *ob) { - BoundBox *bb; - bGPdata *gpd; - float min[3], max[3]; - - if (ob->runtime.bb == NULL) { - ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); + if (ob->runtime.bb == nullptr) { + ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); } - bb = ob->runtime.bb; - gpd = ob->data; + BoundBox *bb = ob->runtime.bb; + bGPdata *gpd = (bGPdata *)ob->data; + float3 min; + float3 max; if (!BKE_gpencil_data_minmax(gpd, min, max)) { - min[0] = min[1] = min[2] = -1.0f; - max[0] = max[1] = max[2] = 1.0f; + min = float3(-1); + max = float3(1); } BKE_boundbox_init_from_minmax(bb, min, max); @@ -181,8 +190,8 @@ static void boundbox_gpencil(Object *ob) */ BoundBox *BKE_gpencil_boundbox_get(Object *ob) { - if (ELEM(NULL, ob, ob->data)) { - return NULL; + if (ELEM(nullptr, ob, ob->data)) { + return nullptr; } bGPdata *gpd = (bGPdata *)ob->data; @@ -196,9 +205,9 @@ BoundBox *BKE_gpencil_boundbox_get(Object *ob) /* Update orig object's boundbox with re-computed evaluated values. This function can be * called with the evaluated object and need update the original object bound box data * to keep both values synchronized. */ - if (!ELEM(ob_orig, NULL, ob)) { - if (ob_orig->runtime.bb == NULL) { - ob_orig->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); + if (!ELEM(ob_orig, nullptr, ob)) { + if (ob_orig->runtime.bb == nullptr) { + ob_orig->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); } for (int i = 0; i < 8; i++) { copy_v3_v3(ob_orig->runtime.bb->vec[i], ob->runtime.bb->vec[i]); @@ -227,7 +236,7 @@ static int stroke_march_next_point(const bGPDstroke *gps, float step_start[3]; float point[3]; int next_point_index = index_next_pt; - bGPDspoint *pt = NULL; + bGPDspoint *pt = nullptr; if (!(next_point_index < gps->totpoints)) { return -1; @@ -295,7 +304,7 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps, float step_start[3]; float point[3]; int next_point_index = index_next_pt; - bGPDspoint *pt = NULL; + bGPDspoint *pt = nullptr; if (!(next_point_index < gps->totpoints)) { return -1; @@ -336,7 +345,7 @@ static int stroke_march_count(const bGPDstroke *gps, const float dist) int point_count = 0; float point[3]; int next_point_index = 1; - bGPDspoint *pt = NULL; + bGPDspoint *pt = nullptr; pt = &gps->points[0]; copy_v3_v3(point, &pt->x); @@ -369,14 +378,14 @@ static void stroke_defvert_create_nr_list(MDeformVert *dv_list, for (j = 0; j < dv->totweight; j++) { bool found = false; dw = &dv->dw[j]; - for (ld = result->first; ld; ld = ld->next) { + for (ld = (LinkData *)result->first; ld; ld = ld->next) { if (ld->data == POINTER_FROM_INT(dw->def_nr)) { found = true; break; } } if (!found) { - ld = MEM_callocN(sizeof(LinkData), "def_nr_item"); + ld = (LinkData *)MEM_callocN(sizeof(LinkData), "def_nr_item"); ld->data = POINTER_FROM_INT(dw->def_nr); BLI_addtail(result, ld); tw++; @@ -391,14 +400,15 @@ static MDeformVert *stroke_defvert_new_count(int count, int totweight, ListBase { int i, j; LinkData *ld; - MDeformVert *dst = MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert"); + MDeformVert *dst = (MDeformVert *)MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert"); for (i = 0; i < count; i++) { - dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * totweight, "new_deformWeight"); + dst[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * totweight, + "new_deformWeight"); dst[i].totweight = totweight; j = 0; /* re-assign deform groups */ - for (ld = def_nr_list->first; ld; ld = ld->next) { + for (ld = (LinkData *)def_nr_list->first; ld; ld = ld->next) { dst[i].dw[j].def_nr = POINTER_AS_INT(ld->data); j++; } @@ -429,10 +439,10 @@ static void stroke_interpolate_deform_weights( bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, const bool select) { bGPDspoint *pt = gps->points; - bGPDspoint *pt1 = NULL; - bGPDspoint *pt2 = NULL; + bGPDspoint *pt1 = nullptr; + bGPDspoint *pt2 = nullptr; LinkData *ld; - ListBase def_nr_list = {0}; + ListBase def_nr_list = {nullptr}; if (gps->totpoints < 2 || dist < FLT_EPSILON) { return false; @@ -440,12 +450,13 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, /* TODO: Implement feature point preservation. */ int count = stroke_march_count(gps, dist); - bGPDspoint *new_pt = MEM_callocN(sizeof(bGPDspoint) * count, "gp_stroke_points_sampled"); - MDeformVert *new_dv = NULL; + bGPDspoint *new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * count, + "gp_stroke_points_sampled"); + MDeformVert *new_dv = nullptr; int result_totweight; - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { stroke_defvert_create_nr_list(gps->dvert, gps->totpoints, &def_nr_list, &result_totweight); new_dv = stroke_defvert_new_count(count, result_totweight, &def_nr_list); } @@ -513,7 +524,7 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, /* Free original weight data. */ BKE_gpencil_free_stroke_weights(gps); MEM_freeN(gps->dvert); - while ((ld = BLI_pophead(&def_nr_list))) { + while ((ld = (LinkData *)BLI_pophead(&def_nr_list))) { MEM_freeN(ld); } @@ -610,30 +621,32 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const if (new_count == 1) { BKE_gpencil_free_stroke_weights(gps); MEM_freeN(gps->points); - gps->points = NULL; - gps->dvert = NULL; + gps->points = nullptr; + gps->dvert = nullptr; gps->totpoints = 0; return false; } - new_pt = MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed"); + new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed"); for (int i = 0; i < new_count; i++) { memcpy(&new_pt[i], &pt[i + index_from], sizeof(bGPDspoint)); } if (gps->dvert) { - new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, "gp_stroke_dverts_trimmed"); + new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count, + "gp_stroke_dverts_trimmed"); for (int i = 0; i < new_count; i++) { dv = &gps->dvert[i + index_from]; new_dv[i].flag = dv->flag; new_dv[i].totweight = dv->totweight; - new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight, - "gp_stroke_dverts_dw_trimmed"); + new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight, + "gp_stroke_dverts_dw_trimmed"); for (int j = 0; j < dv->totweight; j++) { new_dv[i].dw[j].weight = dv->dw[j].weight; new_dv[i].dw[j].def_nr = dv->dw[j].def_nr; } + BKE_defvert_clear(dv); } MEM_freeN(gps->dvert); gps->dvert = new_dv; @@ -684,18 +697,19 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd, } if (gps->dvert) { - new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, - "gp_stroke_dverts_remaining(MDeformVert)"); + new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count, + "gp_stroke_dverts_remaining(MDeformVert)"); for (int i = 0; i < new_count; i++) { dv = &gps->dvert[i + before_index]; new_dv[i].flag = dv->flag; new_dv[i].totweight = dv->totweight; - new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight, - "gp_stroke_dverts_dw_remaining(MDeformWeight)"); + new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight, + "gp_stroke_dverts_dw_remaining(MDeformWeight)"); for (int j = 0; j < dv->totweight; j++) { new_dv[i].dw[j].weight = dv->dw[j].weight; new_dv[i].dw[j].def_nr = dv->dw[j].def_nr; } + BKE_defvert_clear(dv); } new_gps->dvert = new_dv; } @@ -1299,11 +1313,12 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) /* allocate memory for temporary areas */ gps->tot_triangles = gps->totpoints - 2; - uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, - "GP Stroke temp triangulation"); - float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, - "GP Stroke temp 2d points"); - float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data"); + uint(*tmp_triangles)[3] = (uint(*)[3])MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, + "GP Stroke temp triangulation"); + float(*points2d)[2] = (float(*)[2])MEM_mallocN(sizeof(*points2d) * gps->totpoints, + "GP Stroke temp 2d points"); + float(*uv)[2] = (float(*)[2])MEM_mallocN(sizeof(*uv) * gps->totpoints, + "GP Stroke temp 2d uv data"); int direction = 0; @@ -1324,8 +1339,8 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) /* Save triangulation data. */ if (gps->tot_triangles > 0) { MEM_SAFE_FREE(gps->triangles); - gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, - "GP Stroke triangulation"); + gps->triangles = (bGPDtriangle *)MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, + "GP Stroke triangulation"); for (int i = 0; i < gps->tot_triangles; i++) { memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3])); @@ -1342,7 +1357,7 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) MEM_freeN(gps->triangles); } - gps->triangles = NULL; + gps->triangles = nullptr; } /* clear memory */ @@ -1357,7 +1372,7 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps) */ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps) { - if (gps == NULL || gps->totpoints == 0) { + if (gps == nullptr || gps->totpoints == 0) { return; } @@ -1377,11 +1392,11 @@ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps) */ void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps) { - if (gps == NULL) { + if (gps == nullptr) { return; } - if (gps->editcurve != NULL) { + if (gps->editcurve != nullptr) { if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) { /* curve geometry was updated: stroke needs recalculation */ if (gps->flag & GP_STROKE_NEEDS_CURVE_UPDATE) { @@ -1517,20 +1532,20 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps) if (intersect) { /* save points */ - bGPDspoint *old_points = MEM_dupallocN(gps->points); - MDeformVert *old_dvert = NULL; - MDeformVert *dvert_src = NULL; + bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); + MDeformVert *old_dvert = nullptr; + MDeformVert *dvert_src = nullptr; - if (gps->dvert != NULL) { - old_dvert = MEM_dupallocN(gps->dvert); + if (gps->dvert != nullptr) { + old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); } /* resize gps */ int newtot = end - start + 1; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); } for (int i = 0; i < newtot; i++) { @@ -1538,7 +1553,7 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps) bGPDspoint *pt_src = &old_points[idx]; bGPDspoint *pt_new = &gps->points[i]; memcpy(pt_new, pt_src, sizeof(bGPDspoint)); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[idx]; MDeformVert *dvert = &gps->dvert[i]; memcpy(dvert, dvert_src, sizeof(MDeformVert)); @@ -1568,8 +1583,8 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps) */ bool BKE_gpencil_stroke_close(bGPDstroke *gps) { - bGPDspoint *pt1 = NULL; - bGPDspoint *pt2 = NULL; + bGPDspoint *pt1 = nullptr; + bGPDspoint *pt2 = nullptr; /* Only can close a stroke with 3 points or more. */ if (gps->totpoints < 3) { @@ -1603,9 +1618,9 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps) /* Resize stroke array. */ int old_tot = gps->totpoints; gps->totpoints += tot_newpoints; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); } /* Generate new points */ @@ -1627,7 +1642,7 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps) interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step); /* Set weights. */ - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { MDeformVert *dvert1 = &gps->dvert[old_tot - 1]; MDeformWeight *dw1 = BKE_defvert_ensure_index(dvert1, 0); float weight_1 = dw1 ? dw1->weight : 0.0f; @@ -1661,7 +1676,7 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps) void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, const short tag) { bGPDspoint *pt; - MDeformVert *dvert = NULL; + MDeformVert *dvert = nullptr; int i; int tot = gps->totpoints; /* number of points in new buffer */ @@ -1691,30 +1706,32 @@ void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, } else { /* just copy all points to keep into a smaller buffer */ - bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy"); + bGPDspoint *new_points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * tot, + "new gp stroke points copy"); bGPDspoint *npt = new_points; - MDeformVert *new_dvert = NULL; - MDeformVert *ndvert = NULL; + MDeformVert *new_dvert = nullptr; + MDeformVert *ndvert = nullptr; - if (gps->dvert != NULL) { - new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy"); + if (gps->dvert != nullptr) { + new_dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * tot, + "new gp stroke weights copy"); ndvert = new_dvert; } - (gps->dvert != NULL) ? dvert = gps->dvert : NULL; + (gps->dvert != nullptr) ? dvert = gps->dvert : nullptr; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if ((pt->flag & tag) == 0) { *npt = *pt; npt++; - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { *ndvert = *dvert; - ndvert->dw = MEM_dupallocN(dvert->dw); + ndvert->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); ndvert++; } } - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert++; } } @@ -1787,15 +1804,15 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3]) */ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float epsilon) { - bGPDspoint *old_points = MEM_dupallocN(gps->points); + bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); int totpoints = gps->totpoints; - char *marked = NULL; + char *marked = nullptr; char work; int start = 0; int end = gps->totpoints - 1; - marked = MEM_callocN(totpoints, "GP marked array"); + marked = (char *)MEM_callocN(totpoints, "GP marked array"); marked[start] = 1; marked[end] = 1; @@ -1847,11 +1864,11 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e } /* adding points marked */ - MDeformVert *old_dvert = NULL; - MDeformVert *dvert_src = NULL; + MDeformVert *old_dvert = nullptr; + MDeformVert *dvert_src = nullptr; - if (gps->dvert != NULL) { - old_dvert = MEM_dupallocN(gps->dvert); + if (gps->dvert != nullptr) { + old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); } /* resize gps */ int j = 0; @@ -1861,7 +1878,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e if ((marked[i]) || (i == 0) || (i == totpoints - 1)) { memcpy(pt, pt_src, sizeof(bGPDspoint)); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; MDeformVert *dvert = &gps->dvert[j]; memcpy(dvert, dvert_src, sizeof(MDeformVert)); @@ -1872,7 +1889,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e j++; } else { - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; BKE_gpencil_free_point_weights(dvert_src); } @@ -1901,12 +1918,12 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) } /* save points */ - bGPDspoint *old_points = MEM_dupallocN(gps->points); - MDeformVert *old_dvert = NULL; - MDeformVert *dvert_src = NULL; + bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); + MDeformVert *old_dvert = nullptr; + MDeformVert *dvert_src = nullptr; - if (gps->dvert != NULL) { - old_dvert = MEM_dupallocN(gps->dvert); + if (gps->dvert != nullptr) { + old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); } /* resize gps */ @@ -1916,9 +1933,9 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) } newtot += 2; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); } int j = 0; @@ -1928,7 +1945,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) { memcpy(pt, pt_src, sizeof(bGPDspoint)); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; MDeformVert *dvert = &gps->dvert[j]; memcpy(dvert, dvert_src, sizeof(MDeformVert)); @@ -1939,7 +1956,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) j++; } else { - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; BKE_gpencil_free_point_weights(dvert_src); } @@ -1964,25 +1981,25 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int type) { bGPDspoint *temp_points; - MDeformVert *temp_dverts = NULL; - MDeformVert *dvert = NULL; - MDeformVert *dvert_final = NULL; - MDeformVert *dvert_next = NULL; + MDeformVert *temp_dverts = nullptr; + MDeformVert *dvert = nullptr; + MDeformVert *dvert_final = nullptr; + MDeformVert *dvert_next = nullptr; int totnewpoints, oldtotpoints; int i2; for (int s = 0; s < level; s++) { totnewpoints = gps->totpoints - 1; /* duplicate points in a temp area */ - temp_points = MEM_dupallocN(gps->points); + temp_points = (bGPDspoint *)MEM_dupallocN(gps->points); oldtotpoints = gps->totpoints; /* resize the points arrays */ gps->totpoints += totnewpoints; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); - if (gps->dvert != NULL) { - temp_dverts = MEM_dupallocN(gps->dvert); - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); + if (gps->dvert != nullptr) { + temp_dverts = (MDeformVert *)MEM_dupallocN(gps->dvert); + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); } /* move points from last to first to new place */ @@ -2000,7 +2017,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int pt_final->runtime.idx_orig = pt->runtime.idx_orig; copy_v4_v4(pt_final->vert_color, pt->vert_color); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert = &temp_dverts[i]; dvert_final = &gps->dvert[i2]; dvert_final->totweight = dvert->totweight; @@ -2021,17 +2038,17 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int pt_final->strength = interpf(pt->strength, next->strength, 0.5f); CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt_final->time = interpf(pt->time, next->time, 0.5f); - pt_final->runtime.pt_orig = NULL; + pt_final->runtime.pt_orig = nullptr; pt_final->flag = 0; interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { dvert = &temp_dverts[i]; dvert_next = &temp_dverts[i + 1]; dvert_final = &gps->dvert[i2]; dvert_final->totweight = dvert->totweight; - dvert_final->dw = MEM_dupallocN(dvert->dw); + dvert_final->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); /* interpolate weight values */ for (int d = 0; d < dvert->totweight; d++) { @@ -2053,7 +2070,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int /* Move points to smooth stroke (not simple type). */ if (type != GP_SUBDIV_SIMPLE) { /* duplicate points in a temp area with the new subdivide data */ - temp_points = MEM_dupallocN(gps->points); + temp_points = (bGPDspoint *)MEM_dupallocN(gps->points); /* extreme points are not changed */ for (int i = 0; i < gps->totpoints - 2; i++) { @@ -2091,8 +2108,8 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd, const float threshold, const bool use_unselected) { - bGPDspoint *pt = NULL; - bGPDspoint *pt_next = NULL; + bGPDspoint *pt = nullptr; + bGPDspoint *pt_next = nullptr; float tagged = false; /* Use square distance to speed up loop */ const float th_square = threshold * threshold; @@ -2158,7 +2175,7 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd, BKE_gpencil_stroke_geometry_update(gpd, gps); } -typedef struct GpEdge { +struct GpEdge { uint v1, v2; /* Coordinates. */ float v1_co[3], v2_co[3]; @@ -2167,7 +2184,7 @@ typedef struct GpEdge { /* Direction of the segment. */ float vec[3]; int flag; -} GpEdge; +}; static int gpencil_next_edge( GpEdge *gp_edges, int totedges, GpEdge *gped_init, const float threshold, const bool reverse) @@ -2260,13 +2277,13 @@ static void gpencil_generate_edgeloops(Object *ob, /* Arrays for all edge vertices (forward and backward) that form a edge loop. * This is reused for each edgeloop to create gpencil stroke. */ - uint *stroke = MEM_callocN(sizeof(uint) * me->totedge * 2, __func__); - uint *stroke_fw = MEM_callocN(sizeof(uint) * me->totedge, __func__); - uint *stroke_bw = MEM_callocN(sizeof(uint) * me->totedge, __func__); + uint *stroke = (uint *)MEM_callocN(sizeof(uint) * me->totedge * 2, __func__); + uint *stroke_fw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__); + uint *stroke_bw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__); /* Create array with all edges. */ - GpEdge *gp_edges = MEM_callocN(sizeof(GpEdge) * me->totedge, __func__); - GpEdge *gped = NULL; + GpEdge *gp_edges = (GpEdge *)MEM_callocN(sizeof(GpEdge) * me->totedge, __func__); + GpEdge *gped = nullptr; for (int i = 0; i < me->totedge; i++) { MEdge *ed = &me->medge[i]; gped = &gp_edges[i]; @@ -2319,7 +2336,7 @@ static void gpencil_generate_edgeloops(Object *ob, /* Look backward edges. */ int totbw = gpencil_walk_edge(v_table, gp_edges, me->totedge, stroke_bw, e, angle, true); - BLI_ghash_free(v_table, NULL, NULL); + BLI_ghash_free(v_table, nullptr, nullptr); /* Join both arrays. */ int array_len = 0; @@ -2421,7 +2438,7 @@ static int gpencil_material_find_index_by_name(Object *ob, const char *name) { for (int i = 0; i < ob->totcol; i++) { Material *ma = BKE_object_material_get(ob, i + 1); - if ((ma != NULL) && (ma->gp_style != NULL) && (STREQ(ma->id.name + 2, name))) { + if ((ma != nullptr) && (ma->gp_style != nullptr) && (STREQ(ma->id.name + 2, name))) { return i; } } @@ -2472,7 +2489,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, const bool use_seams, const bool use_faces) { - if (ELEM(NULL, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { + if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) { return false; } @@ -2480,9 +2497,9 @@ bool BKE_gpencil_convert_mesh(Main *bmain, /* Use evaluated data to get mesh with all modifiers on top. */ Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, ob_mesh); - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); - MPoly *mp, *mpoly = me_eval->mpoly; - MLoop *mloop = me_eval->mloop; + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + const MPoly *mpoly = me_eval->mpoly; + const MLoop *mloop = me_eval->mloop; int mpoly_len = me_eval->totpoly; char element_name[200]; @@ -2509,23 +2526,24 @@ bool BKE_gpencil_convert_mesh(Main *bmain, make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name); /* Create Layer and Frame. */ bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name); - if (gpl_fill == NULL) { + if (gpl_fill == nullptr) { gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false); } bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get( gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW); int i; - for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) { - MLoop *ml = &mloop[mp->loopstart]; + for (i = 0; i < mpoly_len; i++) { + const MPoly *mp = &mpoly[i]; + /* Find material. */ int mat_idx = 0; Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1); make_element_name( - ob_mesh->id.name + 2, (ma != NULL) ? ma->id.name + 2 : "Fill", 64, element_name); + ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name); mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name); if (mat_idx == -1) { float color[4]; - if (ma != NULL) { + if (ma != nullptr) { copy_v3_v3(color, &ma->r); color[3] = 1.0f; } @@ -2539,8 +2557,10 @@ bool BKE_gpencil_convert_mesh(Main *bmain, gps_fill->flag |= GP_STROKE_CYCLIC; /* Add points to strokes. */ - for (int j = 0; j < mp->totloop; j++, ml++) { - MVert *mv = &me_eval->mvert[ml->v]; + for (int j = 0; j < mp->totloop; j++) { + const MLoop *ml = &mloop[mp->loopstart + j]; + const MVert *mv = &me_eval->mvert[ml->v]; + bGPDspoint *pt = &gps_fill->points[j]; copy_v3_v3(&pt->x, mv->co); mul_m4_v3(matrix, &pt->x); @@ -2562,7 +2582,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, /* Create Layer and Frame. */ bGPDlayer *gpl_stroke = BKE_gpencil_layer_named_get(gpd, element_name); - if (gpl_stroke == NULL) { + if (gpl_stroke == nullptr) { gpl_stroke = BKE_gpencil_layer_addnew(gpd, element_name, true, false); } bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get( @@ -2584,7 +2604,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, */ void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4]) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2620,7 +2640,7 @@ int BKE_gpencil_stroke_point_count(const bGPdata *gpd) { int total_points = 0; - if (gpd == NULL) { + if (gpd == nullptr) { return 0; } @@ -2645,7 +2665,7 @@ int BKE_gpencil_stroke_point_count(const bGPdata *gpd) /* Used for "move only origins" in object_data_transform.c */ void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_data) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2676,7 +2696,7 @@ void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_da /* Used for "move only origins" in object_data_transform.c */ void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates *elem_data) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2712,7 +2732,7 @@ void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd, const GPencilPointCoordinates *elem_data, const float mat[4][4]) { - if (gpd == NULL) { + if (gpd == nullptr) { return; } @@ -2813,24 +2833,24 @@ void BKE_gpencil_stroke_flip(bGPDstroke *gps) * that should be kept when splitting up a stroke. Used in: * gpencil_stroke_delete_tagged_points() */ -typedef struct tGPDeleteIsland { +struct tGPDeleteIsland { int start_idx; int end_idx; -} tGPDeleteIsland; +}; static void gpencil_stroke_join_islands(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps_first, bGPDstroke *gps_last) { - bGPDspoint *pt = NULL; - bGPDspoint *pt_final = NULL; + bGPDspoint *pt = nullptr; + bGPDspoint *pt_final = nullptr; const int totpoints = gps_first->totpoints + gps_last->totpoints; /* create new stroke */ bGPDstroke *join_stroke = BKE_gpencil_stroke_duplicate(gps_first, false, true); - join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__); + join_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__); join_stroke->totpoints = totpoints; join_stroke->flag &= ~GP_STROKE_CYCLIC; @@ -2863,17 +2883,17 @@ static void gpencil_stroke_join_islands(bGPdata *gpd, } /* Copy over vertex weight data (if available) */ - if ((gps_first->dvert != NULL) || (gps_last->dvert != NULL)) { - join_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * totpoints, __func__); - MDeformVert *dvert_src = NULL; - MDeformVert *dvert_dst = NULL; + if ((gps_first->dvert != nullptr) || (gps_last->dvert != nullptr)) { + join_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * totpoints, __func__); + MDeformVert *dvert_src = nullptr; + MDeformVert *dvert_dst = nullptr; /* Copy weights (last before). */ e1 = 0; e2 = 0; for (int i = 0; i < totpoints; i++) { dvert_dst = &join_stroke->dvert[i]; - dvert_src = NULL; + dvert_src = nullptr; if (i < gps_last->totpoints) { if (gps_last->dvert) { dvert_src = &gps_last->dvert[e1]; @@ -2888,7 +2908,7 @@ static void gpencil_stroke_join_islands(bGPdata *gpd, } if ((dvert_src) && (dvert_src->dw)) { - dvert_dst->dw = MEM_dupallocN(dvert_src->dw); + dvert_dst->dw = (MDeformWeight *)MEM_dupallocN(dvert_src->dw); } } } @@ -2929,13 +2949,13 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, bool select, int limit) { - tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, - "gp_point_islands"); + tGPDeleteIsland *islands = (tGPDeleteIsland *)MEM_callocN( + sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands"); bool in_island = false; int num_islands = 0; - bGPDstroke *new_stroke = NULL; - bGPDstroke *gps_first = NULL; + bGPDstroke *new_stroke = nullptr; + bGPDstroke *gps_first = nullptr; const bool is_cyclic = (bool)(gps->flag & GP_STROKE_CYCLIC); /* First Pass: Identify start/end of islands */ @@ -2977,7 +2997,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, new_stroke = BKE_gpencil_stroke_duplicate(gps, false, true); /* if cyclic and first stroke, save to join later */ - if ((is_cyclic) && (gps_first == NULL)) { + if ((is_cyclic) && (gps_first == nullptr)) { gps_first = new_stroke; } @@ -2987,17 +3007,17 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, new_stroke->totpoints = island->end_idx - island->start_idx + 1; /* Copy over the relevant point data */ - new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, - "gp delete stroke fragment"); + new_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, + "gp delete stroke fragment"); memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints); /* Copy over vertex weight data (if available) */ - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { /* Copy over the relevant vertex-weight points */ - new_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints, - "gp delete stroke fragment weight"); + new_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints, + "gp delete stroke fragment weight"); memcpy(new_stroke->dvert, gps->dvert + island->start_idx, sizeof(MDeformVert) * new_stroke->totpoints); @@ -3008,7 +3028,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, MDeformVert *dvert_src = &gps->dvert[e]; MDeformVert *dvert_dst = &new_stroke->dvert[i]; if (dvert_src->dw) { - dvert_dst->dw = MEM_dupallocN(dvert_src->dw); + dvert_dst->dw = (MDeformWeight *)MEM_dupallocN(dvert_src->dw); } e++; } @@ -3042,7 +3062,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, /* Add new stroke to the frame or delete if below limit */ if ((limit > 0) && (new_stroke->totpoints <= limit)) { if (gps_first == new_stroke) { - gps_first = NULL; + gps_first = nullptr; } BKE_gpencil_free_stroke(new_stroke); } @@ -3059,7 +3079,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, } } /* if cyclic, need to join last stroke with first stroke */ - if ((is_cyclic) && (gps_first != NULL) && (gps_first != new_stroke)) { + if ((is_cyclic) && (gps_first != nullptr) && (gps_first != new_stroke)) { gpencil_stroke_join_islands(gpd, gpf, gps_first, new_stroke); } } @@ -3081,13 +3101,13 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd, bGPDcurve *gpc, int tag_flags) { - if (gpc == NULL) { + if (gpc == nullptr) { return; } const bool is_cyclic = gps->flag & GP_STROKE_CYCLIC; const int idx_last = gpc->tot_curve_points - 1; - bGPDstroke *gps_first = NULL; - bGPDstroke *gps_last = NULL; + bGPDstroke *gps_first = nullptr; + bGPDstroke *gps_last = nullptr; int idx_start = 0; int idx_end = 0; @@ -3118,11 +3138,11 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd, } bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, false, false); - new_stroke->points = NULL; + new_stroke->points = nullptr; new_stroke->flag &= ~GP_STROKE_CYCLIC; new_stroke->editcurve = BKE_gpencil_stroke_editcurve_new(island_length); - if (gps_first == NULL) { + if (gps_first == nullptr) { gps_first = new_stroke; } @@ -3150,15 +3170,15 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd, } /* join first and last stroke if cyclic */ - if (is_cyclic && gps_first != NULL && gps_last != NULL && gps_first != gps_last) { + if (is_cyclic && gps_first != nullptr && gps_last != nullptr && gps_first != gps_last) { bGPDcurve *gpc_first = gps_first->editcurve; bGPDcurve *gpc_last = gps_last->editcurve; int first_tot_points = gpc_first->tot_curve_points; int old_tot_points = gpc_last->tot_curve_points; gpc_last->tot_curve_points = first_tot_points + old_tot_points; - gpc_last->curve_points = MEM_recallocN(gpc_last->curve_points, - sizeof(bGPDcurve_point) * gpc_last->tot_curve_points); + gpc_last->curve_points = (bGPDcurve_point *)MEM_recallocN( + gpc_last->curve_points, sizeof(bGPDcurve_point) * gpc_last->tot_curve_points); /* copy data from first to last */ memcpy(gpc_last->curve_points + old_tot_points, gpc_first->curve_points, @@ -3191,14 +3211,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, { bGPDspoint *newpoint; - gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); - if (gps->dvert != NULL) { - gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1)); + gps->points = (bGPDspoint *)MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); + if (gps->dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_reallocN(gps->dvert, + sizeof(MDeformVert) * (gps->totpoints + 1)); } else { /* If destination has weight add weight to origin. */ - if (dvert != NULL) { - gps->dvert = MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1), __func__); + if (dvert != nullptr) { + gps->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1), + __func__); } } @@ -3214,16 +3236,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, newpoint->time = point->time + deltatime; copy_v4_v4(newpoint->vert_color, point->vert_color); - if (gps->dvert != NULL) { + if (gps->dvert != nullptr) { MDeformVert *newdvert = &gps->dvert[gps->totpoints - 1]; - if (dvert != NULL) { + if (dvert != nullptr) { newdvert->totweight = dvert->totweight; - newdvert->dw = MEM_dupallocN(dvert->dw); + newdvert->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); } else { newdvert->totweight = 0; - newdvert->dw = NULL; + newdvert->dw = nullptr; } } } @@ -3241,7 +3263,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, float deltatime = 0.0f; /* sanity checks */ - if (ELEM(NULL, gps_a, gps_b)) { + if (ELEM(nullptr, gps_a, gps_b)) { return; } @@ -3303,11 +3325,11 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, point = gps_a->points[gps_a->totpoints - 1]; deltatime = point.time; - gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, 0.0f); + gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, 0.0f); /* 2nd: add one head point to finish invisible area */ point = gps_b->points[0]; - gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime); + gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, deltatime); } const float ratio = (fit_thickness && gps_a->thickness > 0.0f) ? @@ -3316,7 +3338,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, /* 3rd: add all points */ for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { - MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL; + MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : nullptr; gpencil_stroke_copy_point( gps_a, dvert, pt, delta, pt->pressure * ratio, pt->strength, deltatime); } @@ -3335,16 +3357,16 @@ void BKE_gpencil_stroke_copy_to_keyframes( if (gpf->framenum != cfra) { bGPDframe *gpf_new = BKE_gpencil_layer_frame_find(gpl, cfra); - if (gpf_new == NULL) { + if (gpf_new == nullptr) { gpf_new = BKE_gpencil_frame_addnew(gpl, cfra); } - if (gpf_new == NULL) { + if (gpf_new == nullptr) { continue; } bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, true, true); - if (gps_new == NULL) { + if (gps_new == nullptr) { continue; } @@ -3358,38 +3380,38 @@ void BKE_gpencil_stroke_copy_to_keyframes( } /* Free hash table. */ - BLI_ghash_free(frame_list, NULL, NULL); + BLI_ghash_free(frame_list, nullptr, nullptr); } /* Stroke Uniform Subdivide ------------------------------------- */ -typedef struct tSamplePoint { +struct tSamplePoint { struct tSamplePoint *next, *prev; float x, y, z; float pressure, strength, time; float vertex_color[4]; struct MDeformWeight *dw; int totweight; -} tSamplePoint; +}; -typedef struct tSampleEdge { +struct tSampleEdge { float length_sq; tSamplePoint *from; tSamplePoint *to; -} tSampleEdge; +}; /* Helper: creates a tSamplePoint from a bGPDspoint and (optionally) a MDeformVert. */ static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const MDeformVert *dvert) { - tSamplePoint *new_pt = MEM_callocN(sizeof(tSamplePoint), __func__); + tSamplePoint *new_pt = (tSamplePoint *)MEM_callocN(sizeof(tSamplePoint), __func__); copy_v3_v3(&new_pt->x, &pt->x); new_pt->pressure = pt->pressure; new_pt->strength = pt->strength; new_pt->time = pt->time; copy_v4_v4((float *)&new_pt->vertex_color, (float *)&pt->vert_color); - if (dvert != NULL) { + if (dvert != nullptr) { new_pt->totweight = dvert->totweight; - new_pt->dw = MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__); + new_pt->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__); for (uint i = 0; i < new_pt->totweight; ++i) { MDeformWeight *dw = &new_pt->dw[i]; MDeformWeight *dw_from = &dvert->dw[i]; @@ -3404,7 +3426,7 @@ static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const * the edge. */ static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamplePoint *to) { - tSampleEdge *new_edge = MEM_callocN(sizeof(tSampleEdge), __func__); + tSampleEdge *new_edge = (tSampleEdge *)MEM_callocN(sizeof(tSampleEdge), __func__); new_edge->from = from; new_edge->to = to; new_edge->length_sq = len_squared_v3v3(&from->x, &to->x); @@ -3426,27 +3448,27 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, const bool select) { /* Stroke needs at least two points and strictly less points than the target number. */ - if (gps == NULL || gps->totpoints < 2 || gps->totpoints >= target_number) { + if (gps == nullptr || gps->totpoints < 2 || gps->totpoints >= target_number) { return; } const int totpoints = gps->totpoints; - const bool has_dverts = (gps->dvert != NULL); + const bool has_dverts = (gps->dvert != nullptr); const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC); - ListBase points = {NULL, NULL}; + ListBase points = {nullptr, nullptr}; Heap *edges = BLI_heap_new(); /* Add all points into list. */ for (uint32_t i = 0; i < totpoints; ++i) { bGPDspoint *pt = &gps->points[i]; - MDeformVert *dvert = has_dverts ? &gps->dvert[i] : NULL; + MDeformVert *dvert = has_dverts ? &gps->dvert[i] : nullptr; tSamplePoint *sp = new_sample_point_from_gp_point(pt, dvert); BLI_addtail(&points, sp); } /* Iterate over edges and insert them into the heap. */ - for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != NULL; pt = pt->next) { + for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != nullptr; pt = pt->next) { tSampleEdge *se = new_sample_edge_from_sample_points(pt->prev, pt); /* BLI_heap is a min-heap, but we need the largest key to be at the top, so we take the * negative of the squared length. */ @@ -3454,8 +3476,8 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, } if (is_cyclic) { - tSamplePoint *sp_first = points.first; - tSamplePoint *sp_last = points.last; + tSamplePoint *sp_first = (tSamplePoint *)points.first; + tSamplePoint *sp_last = (tSamplePoint *)points.last; tSampleEdge *se = new_sample_edge_from_sample_points(sp_last, sp_first); BLI_heap_insert(edges, -(se->length_sq), se); } @@ -3464,12 +3486,12 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, BLI_assert(num_points_needed > 0); while (num_points_needed > 0) { - tSampleEdge *se = BLI_heap_pop_min(edges); + tSampleEdge *se = (tSampleEdge *)BLI_heap_pop_min(edges); tSamplePoint *sp = se->from; tSamplePoint *sp_next = se->to; /* Subdivide the edge. */ - tSamplePoint *new_sp = MEM_callocN(sizeof(tSamplePoint), __func__); + tSamplePoint *new_sp = (tSamplePoint *)MEM_callocN(sizeof(tSamplePoint), __func__); interp_v3_v3v3(&new_sp->x, &sp->x, &sp_next->x, 0.5f); new_sp->pressure = interpf(sp->pressure, sp_next->pressure, 0.5f); new_sp->strength = interpf(sp->strength, sp_next->strength, 0.5f); @@ -3480,7 +3502,8 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, 0.5f); if (sp->dw && sp_next->dw) { new_sp->totweight = MIN2(sp->totweight, sp_next->totweight); - new_sp->dw = MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, __func__); + new_sp->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, + __func__); for (uint32_t i = 0; i < new_sp->totweight; ++i) { MDeformWeight *dw = &new_sp->dw[i]; MDeformWeight *dw_from = &sp->dw[i]; @@ -3504,13 +3527,13 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, BLI_heap_free(edges, (HeapFreeFP)MEM_freeN); gps->totpoints = target_number; - gps->points = MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints); + gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints); if (has_dverts) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints); + gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints); } /* Convert list back to stroke point array. */ - tSamplePoint *sp = points.first; + tSamplePoint *sp = (tSamplePoint *)points.first; for (uint32_t i = 0; i < gps->totpoints && sp; ++i, sp = sp->next) { bGPDspoint *pt = &gps->points[i]; MDeformVert *dvert = &gps->dvert[i]; @@ -3523,7 +3546,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, if (sp->dw) { dvert->totweight = sp->totweight; - dvert->dw = MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__); + dvert->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__); for (uint32_t j = 0; j < dvert->totweight; ++j) { MDeformWeight *dw = &dvert->dw[j]; MDeformWeight *dw_from = &sp->dw[j]; @@ -3544,7 +3567,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, /* Free the sample points. Important to use the mutable loop here because we are erasing the list * elements. */ LISTBASE_FOREACH_MUTABLE (tSamplePoint *, temp, &points) { - if (temp->dw != NULL) { + if (temp->dw != nullptr) { MEM_freeN(temp->dw); } MEM_SAFE_FREE(temp); @@ -3558,7 +3581,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, * Stroke to view space * Transforms a stroke to view space. This allows for manipulations in 2D but also easy conversion * back to 3D. - * Note: also takes care of parent space transform + * NOTE: also takes care of parent space transform */ void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d, bGPDstroke *gps, @@ -3577,7 +3600,7 @@ void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d, * Stroke from view space * Transforms a stroke from view space back to world space. Inverse of * BKE_gpencil_stroke_to_view_space - * Note: also takes care of parent space transform + * NOTE: also takes care of parent space transform */ void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d, bGPDstroke *gps, @@ -3596,14 +3619,14 @@ void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d, /* ----------------------------------------------------------------------------- */ /* Stroke to perimeter */ -typedef struct tPerimeterPoint { +struct tPerimeterPoint { struct tPerimeterPoint *next, *prev; float x, y, z; -} tPerimeterPoint; +}; static tPerimeterPoint *new_perimeter_point(const float pt[3]) { - tPerimeterPoint *new_pt = MEM_callocN(sizeof(tPerimeterPoint), __func__); + tPerimeterPoint *new_pt = (tPerimeterPoint *)MEM_callocN(sizeof(tPerimeterPoint), __func__); copy_v3_v3(&new_pt->x, pt); return new_pt; } @@ -3766,14 +3789,14 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd, { /* sanity check */ if (gps->totpoints < 1) { - return NULL; + return nullptr; } float defaultpixsize = 1000.0f / gpd->pixfactor; float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f; - ListBase *perimeter_right_side = MEM_callocN(sizeof(ListBase), __func__); - ListBase *perimeter_left_side = MEM_callocN(sizeof(ListBase), __func__); + ListBase *perimeter_right_side = (ListBase *)MEM_callocN(sizeof(ListBase), __func__); + ListBase *perimeter_left_side = (ListBase *)MEM_callocN(sizeof(ListBase), __func__); int num_perimeter_points = 0; bGPDspoint *first = &gps->points[0]; @@ -4013,7 +4036,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, const float diff_mat[4][4]) { if (gps->totpoints == 0) { - return NULL; + return nullptr; } bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, true, false); const bool cyclic = ((gps_temp->flag & GP_STROKE_CYCLIC) != 0); @@ -4021,8 +4044,8 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, /* If Cyclic, add a new point. */ if (cyclic && (gps_temp->totpoints > 1)) { gps_temp->totpoints++; - gps_temp->points = MEM_recallocN(gps_temp->points, - sizeof(*gps_temp->points) * gps_temp->totpoints); + gps_temp->points = (bGPDspoint *)MEM_recallocN( + gps_temp->points, sizeof(*gps_temp->points) * gps_temp->totpoints); bGPDspoint *pt_src = &gps_temp->points[0]; bGPDspoint *pt_dst = &gps_temp->points[gps_temp->totpoints - 1]; copy_v3_v3(&pt_dst->x, &pt_src->x); @@ -4038,7 +4061,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, gpd, gpl, gps_temp, subdivisions, &num_perimeter_points); if (num_perimeter_points == 0) { - return NULL; + return nullptr; } /* Create new stroke. */ diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 9f5f70ab2ba..4db527e5b42 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -257,9 +257,13 @@ bool BKE_gpencil_is_first_lineart_in_stack(const Object *ob, const GpencilModifi return false; } -/* apply time modifiers */ -static int gpencil_time_modifier( - Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl, int cfra, bool is_render) +/* Get Time modifier frame number. */ +int BKE_gpencil_time_modifier_cfra(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + bGPDlayer *gpl, + const int cfra, + const bool is_render) { bGPdata *gpd = ob->data; const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd); @@ -269,7 +273,7 @@ static int gpencil_time_modifier( if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); - if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { + if (GPENCIL_MODIFIER_EDIT(md, is_edit) && (!is_render)) { continue; } @@ -350,7 +354,7 @@ GpencilModifierData *BKE_gpencil_modifier_new(int type) const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type); GpencilModifierData *md = MEM_callocN(mti->struct_size, mti->struct_name); - /* note, this name must be made unique later */ + /* NOTE: this name must be made unique later. */ BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name)); md->type = type; @@ -665,7 +669,7 @@ static int gpencil_remap_time_get(Depsgraph *depsgraph, Scene *scene, Object *ob int remap_cfra = cfra_eval; if (time_remap) { - remap_cfra = gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render); + remap_cfra = BKE_gpencil_time_modifier_cfra(depsgraph, scene, ob, gpl, cfra_eval, is_render); } return remap_cfra; @@ -834,7 +838,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); - if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { + if (GPENCIL_MODIFIER_EDIT(md, is_edit) && (!is_render)) { continue; } diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index a67e78ceea0..7a88a00c44f 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -186,7 +186,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen) } } - /* - Note: This code comes from python, here's the corresponding comment. - */ + /* NOTE: This code comes from python, here's the corresponding comment. */ /* This over-allocates proportional to the list size, making room * for additional growth. The over-allocation is mild, but is * enough to give linear-time amortized behavior over a long @@ -240,7 +240,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) return; } - /* - Note: This code comes from python, here's the corresponding comment. - */ + /* NOTE: This code comes from python, here's the corresponding comment. */ /* This over-allocates proportional to the list size, making room * for additional growth. The over-allocation is mild, but is * enough to give linear-time amortized behavior over a long @@ -942,7 +942,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char * prop = MEM_callocN(sizeof(IDProperty), "IDProperty string"); if (val->string.subtype == IDP_STRING_SUB_BYTE) { - /* note, intentionally not null terminated */ + /* NOTE: Intentionally not null terminated. */ if (st == NULL) { prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); *IDP_String(prop) = '\0'; @@ -1183,7 +1183,7 @@ static void IDP_DirectLinkIDPArray(IDProperty *prop, BlendDataReader *reader) IDProperty *array = (IDProperty *)prop->data.pointer; - /* note!, idp-arrays didn't exist in 2.4x, so the pointer will be cleared + /* NOTE:, idp-arrays didn't exist in 2.4x, so the pointer will be cleared * there's not really anything we can do to correct this, at least don't crash */ if (array == NULL) { prop->len = 0; @@ -1274,7 +1274,7 @@ static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader) * IDP are way too polymorphic to do it safely. */ printf( "%s: found unknown IDProperty type %d, reset to Integer one !\n", __func__, prop->type); - /* Note: we do not attempt to free unknown prop, we have no way to know how to do that! */ + /* NOTE: we do not attempt to free unknown prop, we have no way to know how to do that! */ prop->type = IDP_INT; prop->subtype = 0; IDP_Int(prop) = 0; diff --git a/source/blender/blenkernel/intern/idprop_utils.c b/source/blender/blenkernel/intern/idprop_utils.c index 433f0e97844..0cc212e1880 100644 --- a/source/blender/blenkernel/intern/idprop_utils.c +++ b/source/blender/blenkernel/intern/idprop_utils.c @@ -96,7 +96,7 @@ static void idp_str_append_escape(struct ReprState *state, static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *prop) { - /* Note: 'strlen' will be calculated at compile time for literals. */ + /* NOTE: 'strlen' will be calculated at compile time for literals. */ #define STR_APPEND_STR(str) state->str_append_fn(state->user_data, str, (uint)strlen(str)) #define STR_APPEND_STR_QUOTE(str) idp_str_append_escape(state, str, (uint)strlen(str), true) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 740c9b3864c..f4ba1ff8b92 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -640,7 +640,7 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source) } } -/* note, we could be clever and scale all imbuf's but since some are mipmaps its not so simple */ +/* NOTE: We could be clever and scale all imbuf's but since some are mipmaps its not so simple. */ bool BKE_image_scale(Image *image, int width, int height) { ImBuf *ibuf; @@ -1778,7 +1778,7 @@ static bool do_add_image_extension(char *string, } } else { - BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec"); + BLI_assert_msg(0, "Unsupported jp2 codec was specified in im_format->jp2_codec"); } } else { @@ -1949,7 +1949,7 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i im_format->jp2_codec = R_IMF_JP2_CODEC_J2K; } else { - BLI_assert(!"Unsupported jp2 codec was specified in file type"); + BLI_assert_msg(0, "Unsupported jp2 codec was specified in file type"); } } #endif @@ -2323,7 +2323,7 @@ void BKE_image_stamp_buf(Scene *scene, stampdata_from_template(&stamp_data, scene, stamp_data_template, do_prefix); } - /* TODO, do_versions */ + /* TODO: do_versions. */ if (scene->r.stamp_font_id < 8) { scene->r.stamp_font_id = 12; } @@ -2867,7 +2867,7 @@ bool BKE_imbuf_alpha_test(ImBuf *ibuf) return false; } -/* note: imf->planes is ignored here, its assumed the image channels +/* NOTE: imf->planes is ignored here, its assumed the image channels * are already set */ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf) { @@ -3017,7 +3017,7 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf) ibuf->foptions.flag |= JP2_J2K; } else { - BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec"); + BLI_assert_msg(0, "Unsupported jp2 codec was specified in im_format->jp2_codec"); } } #endif @@ -4540,7 +4540,7 @@ static ImBuf *load_image_single(Image *ima, } /* warning, 'iuser' can be NULL - * note: Image->views was already populated (in image_update_views_format) + * NOTE: Image->views was already populated (in image_update_views_format) */ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) { @@ -5391,7 +5391,7 @@ void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra) } if (ima && ima->gpuframenr != iuser->framenr) { - /* Note: a single texture and refresh doesn't really work when + /* NOTE: a single texture and refresh doesn't really work when * multiple image users may use different frames, this is to * be improved with perhaps a GPU texture cache. */ ima->gpuflag |= IMA_GPU_REFRESH; diff --git a/source/blender/blenkernel/intern/image_save.c b/source/blender/blenkernel/intern/image_save.c index b68cd9e4d2d..9e3d5a162ae 100644 --- a/source/blender/blenkernel/intern/image_save.c +++ b/source/blender/blenkernel/intern/image_save.c @@ -169,7 +169,7 @@ static bool image_save_single(ReportList *reports, } } else { - /* TODO, better solution, if a 24bit image is painted onto it may contain alpha */ + /* TODO: better solution, if a 24bit image is painted onto it may contain alpha. */ if ((opts->im_format.planes == R_IMF_PLANES_RGBA) && /* it has been painted onto */ (ibuf->userflags & IB_BITMAPDIRTY)) { diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index f365e759221..8a70f065e40 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1135,7 +1135,7 @@ static char *get_rna_access(ID *id, /* special case for rotdiff drivers... we don't need a property for this... */ break; - /* TODO... add other blocktypes... */ + /* TODO: add other block-types. */ default: CLOG_WARN(&LOG, "No path for blocktype %d, adrcode %d yet", blocktype, adrcode); break; @@ -1162,7 +1162,7 @@ static char *get_rna_access(ID *id, /* 'buf' _must_ be initialized in this block */ /* append preceding bits to path */ - /* note, strings are not escapted and they should be! */ + /* NOTE: strings are not escapted and they should be! */ if ((actname && actname[0]) && (constname && constname[0])) { /* Constraint in Pose-Channel */ char actname_esc[sizeof(((bActionChannel *)NULL)->name) * 2]; @@ -1305,7 +1305,7 @@ static ChannelDriver *idriver_to_cdriver(IpoDriver *idriver) dtar = &dvar->targets[1]; dtar->id = (ID *)idriver->ob; dtar->idtype = ID_OB; - if (idriver->name[0]) { /* xxx... for safety */ + if (idriver->name[0]) { /* XXX: for safety. */ BLI_strncpy( dtar->pchan_name, idriver->name + DRIVER_NAME_OFFS, sizeof(dtar->pchan_name)); } @@ -1358,12 +1358,12 @@ static void fcurve_add_to_list( bActionGroup *agrp = NULL; /* init the temp action */ - memset(&tmp_act, 0, sizeof(bAction)); /* XXX only enable this line if we get errors */ + memset(&tmp_act, 0, sizeof(bAction)); /* XXX: Only enable this line if we get errors. */ tmp_act.groups.first = groups->first; tmp_act.groups.last = groups->last; tmp_act.curves.first = list->first; tmp_act.curves.last = list->last; - /* ... xxx, the other vars don't need to be filled in */ + /* XXX: The other vars don't need to be filled in. */ /* get the group to use */ agrp = BKE_action_group_find_name(&tmp_act, grpname); @@ -2087,7 +2087,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* check if object has any animation data */ if (ob->nlastrips.first) { /* Add AnimData block */ - BKE_animdata_add_id(id); + BKE_animdata_ensure_id(id); /* IPO first to take into any non-NLA'd Object Animation */ if (ob->ipo) { @@ -2109,7 +2109,7 @@ void do_versions_ipos_to_animato(Main *bmain) } else if ((ob->ipo) || (ob->action)) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Action first - so that Action name get conserved */ if (ob->action) { @@ -2133,7 +2133,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* check PoseChannels for constraints with local data */ if (ob->pose) { /* Verify if there's AnimData block */ - BKE_animdata_add_id(id); + BKE_animdata_ensure_id(id); for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { @@ -2159,7 +2159,7 @@ void do_versions_ipos_to_animato(Main *bmain) */ if (con->ipo) { /* Verify if there's AnimData block, just in case */ - BKE_animdata_add_id(id); + BKE_animdata_ensure_id(id); /* although this was the constraint's local IPO, we still need to provide con * so that drivers can be added properly... @@ -2176,7 +2176,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* check constraint channels - we need to remove them anyway... */ if (ob->constraintChannels.first) { /* Verify if there's AnimData block */ - BKE_animdata_add_id(id); + BKE_animdata_ensure_id(id); for (conchan = ob->constraintChannels.first; conchan; conchan = conchann) { /* get pointer to next Constraint Channel */ @@ -2217,7 +2217,7 @@ void do_versions_ipos_to_animato(Main *bmain) */ if (key->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Convert Shapekey data... */ ipo_to_animdata(bmain, id, key->ipo, NULL, NULL, NULL); @@ -2242,7 +2242,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* we're only interested in the IPO */ if (ma->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Convert Material data... */ ipo_to_animdata(bmain, id, ma->ipo, NULL, NULL, NULL); @@ -2267,7 +2267,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* we're only interested in the IPO */ if (wo->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Convert World data... */ ipo_to_animdata(bmain, id, wo->ipo, NULL, NULL, NULL); @@ -2288,7 +2288,7 @@ void do_versions_ipos_to_animato(Main *bmain) if (ed && ed->seqbasep) { Sequence *seq; - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); SEQ_ALL_BEGIN (ed, seq) { IpoCurve *icu = (seq->ipo) ? seq->ipo->curve.first : NULL; @@ -2346,7 +2346,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* we're only interested in the IPO */ if (te->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Convert Texture data... */ ipo_to_animdata(bmain, id, te->ipo, NULL, NULL, NULL); @@ -2371,7 +2371,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* we're only interested in the IPO */ if (ca->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Convert Camera data... */ ipo_to_animdata(bmain, id, ca->ipo, NULL, NULL, NULL); @@ -2396,7 +2396,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* we're only interested in the IPO */ if (la->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Convert Light data... */ ipo_to_animdata(bmain, id, la->ipo, NULL, NULL, NULL); @@ -2421,7 +2421,7 @@ void do_versions_ipos_to_animato(Main *bmain) /* we're only interested in the IPO */ if (cu->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); /* Convert Curve data... */ ipo_to_animdata(bmain, id, cu->ipo, NULL, NULL, NULL); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 6cc90f86b4a..0f8c9bad798 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -694,7 +694,7 @@ static bool key_pointer_size(const Key *key, const int mode, int *poinsize, int *poinsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]); break; default: - BLI_assert(!"invalid 'key->from' ID type"); + BLI_assert_msg(0, "invalid 'key->from' ID type"); return false; } @@ -806,7 +806,7 @@ static void cp_key(const int start, if (freekref) { MEM_freeN(freekref); } - BLI_assert(!"invalid 'cp[1]'"); + BLI_assert_msg(0, "invalid 'cp[1]'"); return; } @@ -984,7 +984,7 @@ static void key_evaluate_relative(const int start, if (freefrom) { MEM_freeN(freefrom); } - BLI_assert(!"invalid 'cp[1]'"); + BLI_assert_msg(0, "invalid 'cp[1]'"); return; } @@ -1204,7 +1204,7 @@ static void do_key(const int start, if (freek4) { MEM_freeN(freek4); } - BLI_assert(!"invalid 'cp[1]'"); + BLI_assert_msg(0, "invalid 'cp[1]'"); return; } @@ -1317,7 +1317,7 @@ static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cac if (cache) { if (cache->defgroup_weights == NULL) { - int num_defgroup = BLI_listbase_count(&ob->defbase); + int num_defgroup = BKE_object_defgroup_count(ob); cache->defgroup_weights = MEM_callocN(sizeof(*cache->defgroup_weights) * num_defgroup, "cached defgroup weights"); cache->num_defgroup_weights = num_defgroup; @@ -1695,7 +1695,7 @@ void BKE_keyblock_data_set_with_mat4(Key *key, const float mat[4][4]) { if (key->elemsize != sizeof(float[3])) { - BLI_assert(!"Invalid elemsize"); + BLI_assert_msg(0, "Invalid elemsize"); return; } diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 1357424d5ff..9875d776d33 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -87,6 +87,8 @@ static void lattice_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const i lattice_dst->key->from = &lattice_dst->id; } + BKE_defgroup_copy_list(&lattice_dst->vertex_group_names, &lattice_src->vertex_group_names); + if (lattice_src->dvert) { int tot = lattice_src->pntsu * lattice_src->pntsv * lattice_src->pntsw; lattice_dst->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert"); @@ -103,6 +105,8 @@ static void lattice_free_data(ID *id) BKE_lattice_batch_cache_free(lattice); + BLI_freelistN(&lattice->vertex_group_names); + MEM_SAFE_FREE(lattice->def); if (lattice->dvert) { BKE_defvert_array_free(lattice->dvert, lattice->pntsu * lattice->pntsv * lattice->pntsw); @@ -150,6 +154,7 @@ static void lattice_blend_write(BlendWriter *writer, ID *id, const void *id_addr /* direct data */ BLO_write_struct_array(writer, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def); + BKE_defbase_blend_write(writer, <->vertex_group_names); BKE_defvert_blend_write(writer, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert); } } @@ -161,6 +166,7 @@ static void lattice_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_data_address(reader, <->dvert); BKE_defvert_blend_read(reader, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert); + BLO_read_list(reader, <->vertex_group_names); lt->editlatt = NULL; lt->batch_cache = NULL; diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c index a3133b58a0a..f9437eeaffa 100644 --- a/source/blender/blenkernel/intern/lattice_deform.c +++ b/source/blender/blenkernel/intern/lattice_deform.c @@ -108,11 +108,11 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob invert_m4_m4(imat, latmat); } - /* Prefetch latice deform group weights. */ + /* Prefetch lattice deform group weights. */ int defgrp_index = -1; const MDeformVert *dvert = BKE_lattice_deform_verts_get(oblatt); if (lt->vgroup[0] && dvert) { - defgrp_index = BKE_object_defgroup_name_index(oblatt, lt->vgroup); + defgrp_index = BKE_id_defgroup_name_index(<->id, lt->vgroup); if (defgrp_index != -1) { lattice_weights = MEM_malloc_arrayN(sizeof(float), num_points, "lattice_weights"); @@ -364,7 +364,7 @@ static void lattice_deform_coords_impl(const Object *ob_lattice, * We want either a Mesh/Lattice with no derived data, or derived data with deformverts. */ if (defgrp_name && defgrp_name[0] && ob_target && ELEM(ob_target->type, OB_MESH, OB_LATTICE)) { - defgrp_index = BKE_object_defgroup_name_index(ob_target, defgrp_name); + defgrp_index = BKE_id_defgroup_name_index((ID *)ob_target->data, defgrp_name); if (defgrp_index != -1) { /* if there's derived data without deformverts, don't use vgroups */ diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index d49eb0d4da8..730c989abc9 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -737,172 +737,193 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection * in at least one layer collection. That list is also synchronized here, and * stores state like selection. */ +static void layer_collection_objects_sync(ViewLayer *view_layer, + LayerCollection *layer, + ListBase *r_lb_new_object_bases, + const short collection_restrict, + const short layer_restrict, + const ushort local_collections_bits) +{ + /* No need to sync objects if the collection is excluded. */ + if ((layer->flag & LAYER_COLLECTION_EXCLUDE) != 0) { + return; + } + + LISTBASE_FOREACH (CollectionObject *, cob, &layer->collection->gobject) { + if (cob->ob == NULL) { + continue; + } + + /* Tag linked object as a weak reference so we keep the object + * base pointer on file load and remember hidden state. */ + id_lib_indirect_weak_link(&cob->ob->id); + + void **base_p; + Base *base; + if (BLI_ghash_ensure_p(view_layer->object_bases_hash, cob->ob, &base_p)) { + /* Move from old base list to new base list. Base might have already + * been moved to the new base list and the first/last test ensure that + * case also works. */ + base = *base_p; + if (!ELEM(base, r_lb_new_object_bases->first, r_lb_new_object_bases->last)) { + BLI_remlink(&view_layer->object_bases, base); + BLI_addtail(r_lb_new_object_bases, base); + } + } + else { + /* Create new base. */ + base = object_base_new(cob->ob); + base->local_collections_bits = local_collections_bits; + *base_p = base; + BLI_addtail(r_lb_new_object_bases, base); + } + + if ((collection_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) { + base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH); + if ((layer_restrict & LAYER_COLLECTION_HIDE) == 0) { + base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER; + } + if (((collection_restrict & COLLECTION_RESTRICT_SELECT) == 0)) { + base->flag_from_collection |= BASE_SELECTABLE; + } + } + + if ((collection_restrict & COLLECTION_RESTRICT_RENDER) == 0) { + base->flag_from_collection |= BASE_ENABLED_RENDER; + } + + /* Holdout and indirect only */ + if (layer->flag & LAYER_COLLECTION_HOLDOUT) { + base->flag_from_collection |= BASE_HOLDOUT; + } + if (layer->flag & LAYER_COLLECTION_INDIRECT_ONLY) { + base->flag_from_collection |= BASE_INDIRECT_ONLY; + } + + layer->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS; + } +} + static void layer_collection_sync(ViewLayer *view_layer, - const ListBase *lb_collections, - ListBase *lb_layer_collections, - ListBase *new_object_bases, - short parent_exclude, - short parent_restrict, - short parent_layer_restrict, - unsigned short parent_local_collections_bits) + const ListBase *lb_children_collections, + ListBase *r_lb_children_layers, + ListBase *r_lb_new_object_bases, + const short parent_layer_flag, + const short parent_collection_restrict, + const short parent_layer_restrict, + const ushort parent_local_collections_bits) { /* TODO: support recovery after removal of intermediate collections, reordering, .. * For local edits we can make editing operating do the appropriate thing, but for * linking we can only sync after the fact. */ /* Remove layer collections that no longer have a corresponding scene collection. */ - LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, lb_layer_collections) { - /* Note that ID remap can set lc->collection to NULL when deleting collections. */ - Collection *collection = (lc->collection) ? - BLI_findptr(lb_collections, - lc->collection, - offsetof(CollectionChild, collection)) : - NULL; - - if (!collection) { - if (lc == view_layer->active_collection) { + LISTBASE_FOREACH_MUTABLE (LayerCollection *, child_layer, r_lb_children_layers) { + /* Note that ID remap can set child_layer->collection to NULL when deleting collections. */ + Collection *child_collection = (child_layer->collection != NULL) ? + BLI_findptr(lb_children_collections, + child_layer->collection, + offsetof(CollectionChild, collection)) : + NULL; + + if (child_collection == NULL) { + if (child_layer == view_layer->active_collection) { view_layer->active_collection = NULL; } /* Free recursively. */ - layer_collection_free(view_layer, lc); - BLI_freelinkN(lb_layer_collections, lc); + layer_collection_free(view_layer, child_layer); + BLI_freelinkN(r_lb_children_layers, child_layer); } } /* Add layer collections for any new scene collections, and ensure order is the same. */ - ListBase new_lb_layer = {NULL, NULL}; + ListBase lb_new_children_layers = {NULL, NULL}; - LISTBASE_FOREACH (const CollectionChild *, child, lb_collections) { - Collection *collection = child->collection; - LayerCollection *lc = BLI_findptr( - lb_layer_collections, collection, offsetof(LayerCollection, collection)); + LISTBASE_FOREACH (const CollectionChild *, child, lb_children_collections) { + Collection *child_collection = child->collection; + LayerCollection *child_layer = BLI_findptr( + r_lb_children_layers, child_collection, offsetof(LayerCollection, collection)); - if (lc) { - BLI_remlink(lb_layer_collections, lc); - BLI_addtail(&new_lb_layer, lc); + if (child_layer) { + BLI_remlink(r_lb_children_layers, child_layer); + BLI_addtail(&lb_new_children_layers, child_layer); } else { - lc = layer_collection_add(&new_lb_layer, collection); - lc->flag = parent_exclude; + child_layer = layer_collection_add(&lb_new_children_layers, child_collection); + child_layer->flag = parent_layer_flag; } - unsigned short local_collections_bits = parent_local_collections_bits & - lc->local_collections_bits; + const ushort child_local_collections_bits = parent_local_collections_bits & + child_layer->local_collections_bits; /* Tag linked collection as a weak reference so we keep the layer * collection pointer on file load and remember exclude state. */ - id_lib_indirect_weak_link(&collection->id); + id_lib_indirect_weak_link(&child_collection->id); /* Collection restrict is inherited. */ - short child_restrict = parent_restrict; + short child_collection_restrict = parent_collection_restrict; short child_layer_restrict = parent_layer_restrict; - if (!(collection->flag & COLLECTION_IS_MASTER)) { - child_restrict |= collection->flag; - child_layer_restrict |= lc->flag; + if (!(child_collection->flag & COLLECTION_IS_MASTER)) { + child_collection_restrict |= child_collection->flag; + child_layer_restrict |= child_layer->flag; } /* Sync child collections. */ layer_collection_sync(view_layer, - &collection->children, - &lc->layer_collections, - new_object_bases, - lc->flag, - child_restrict, + &child_collection->children, + &child_layer->layer_collections, + r_lb_new_object_bases, + child_layer->flag, + child_collection_restrict, child_layer_restrict, - local_collections_bits); + child_local_collections_bits); - /* Layer collection exclude is not inherited. */ - lc->runtime_flag = 0; - if (lc->flag & LAYER_COLLECTION_EXCLUDE) { + /* Layer collection exclude is not inherited, we can skip the remaining process, including + * object bases synchronization. */ + child_layer->runtime_flag = 0; + if (child_layer->flag & LAYER_COLLECTION_EXCLUDE) { continue; } /* We separate restrict viewport and visible view layer because a layer collection can be * hidden in the view layer yet (locally) visible in a viewport (if it is not restricted). */ - if (child_restrict & COLLECTION_RESTRICT_VIEWPORT) { - lc->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT; + if (child_collection_restrict & COLLECTION_RESTRICT_VIEWPORT) { + child_layer->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT; } - if (((lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) && + if (((child_layer->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) && ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) { - lc->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER; + child_layer->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER; } - /* Sync objects, except if collection was excluded. */ - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - if (cob->ob == NULL) { - continue; - } - - /* Tag linked object as a weak reference so we keep the object - * base pointer on file load and remember hidden state. */ - id_lib_indirect_weak_link(&cob->ob->id); - - void **base_p; - Base *base; - if (BLI_ghash_ensure_p(view_layer->object_bases_hash, cob->ob, &base_p)) { - /* Move from old base list to new base list. Base might have already - * been moved to the new base list and the first/last test ensure that - * case also works. */ - base = *base_p; - if (!ELEM(base, new_object_bases->first, new_object_bases->last)) { - BLI_remlink(&view_layer->object_bases, base); - BLI_addtail(new_object_bases, base); - } - } - else { - /* Create new base. */ - base = object_base_new(cob->ob); - base->local_collections_bits = local_collections_bits; - *base_p = base; - BLI_addtail(new_object_bases, base); - } - - if ((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) { - base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH); - if ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0) { - base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER; - } - if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0)) { - base->flag_from_collection |= BASE_SELECTABLE; - } - } - - if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) { - base->flag_from_collection |= BASE_ENABLED_RENDER; - } - - /* Holdout and indirect only */ - if (lc->flag & LAYER_COLLECTION_HOLDOUT) { - base->flag_from_collection |= BASE_HOLDOUT; - } - if (lc->flag & LAYER_COLLECTION_INDIRECT_ONLY) { - base->flag_from_collection |= BASE_INDIRECT_ONLY; - } - - lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS; - } + layer_collection_objects_sync(view_layer, + child_layer, + r_lb_new_object_bases, + child_collection_restrict, + child_layer_restrict, + child_local_collections_bits); } /* Free potentially remaining unused layer collections in old list. * NOTE: While this does not happen in typical situations, some corner cases (like remapping * several different collections to a single one) can lead to this list having extra unused * items. */ - LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, lb_layer_collections) { + LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, r_lb_children_layers) { if (lc == view_layer->active_collection) { view_layer->active_collection = NULL; } /* Free recursively. */ layer_collection_free(view_layer, lc); - BLI_freelinkN(lb_layer_collections, lc); + BLI_freelinkN(r_lb_children_layers, lc); } - BLI_assert(BLI_listbase_is_empty(lb_layer_collections)); + BLI_assert(BLI_listbase_is_empty(r_lb_children_layers)); /* Replace layer collection list with new one. */ - *lb_layer_collections = new_lb_layer; - BLI_assert(BLI_listbase_count(lb_collections) == BLI_listbase_count(lb_layer_collections)); + *r_lb_children_layers = lb_new_children_layers; + BLI_assert(BLI_listbase_count(lb_children_collections) == + BLI_listbase_count(r_lb_children_layers)); } /** diff --git a/source/blender/blenkernel/intern/layer_utils.c b/source/blender/blenkernel/intern/layer_utils.c index 10ab0a06dd0..48179e0c3bf 100644 --- a/source/blender/blenkernel/intern/layer_utils.c +++ b/source/blender/blenkernel/intern/layer_utils.c @@ -23,6 +23,7 @@ #include "BLI_array.h" #include "BKE_collection.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_layer.h" diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 297ee565257..62d29188c5a 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -499,7 +499,7 @@ bool BKE_lib_id_make_local(Main *bmain, ID *id, const bool test, const int flags return false; } - BLI_assert(!"IDType Missing IDTypeInfo"); + BLI_assert_msg(0, "IDType Missing IDTypeInfo"); return false; } @@ -603,7 +603,7 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) } } else { - BLI_assert(!"IDType Missing IDTypeInfo"); + BLI_assert_msg(0, "IDType Missing IDTypeInfo"); } /* Update ID refcount, remap pointers to self in new ID. */ @@ -667,7 +667,7 @@ ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplica ID_NEW_SET(key, key_new); } - /* Note: embedded data (root nodetrees and master collections) should never be referenced by + /* NOTE: embedded data (root nodetrees and master collections) should never be referenced by * anything else, so we do not need to set their newid pointer and flag. */ BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags); @@ -1053,7 +1053,7 @@ void *BKE_libblock_alloc_notest(short type) if (size != 0) { return MEM_callocN(size, name); } - BLI_assert(!"Request to allocate unknown data type"); + BLI_assert_msg(0, "Request to allocate unknown data type"); return NULL; } @@ -1099,7 +1099,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl /* alphabetic insertion: is in new_id */ BKE_main_unlock(bmain); - /* TODO to be removed from here! */ + /* TODO: to be removed from here! */ if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) { DEG_id_type_tag(bmain, type); } @@ -1134,7 +1134,7 @@ void BKE_libblock_init_empty(ID *id) return; } - BLI_assert(!"IDType Missing IDTypeInfo"); + BLI_assert_msg(0, "IDType Missing IDTypeInfo"); } /* ********** ID session-wise UUID management. ********** */ @@ -1234,11 +1234,11 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) { /* r_newid already contains pointer to allocated memory. */ - /* TODO do we want to memset(0) whole mem before filling it? */ + /* TODO: do we want to memset(0) whole mem before filling it? */ BLI_strncpy(new_id->name, id->name, sizeof(new_id->name)); new_id->us = 0; new_id->tag |= LIB_TAG_NOT_ALLOCATED | LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT; - /* TODO Do we want/need to copy more from ID struct itself? */ + /* TODO: Do we want/need to copy more from ID struct itself? */ } else { new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag); @@ -1380,7 +1380,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint) /* Step one: We go backward over a whole chunk of items at once, until we find a limit item * that is lower than, or equal (should never happen!) to the one we want to insert. */ - /* Note: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at + /* NOTE: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at * once using the same base name), newly inserted items will generally be towards the end * (higher extension numbers). */ bool is_in_library = false; @@ -1450,7 +1450,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint) #undef ID_SORT_STEP_SIZE } -/* Note: this code assumes and ensures that the suffix number can never go beyond 1 billion. */ +/* NOTE: this code assumes and ensures that the suffix number can never go beyond 1 billion. */ #define MAX_NUMBER 1000000000 /* We do not want to get "name.000", so minimal number is 1. */ #define MIN_NUMBER 1 @@ -1605,7 +1605,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_ } /* In case we get an insane initial number suffix in given name. */ - /* Note: BLI_split_name_num() cannot return negative numbers, so we do not have to check for + /* NOTE: BLI_split_name_num() cannot return negative numbers, so we do not have to check for * that here. */ if (number >= MAX_NUMBER || number < MIN_NUMBER) { number = MIN_NUMBER; @@ -1642,9 +1642,8 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_ * already. */ if (!is_orig_name_used) { - /* Don't bother updating prev_ static variables here, this case is not supposed to happen - * that often, and is not straight-forward here, so just ignore and reset them to default. - */ + /* Don't bother updating `prev_*` static variables here, this case is not supposed to happen + * that often, and is not straight-forward here, so just ignore and reset them to default. */ prev_id_type = ID_LINK_PLACEHOLDER; prev_final_base_name[0] = '\0'; prev_number = MIN_NUMBER - 1; @@ -1684,7 +1683,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_ continue; } - /* Update prev_ static variables, in case next call is for the same type of IDs and with the + /* Update `prev_*` static variables, in case next call is for the same type of IDs and with the * same initial base name, we can skip a lot of above process. */ prev_id_type = id_type; strcpy(prev_final_base_name, base_name); @@ -1892,7 +1891,7 @@ static void library_make_local_copying_check(ID *id, * \param set_fake: If true, set fake user on all localized data-blocks * (except group and objects ones). */ -/* Note: Old (2.77) version was simply making (tagging) data-blocks as local, +/* NOTE: Old (2.77) version was simply making (tagging) data-blocks as local, * without actually making any check whether they were also indirectly used or not... * * Current version uses regular id_make_local callback, with advanced pre-processing step to @@ -2070,7 +2069,7 @@ void BKE_library_make_local(Main *bmain, * ID in a separated loop, * as lbarray ordering is not enough to ensure us we did catch all dependencies * (e.g. if making local a parent object before its child...). See T48907. */ - /* TODO This is now the biggest step by far (in term of processing time). + /* TODO: This is now the biggest step by far (in term of processing time). * We may be able to gain here by using again main->relations mapping, but... * this implies BKE_libblock_remap & co to be able to update main->relations on the fly. * Have to think about it a bit more, and see whether new code is OK first, anyway. */ diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index 67b2e4429d6..a9407860c06 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -83,7 +83,7 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag)) return; } - BLI_assert(!"IDType Missing IDTypeInfo"); + BLI_assert_msg(0, "IDType Missing IDTypeInfo"); } /** @@ -277,7 +277,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) for (id = lb->first; id; id = id_next) { id_next = id->next; - /* Note: in case we delete a library, we also delete all its datablocks! */ + /* NOTE: in case we delete a library, we also delete all its datablocks! */ if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) { BLI_remlink(lb, id); BLI_addtail(&tagged_deleted_ids, id); @@ -331,7 +331,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) for (id = lb->first; id; id = id_next) { id_next = id->next; - /* Note: in case we delete a library, we also delete all its datablocks! */ + /* NOTE: in case we delete a library, we also delete all its datablocks! */ if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) { id->tag |= tag; diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 595e470876d..9871bf5dc83 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -94,7 +94,7 @@ BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id) if (id_type->owner_get != NULL) { return id_type->owner_get(bmain, id)->override_library; } - BLI_assert(!"IDTypeInfo of liboverride-embedded ID with no owner getter"); + BLI_assert_msg(0, "IDTypeInfo of liboverride-embedded ID with no owner getter"); } return id->override_library; } @@ -130,7 +130,7 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) local_id->override_library->reference = reference_id; id_us_plus(local_id->override_library->reference); local_id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_REFOK; - /* TODO do we want to add tag or flag to referee to mark it as such? */ + /* TODO: do we want to add tag or flag to referee to mark it as such? */ return local_id->override_library; } @@ -217,7 +217,7 @@ static ID *lib_override_library_create_from(Main *bmain, ID *reference_id, const int lib_id_copy_flags) { - /* Note: We do not want to copy possible override data from reference here (whether it is an + /* NOTE: We do not want to copy possible override data from reference here (whether it is an * override template, or already an override of some other ref data). */ ID *local_id = BKE_id_copy_ex(bmain, reference_id, @@ -232,7 +232,7 @@ static ID *lib_override_library_create_from(Main *bmain, BKE_lib_override_library_init(local_id, reference_id); - /* Note: From liboverride perspective (and RNA one), shape keys are considered as local embedded + /* NOTE: From liboverride perspective (and RNA one), shape keys are considered as local embedded * data-blocks, just like root node trees or master collections. Therefore, we never need to * create overrides for them. We need a way to mark them as overrides though. */ Key *reference_key; @@ -369,7 +369,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain, /* If `newid` is already set, assume it has been handled by calling code. * Only current use case: re-using proxy ID when converting to liboverride. */ if (reference_id->newid == NULL) { - /* Note: `no main` case is used during resync procedure, to support recursive resync. + /* NOTE: `no main` case is used during resync procedure, to support recursive resync. * This requires extra care further down the resync process, * see: #BKE_lib_override_library_resync. */ reference_id->newid = lib_override_library_create_from( @@ -569,7 +569,7 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat /* We tag all collections and objects for override. And we also tag all other data-blocks which * would use one of those. - * Note: missing IDs (aka placeholders) are never overridden. */ + * NOTE: missing IDs (aka placeholders) are never overridden. */ if (ELEM(GS(to_id->name), ID_OB, ID_GR)) { if ((to_id->tag & LIB_TAG_MISSING)) { to_id->tag |= missing_tag; @@ -1347,7 +1347,7 @@ bool BKE_lib_override_library_resync(Main *bmain, if (do_post_process) { /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ - /* Note: Here 'reference' collection and 'newly added' collection are the same, which is fine + /* NOTE: Here 'reference' collection and 'newly added' collection are the same, which is fine * since we already relinked old root override collection to new resync'ed one above. So this * call is not expected to instantiate this new resync'ed collection anywhere, just to ensure * that we do not have any stray objects. */ @@ -2126,7 +2126,7 @@ bool BKE_lib_override_library_property_operation_operands_validate( ATTR_FALLTHROUGH; case IDOVERRIDE_LIBRARY_OP_MULTIPLY: if (ptr_storage == NULL || ptr_storage->data == NULL || prop_storage == NULL) { - BLI_assert(!"Missing data to apply differential override operation."); + BLI_assert_msg(0, "Missing data to apply differential override operation."); return false; } ATTR_FALLTHROUGH; @@ -2137,7 +2137,7 @@ bool BKE_lib_override_library_property_operation_operands_validate( case IDOVERRIDE_LIBRARY_OP_REPLACE: if ((ptr_dst == NULL || ptr_dst->data == NULL || prop_dst == NULL) || (ptr_src == NULL || ptr_src->data == NULL || prop_src == NULL)) { - BLI_assert(!"Missing data to apply override operation."); + BLI_assert_msg(0, "Missing data to apply override operation."); return false; } } @@ -2820,7 +2820,7 @@ void BKE_lib_override_library_update(Main *bmain, ID *local) local->tag |= LIB_TAG_OVERRIDE_LIBRARY_REFOK; - /* Note: Since we reload full content from linked ID here, potentially from edited local + /* NOTE: Since we reload full content from linked ID here, potentially from edited local * override, we do not really have a way to know *what* is changed, so we need to rely on the * massive destruction weapon of `ID_RECALC_ALL` here. */ DEG_id_tag_update_ex(bmain, local, ID_RECALC_ALL); @@ -2907,7 +2907,7 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain, * other-ID-reference creation/update in that case (since no differential operation is expected * to involve those anyway). */ #if 0 - /* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy + /* XXX TODO: We may also want a specialized handling of things here too, to avoid copying heavy * never-overridable data (like Mesh geometry etc.)? And also maybe avoid lib * reference-counting completely (shallow copy). */ /* This would imply change in handling of user-count all over RNA diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index 9d2552777bf..977e53c8474 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -273,7 +273,7 @@ static void library_foreach_ID_link(Main *bmain, continue; } - /* Note: ID.lib pointer is purposefully fully ignored here... + /* NOTE: ID.lib pointer is purposefully fully ignored here... * We may want to add it at some point? */ if (flag & IDWALK_DO_INTERNAL_RUNTIME_POINTERS) { diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index 2641208897e..bba15a3bcdf 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -126,7 +126,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) const bool is_reference = (cb_flag & IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE) != 0; const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0; const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0; - /* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct, + /* NOTE: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct, * on the other hand since they get reset to lib data on file open/reload it is indirect too. * Edit Mode is also a 'skip direct' case. */ const bool is_obj = (GS(id_owner->name) == ID_OB); @@ -312,7 +312,7 @@ static void libblock_remap_data_postprocess_collection_update(Main *bmain, /* XXX Complex cases can lead to NULL pointers in other collections than old_collection, * and BKE_main_collection_sync_remap() does not tolerate any of those, so for now always check * whole existing collections for NULL pointers. - * I'd consider optimizing that whole collection remapping process a TODO for later. */ + * I'd consider optimizing that whole collection remapping process a TODO: for later. */ BKE_collections_child_remove_nulls(bmain, owner_collection, NULL /*old_collection*/); } else { @@ -630,7 +630,7 @@ void BKE_libblock_relink_ex( switch (GS(id->name)) { case ID_SCE: case ID_GR: { - /* Note: here we know which collection we have affected, so at lest for NULL children + /* NOTE: here we know which collection we have affected, so at lest for NULL children * detection we can only process that one. * This is also a required fix in case `id` would not be in Main anymore, which can happen * e.g. when called from `id_delete`. */ diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 677b9497c98..07a3396ad5f 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -102,10 +102,10 @@ void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath) /* Not essential but set `filepath_abs` is an absolute copy of value which * is more useful if its kept in sync. */ if (BLI_path_is_rel(lib->filepath_abs)) { - /* note that the file may be unsaved, in this case, setting the + /* NOTE(campbell): the file may be unsaved, in this case, setting the * `filepath_abs` on an indirectly linked path is not allowed from the * outliner, and its not really supported but allow from here for now - * since making local could cause this to be directly linked - campbell + * since making local could cause this to be directly linked. */ /* Never make paths relative to parent lib - reading code (blenloader) always set *all* * `lib->filepath` relative to current main, not to their parent for indirectly linked ones. */ diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c index d872ecf7578..b09aed82921 100644 --- a/source/blender/blenkernel/intern/lightprobe.c +++ b/source/blender/blenkernel/intern/lightprobe.c @@ -131,7 +131,7 @@ void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type) probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID; break; default: - BLI_assert(!"LightProbe type not configured."); + BLI_assert_msg(0, "LightProbe type not configured."); break; } } diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c index 39cc5737ca2..655b6d3732c 100644 --- a/source/blender/blenkernel/intern/main.c +++ b/source/blender/blenkernel/intern/main.c @@ -400,7 +400,7 @@ ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data) } if (data) { - /* Note: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer, + /* NOTE: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer, * which will fail here (we do not want to pass the first two ints!). */ img = IMB_allocImBuf( (unsigned int)data->width, (unsigned int)data->height, 32, IB_rect | IB_metadata); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 371af2a95ed..34dd38164c2 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -69,7 +69,7 @@ static void mask_copy_data(Main *UNUSED(bmain), BLI_listbase_clear(&mask_dst->masklayers); - /* TODO add unused flag to those as well. */ + /* TODO: add unused flag to those as well. */ BKE_mask_layer_copy_list(&mask_dst->masklayers, &mask_src->masklayers); /* enable fake user by default */ @@ -342,7 +342,7 @@ MaskSplinePoint *BKE_mask_spline_point_array_from_point(MaskSpline *spline, return spline->points_deform; } - BLI_assert(!"wrong array"); + BLI_assert_msg(0, "wrong array"); return NULL; } @@ -372,7 +372,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name) return masklay; } -/* note: may still be hidden, caller needs to check */ +/* NOTE: may still be hidden, caller needs to check. */ MaskLayer *BKE_mask_layer_active(Mask *mask) { return BLI_findlink(&mask->masklayers, mask->masklay_act); @@ -707,7 +707,7 @@ void BKE_mask_point_handle(const MaskSplinePoint *point, copy_v2_v2(r_handle, bezt->vec[2]); } else { - BLI_assert(!"Unknown handle passed to BKE_mask_point_handle"); + BLI_assert_msg(0, "Unknown handle passed to BKE_mask_point_handle"); } } @@ -760,7 +760,7 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, copy_v2_v2(bezt->vec[2], loc); } else { - BLI_assert(!"unknown handle passed to BKE_mask_point_set_handle"); + BLI_assert_msg(0, "unknown handle passed to BKE_mask_point_set_handle"); } } @@ -1003,7 +1003,7 @@ void BKE_mask_point_select_set_handle(MaskSplinePoint *point, point->bezt.f3 |= SELECT; } else { - BLI_assert(!"Wrong which_handle passed to BKE_mask_point_select_set_handle"); + BLI_assert_msg(0, "Wrong which_handle passed to BKE_mask_point_select_set_handle"); } } else { @@ -1018,7 +1018,7 @@ void BKE_mask_point_select_set_handle(MaskSplinePoint *point, point->bezt.f3 &= ~SELECT; } else { - BLI_assert(!"Wrong which_handle passed to BKE_mask_point_select_set_handle"); + BLI_assert_msg(0, "Wrong which_handle passed to BKE_mask_point_select_set_handle"); } } } @@ -1133,7 +1133,7 @@ MaskSpline *BKE_mask_spline_copy(const MaskSpline *spline) return nspline; } -/* note: does NOT add to the list */ +/* NOTE: Does NOT add to the list. */ MaskLayerShape *BKE_mask_layer_shape_alloc(MaskLayer *masklay, const int frame) { MaskLayerShape *masklay_shape; @@ -1422,7 +1422,7 @@ void BKE_mask_get_handle_point_adjacent(MaskSpline *spline, MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next) { - /* TODO, could avoid calling this at such low level */ + /* TODO: could avoid calling this at such low level. */ MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); *r_point_prev = mask_spline_point_prev(spline, points_array, point); @@ -1472,7 +1472,7 @@ void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *point, const float u) { - /* TODO! - make this interpolate between siblings - not always midpoint! */ + /* TODO: make this interpolate between siblings - not always midpoint! */ int length_tot = 0; float length_average = 0.0f; float weight_average = 0.0f; @@ -1942,7 +1942,7 @@ void BKE_mask_layer_shape_changed_add(MaskLayer *masklay, int tot = BKE_mask_layer_shape_totvert(masklay) - 1; /* for interpolation */ - /* TODO - assumes closed curve for now */ + /* TODO: assumes closed curve for now. */ float uv[3][2]; /* 3x 2D handles */ const int pi_curr = spline_point_index; const int pi_prev = ((spline_point_index - 1) + spline->tot_point) % spline->tot_point; diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 69f60ca0384..4584d9e527e 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -545,7 +545,7 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__even( float u = (float)j / resol, weight; float co[2], n[2]; - /* TODO - these calls all calculate similar things + /* TODO: these calls all calculate similar things * could be unified for some speed */ BKE_mask_point_segment_co(spline, point_prev, u, co); BKE_mask_point_normal(spline, point_prev, u, n); @@ -691,7 +691,7 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__double float weight_uw, weight_scalar; float co[2]; - /* TODO - these calls all calculate similar things + /* TODO: these calls all calculate similar things * could be unified for some speed */ BKE_mask_point_segment_co(spline, point_prev, u, co); diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index d29a6e75954..81c161a4a7d 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -514,7 +514,7 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) BLI_assert(bucket_index < bucket_tot); /* Check if the bucket intersects with the face. */ - /* Note: there is a trade off here since checking box/tri intersections isn't as + /* NOTE: there is a trade off here since checking box/tri intersections isn't as * optimal as it could be, but checking pixels against faces they will never * intersect with is likely the greater slowdown here - * so check if the cell intersects the face. */ @@ -729,7 +729,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, sf_vert_tot++; - /* TODO, an alternate functions so we can avoid double vector copy! */ + /* TODO: an alternate functions so we can avoid double vector copy! */ for (j = 1; j < tot_diff_point; j++) { copy_v2_v2(co, diff_points[j]); sf_vert = BLI_scanfill_vert_add(&sf_ctx, co); @@ -762,7 +762,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, BLI_assert(tot_diff_feather_points == tot_diff_point); - /* Note: only added for convenience, we don't in fact use these to scan-fill, + /* NOTE: only added for convenience, we don't in fact use these to scan-fill, * only to create feather faces after scan-fill. */ for (j = 0; j < tot_diff_feather_points; j++) { copy_v2_v2(co_feather, diff_feather_points[j]); @@ -804,7 +804,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, open_spline_ranges[open_spline_index].vertex_offset = sf_vert_tot; open_spline_ranges[open_spline_index].vertex_total = tot_diff_point; - /* TODO, an alternate functions so we can avoid double vector copy! */ + /* TODO: an alternate functions so we can avoid double vector copy! */ for (j = 0; j < tot_diff_point; j++) { /* center vert */ @@ -937,7 +937,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, ListBase isect_remedgebase = {NULL, NULL}; /* now we have all the splines */ - face_coords = MEM_mallocN((sizeof(float[3])) * sf_vert_tot, "maskrast_face_coords"); + face_coords = MEM_mallocN(sizeof(float[3]) * sf_vert_tot, "maskrast_face_coords"); /* init bounds */ BLI_rctf_init_minmax(&bounds); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index c5060e16e4d..4f0b2a718ed 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -135,7 +135,7 @@ static void material_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const BLI_listbase_clear(&material_dst->gpumaterial); - /* TODO Duplicate Engine Settings and set runtime to NULL */ + /* TODO: Duplicate Engine Settings and set runtime to NULL. */ } static void material_free_data(ID *id) @@ -864,7 +864,7 @@ void BKE_object_material_resize(Main *bmain, Object *ob, const short totcol, boo ob->mat = newmatar; ob->matbits = newmatbits; } - /* XXX, why not realloc on shrink? - campbell */ + /* XXX(campbell): why not realloc on shrink? */ ob->totcol = totcol; if (ob->totcol && ob->actcol == 0) { @@ -1168,7 +1168,7 @@ void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, ID *data_e BKE_object_materials_test(bmain, ob_orig, data_orig); } -/* XXX - this calls many more update calls per object then are needed, could be optimized */ +/* XXX: this calls many more update calls per object then are needed, could be optimized. */ void BKE_object_material_array_assign(Main *bmain, struct Object *ob, struct Material ***matar, @@ -1823,7 +1823,7 @@ void BKE_material_copybuf_copy(Main *bmain, Material *ma) matcopybuf.preview = NULL; BLI_listbase_clear(&matcopybuf.gpumaterial); - /* TODO Duplicate Engine Settings and set runtime to NULL */ + /* TODO: Duplicate Engine Settings and set runtime to NULL. */ matcopied = 1; } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index f5d898e801b..6a2b56306d6 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -559,7 +559,7 @@ bool BKE_mball_minmax_ex( copy_v3_v3(centroid, &ml->x); } - /* TODO, non circle shapes cubes etc, probably nobody notices - campbell */ + /* TODO(campbell): non circle shapes cubes etc, probably nobody notices. */ for (int i = -1; i != 3; i += 2) { copy_v3_v3(vec, centroid); add_v3_fl(vec, scale_mb * i); diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 413cefd2271..760febaca91 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -1336,7 +1336,7 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje } /* untransformed Bounding Box of MetaElem */ - /* TODO, its possible the elem type has been changed and the exp* + /* TODO: its possible the elem type has been changed and the exp* * values can use a fallback. */ copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */ copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */ @@ -1438,7 +1438,7 @@ void BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBa build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb); /* Don't polygonize meta-balls with too high resolution (base mball too small) - * note: Eps was 0.0001f but this was giving problems for blood animation for + * NOTE: Eps was 0.0001f but this was giving problems for blood animation for * the open movie "Sintel", using 0.00001f. */ if (ob->scale[0] > 0.00001f * (process.allbb.max[0] - process.allbb.min[0]) || ob->scale[1] > 0.00001f * (process.allbb.max[1] - process.allbb.min[1]) || diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index b518f35fac7..b463d903303 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -39,6 +39,7 @@ #include "BLI_ghash.h" #include "BLI_hash.h" #include "BLI_linklist.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_string.h" @@ -125,6 +126,8 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int mesh_dst->mat = MEM_dupallocN(mesh_src->mat); + BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names); + const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, alloc_type, mesh_dst->totvert); CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, alloc_type, mesh_dst->totedge); @@ -143,7 +146,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int mesh_dst->mselect = MEM_dupallocN(mesh_dst->mselect); - /* TODO Do we want to add flag to prevent this? */ + /* TODO: Do we want to add flag to prevent this? */ if (mesh_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) { BKE_id_copy_ex(bmain, &mesh_src->key->id, (ID **)&mesh_dst->key, flag); /* XXX This is not nice, we need to make BKE_id_copy_ex fully re-entrant... */ @@ -155,6 +158,8 @@ static void mesh_free_data(ID *id) { Mesh *mesh = (Mesh *)id; + BLI_freelistN(&mesh->vertex_group_names); + BKE_mesh_runtime_clear_cache(mesh); mesh_clear_geometry(mesh); MEM_SAFE_FREE(mesh->mat); @@ -229,6 +234,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address BKE_animdata_blend_write(writer, mesh->adt); } + BKE_defbase_blend_write(writer, &mesh->vertex_group_names); + BLO_write_pointer_array(writer, mesh->totcol, mesh->mat); BLO_write_raw(writer, sizeof(MSelect) * mesh->totselect, mesh->mselect); @@ -288,6 +295,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) /* Normally BKE_defvert_blend_read should be called in CustomData_blend_read, * but for backwards compatibility in do_versions to work we do it here. */ BKE_defvert_blend_read(reader, mesh->totvert, mesh->dvert); + BLO_read_list(reader, &mesh->vertex_group_names); CustomData_blend_read(reader, &mesh->vdata, mesh->totvert); CustomData_blend_read(reader, &mesh->edata, mesh->totedge); @@ -304,7 +312,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) mesh->totselect = 0; } - if ((BLO_read_requires_endian_switch(reader)) && mesh->tface) { + if (BLO_read_requires_endian_switch(reader) && mesh->tface) { TFace *tf = mesh->tface; for (int i = 0; i < mesh->totface; i++, tf++) { BLI_endian_switch_uint32_array(tf->col, 4); @@ -657,12 +665,12 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) CustomData_from_bmeshpoly(&me->fdata, &me->ldata, me->totface); - /* TODO - add some --debug-mesh option */ + /* TODO: add some `--debug-mesh` option. */ if (G.debug & G_DEBUG) { - /* note: this warning may be un-called for if we are initializing the mesh for the - * first time from bmesh, rather than giving a warning about this we could be smarter + /* NOTE(campbell): this warning may be un-called for if we are initializing the mesh for + * the first time from #BMesh, rather than giving a warning about this we could be smarter * and check if there was any data to begin with, for now just print the warning with - * some info to help troubleshoot what's going on - campbell */ + * some info to help troubleshoot what's going on. */ printf( "%s: warning! Tessellation uvs or vcol data got out of sync, " "had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: " @@ -923,6 +931,8 @@ void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src) me_dst->texflag = me_src->texflag; copy_v3_v3(me_dst->loc, me_src->loc); copy_v3_v3(me_dst->size, me_src->size); + + me_dst->vertex_group_active_index = me_src->vertex_group_active_index; } /** @@ -938,6 +948,10 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src) BKE_mesh_copy_parameters(me_dst, me_src); + /* Copy vertex group names. */ + BLI_assert(BLI_listbase_is_empty(&me_dst->vertex_group_names)); + BKE_defgroup_copy_list(&me_dst->vertex_group_names, &me_src->vertex_group_names); + /* Copy materials. */ if (me_dst->mat != NULL) { MEM_freeN(me_dst->mat); @@ -2126,7 +2140,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) } } - /* Note: after this point mesh is expected to be valid again. */ + /* NOTE: after this point mesh is expected to be valid again. */ /* CD_NORMAL is expected to be temporary only. */ if (free_loop_normals) { diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index c162458ffb9..798d9562150 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -38,6 +38,7 @@ #include "BLI_mesh_boolean.hh" #include "BLI_mesh_intersect.hh" #include "BLI_span.hh" +#include "BLI_task.hh" namespace blender::meshintersect { @@ -309,22 +310,38 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes, clean_obmat(*obmats[mi]); r_info->to_target_transform[mi] = inv_target_mat * objn_mat; - /* Skip the matrix multiplication for each point when there is no transform for a mesh, - * for example when the first mesh is already in the target space. (Note the logic directly - * above, which uses an identity matrix with a null input transform). */ + Vector<Vert *> verts(me->totvert); + Span<MVert> mverts = Span(me->mvert, me->totvert); + + /* Allocate verts + * Skip the matrix multiplication for each point when there is no transform for a mesh, + * for example when the first mesh is already in the target space. (Note the logic + * directly above, which uses an identity matrix with a null input transform). */ if (obmats[mi] == nullptr) { - for (const MVert &vert : Span(me->mvert, me->totvert)) { - const float3 co = float3(vert.co); - r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co.x, co.y, co.z), v); - ++v; - } + threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) { + float3 co; + for (int i : range) { + co = float3(mverts[i].co); + mpq3 mco = mpq3(co.x, co.y, co.z); + double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d()); + verts[i] = new Vert(mco, dco, NO_INDEX, i); + } + }); } else { - for (const MVert &vert : Span(me->mvert, me->totvert)) { - const float3 co = r_info->to_target_transform[mi] * float3(vert.co); - r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co.x, co.y, co.z), v); - ++v; - } + threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) { + float3 co; + for (int i : range) { + co = r_info->to_target_transform[mi] * float3(mverts[i].co); + mpq3 mco = mpq3(co.x, co.y, co.z); + double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d()); + verts[i] = new Vert(mco, dco, NO_INDEX, i); + } + }); + } + for (int i : mverts.index_range()) { + r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(verts[i]); + ++v; } for (const MPoly &poly : Span(me->mpoly, me->totpoly)) { @@ -611,7 +628,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, source_cd, target_cd, source_layer_i, target_layer_i, orig_loop_index, loop_index, 1); } else { - /* Note: although CustomData_bmesh_interp_n function has bmesh in its name, nothing about + /* NOTE: although CustomData_bmesh_interp_n function has bmesh in its name, nothing about * it is BMesh-specific. We can't use CustomData_interp because it assumes that * all source layers exist in the dest. * A non bmesh version could have the benefit of not copying data into src_blocks_ofs - diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index cfad5e1100d..e777eb7ffe9 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1117,7 +1117,7 @@ static void curve_to_mesh_eval_ensure(Object *object) BKE_displist_make_curveTypes_forRender( NULL, NULL, &remapped_object, &remapped_object.runtime.curve_cache->disp, &mesh_eval); - /* Note: this is to be consistent with `BKE_displist_make_curveTypes()`, however that is not a + /* NOTE: this is to be consistent with `BKE_displist_make_curveTypes()`, however that is not a * real issue currently, code here is broken in more than one way, fix(es) will be done * separately. */ if (mesh_eval != NULL) { @@ -1327,7 +1327,7 @@ static int foreach_libblock_make_usercounts_callback(LibraryIDLinkCallbackData * id_us_plus(*id_p); } else if (cb_flag & IDWALK_CB_USER_ONE) { - /* Note: in that context, that one should not be needed (since there should be at least already + /* NOTE: in that context, that one should not be needed (since there should be at least already * one USER_ONE user of that ID), but better be consistent. */ id_us_ensure_real(*id_p); } @@ -1668,7 +1668,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, } /* object had got displacement layer, should copy this layer to save sculpted data */ - /* NOTE: maybe some other layers should be copied? nazgul */ + /* NOTE(nazgul): maybe some other layers should be copied? */ if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) { if (totloop == mesh_dst->totloop) { MDisps *mdisps = CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS); diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.cc index 6eac96ba85b..91fd022a316 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.cc @@ -23,7 +23,7 @@ * Functions to evaluate mesh data. */ -#include <limits.h> +#include <climits> #include "MEM_guardedalloc.h" @@ -191,7 +191,7 @@ void BKE_mesh_calc_poly_center(const MPoly *mpoly, } } -/* note, passing polynormal is only a speedup so we can skip calculating it */ +/* NOTE: passing poly-normal is only a speedup so we can skip calculating it. */ float BKE_mesh_calc_poly_area(const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray) { if (mpoly->totloop == 3) { @@ -200,7 +200,7 @@ float BKE_mesh_calc_poly_area(const MPoly *mpoly, const MLoop *loopstart, const } const MLoop *l_iter = loopstart; - float(*vertexcos)[3] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop); + float(*vertexcos)[3] = (float(*)[3])BLI_array_alloca(vertexcos, (size_t)mpoly->totloop); /* pack vertex cos into an array for area_poly_v3 */ for (int i = 0; i < mpoly->totloop; i++, l_iter++) { @@ -236,7 +236,7 @@ float BKE_mesh_calc_poly_uv_area(const MPoly *mpoly, const MLoopUV *uv_array) int i, l_iter = mpoly->loopstart; float area; - float(*vertexcos)[2] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop); + float(*vertexcos)[2] = (float(*)[2])BLI_array_alloca(vertexcos, (size_t)mpoly->totloop); /* pack vertex cos into an array for area_poly_v2 */ for (i = 0; i < mpoly->totloop; i++, l_iter++) { @@ -404,7 +404,7 @@ void BKE_mesh_poly_edgehash_insert(EdgeHash *ehash, const MPoly *mp, const MLoop ml = &ml_next[i - 1]; /* last loop */ while (i-- != 0) { - BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, NULL); + BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, nullptr); ml = ml_next; ml_next++; @@ -656,7 +656,7 @@ void BKE_mesh_calc_volume(const MVert *mverts, } } - /* Note: Depending on arbitrary centroid position, + /* NOTE: Depending on arbitrary centroid position, * totvol can become negative even for a valid mesh. * The true value is always the positive value. */ @@ -664,7 +664,7 @@ void BKE_mesh_calc_volume(const MVert *mverts, *r_volume = fabsf(totvol); } if (r_center) { - /* Note: Factor 1/3 is applied once for all vertices here. + /* NOTE: Factor 1/3 is applied once for all vertices here. * This also automatically negates the vector if totvol is negative. */ if (totvol != 0.0f) { @@ -676,7 +676,7 @@ void BKE_mesh_calc_volume(const MVert *mverts, /** \} */ /* -------------------------------------------------------------------- */ -/** \name NGon Tessellation (NGon/Tessface Conversion) +/** \name NGon Tessellation (NGon to MFace Conversion) * \{ */ static void bm_corners_to_loops_ex(ID *id, @@ -692,9 +692,9 @@ static void bm_corners_to_loops_ex(ID *id, MFace *mf = mface + findex; for (int i = 0; i < numTex; i++) { - MTFace *texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); + MTFace *texface = (MTFace *)CustomData_get_n(fdata, CD_MTFACE, findex, i); - MLoopUV *mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i); + MLoopUV *mloopuv = (MLoopUV *)CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i); copy_v2_v2(mloopuv->uv, texface->uv[0]); mloopuv++; copy_v2_v2(mloopuv->uv, texface->uv[1]); @@ -709,8 +709,8 @@ static void bm_corners_to_loops_ex(ID *id, } for (int i = 0; i < numCol; i++) { - MLoopCol *mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i); - MCol *mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); + MLoopCol *mloopcol = (MLoopCol *)CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i); + MCol *mcol = (MCol *)CustomData_get_n(fdata, CD_MCOL, findex, i); MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]); mloopcol++; @@ -725,8 +725,8 @@ static void bm_corners_to_loops_ex(ID *id, } if (CustomData_has_layer(fdata, CD_TESSLOOPNORMAL)) { - float(*lnors)[3] = CustomData_get(ldata, loopstart, CD_NORMAL); - short(*tlnors)[3] = CustomData_get(fdata, findex, CD_TESSLOOPNORMAL); + float(*lnors)[3] = (float(*)[3])CustomData_get(ldata, loopstart, CD_NORMAL); + short(*tlnors)[3] = (short(*)[3])CustomData_get(fdata, findex, CD_TESSLOOPNORMAL); const int max = mf->v4 ? 4 : 3; for (int i = 0; i < max; i++, lnors++, tlnors++) { @@ -735,8 +735,8 @@ static void bm_corners_to_loops_ex(ID *id, } if (CustomData_has_layer(fdata, CD_MDISPS)) { - MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS); - MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS); + MDisps *ld = (MDisps *)CustomData_get(ldata, loopstart, CD_MDISPS); + MDisps *fd = (MDisps *)CustomData_get(fdata, findex, CD_MDISPS); float(*disps)[3] = fd->disps; int tot = mf->v4 ? 4 : 3; int corners; @@ -750,9 +750,9 @@ static void bm_corners_to_loops_ex(ID *id, corners = multires_mdisp_corners(fd); if (corners == 0) { - /* Empty MDisp layers appear in at least one of the sintel.blend files. + /* Empty #MDisp layers appear in at least one of the `sintel.blend` files. * Not sure why this happens, but it seems fine to just ignore them here. - * If (corners == 0) for a non-empty layer though, something went wrong. */ + * If `corners == 0` for a non-empty layer though, something went wrong. */ BLI_assert(fd->totdisp == 0); } else { @@ -767,7 +767,8 @@ static void bm_corners_to_loops_ex(ID *id, MEM_freeN(ld->disps); } - ld->disps = MEM_malloc_arrayN((size_t)side_sq, sizeof(float[3]), "converted loop mdisps"); + ld->disps = (float(*)[3])MEM_malloc_arrayN( + (size_t)side_sq, sizeof(float[3]), "converted loop mdisps"); if (fd->disps) { memcpy(ld->disps, disps, (size_t)side_sq * sizeof(float[3])); } @@ -801,15 +802,16 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) /** * The same as #BKE_mesh_convert_mfaces_to_mpolys - * but oriented to be used in #do_versions from readfile.c - * the difference is how active/render/clone/stencil indices are handled here + * but oriented to be used in #do_versions from `readfile.c` + * the difference is how active/render/clone/stencil indices are handled here. * - * normally thay're being set from pdata which totally makes sense for meshes which are already - * converted to bmesh structures, but when loading older files indices shall be updated in other - * way around, so newly added pdata and ldata would have this indices set based on fdata layer + * normally they're being set from `pdata` which totally makes sense for meshes which are already + * converted to #BMesh structures, but when loading older files indices shall be updated in other + * way around, so newly added `pdata` and `ldata` would have this indices set + * based on `fdata` layer. * * this is normally only needed when reading older files, - * in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used + * in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used. */ void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh) { @@ -864,7 +866,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData_free(pdata, totpoly_i); totpoly = totface_i; - mpoly = MEM_calloc_arrayN((size_t)totpoly, sizeof(MPoly), "mpoly converted"); + mpoly = (MPoly *)MEM_calloc_arrayN((size_t)totpoly, sizeof(MPoly), "mpoly converted"); CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly); numTex = CustomData_number_of_layers(fdata, CD_MTFACE); @@ -876,7 +878,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, totloop += mf->v4 ? 4 : 3; } - mloop = MEM_calloc_arrayN((size_t)totloop, sizeof(MLoop), "mloop converted"); + mloop = (MLoop *)MEM_calloc_arrayN((size_t)totloop, sizeof(MLoop), "mloop converted"); CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop); @@ -900,7 +902,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, me->flag &= ~ME_FGON; } - polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX); + polyindex = (int *)CustomData_get_layer(fdata, CD_ORIGINDEX); j = 0; /* current loop index */ ml = mloop; @@ -943,10 +945,10 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, } } - /* note, we don't convert NGons at all, these are not even real ngons, + /* NOTE: we don't convert NGons at all, these are not even real ngons, * they have their own UV's, colors etc - its more an editing feature. */ - BLI_edgehash_free(eh, NULL); + BLI_edgehash_free(eh, nullptr); *r_totpoly = totpoly; *r_totloop = totloop; @@ -1050,8 +1052,8 @@ void BKE_mesh_polygon_flip_ex(MPoly *mpoly, void BKE_mesh_polygon_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata) { - MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS); - BKE_mesh_polygon_flip_ex(mpoly, mloop, ldata, NULL, mdisp, true); + MDisps *mdisp = (MDisps *)CustomData_get_layer(ldata, CD_MDISPS); + BKE_mesh_polygon_flip_ex(mpoly, mloop, ldata, nullptr, mdisp, true); } /** @@ -1061,12 +1063,12 @@ void BKE_mesh_polygon_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata) */ void BKE_mesh_polygons_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata, int totpoly) { - MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS); + MDisps *mdisp = (MDisps *)CustomData_get_layer(ldata, CD_MDISPS); MPoly *mp; int i; for (mp = mpoly, i = 0; i < totpoly; mp++, i++) { - BKE_mesh_polygon_flip_ex(mp, mloop, ldata, NULL, mdisp, true); + BKE_mesh_polygon_flip_ex(mp, mloop, ldata, nullptr, mdisp, true); } } @@ -1277,7 +1279,7 @@ void BKE_mesh_calc_relative_deform(const MPoly *mpoly, const MPoly *mp; int i; - int *vert_accum = MEM_calloc_arrayN((size_t)totvert, sizeof(*vert_accum), __func__); + int *vert_accum = (int *)MEM_calloc_arrayN((size_t)totvert, sizeof(*vert_accum), __func__); memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * (size_t)totvert); diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index c469a65449d..ca6c60557a6 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -776,7 +776,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, } if (UNLIKELY(gid_bit > 31)) { /* All bits used in contiguous smooth groups, we can't do much! - * Note: this is *very* unlikely - theoretically, four groups are enough, + * NOTE: this is *very* unlikely - theoretically, four groups are enough, * I don't think we can reach this goal with such a simple algorithm, * but I don't think either we'll never need all 32 groups! */ @@ -998,7 +998,7 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store, } /* TODO: I'm not sure edge seam flag is enough to define UV islands? - * Maybe we should also consider UVmaps values + * Maybe we should also consider UV-maps values * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?). * Would make things much more complex though, * and each UVMap would then need its own mesh mapping, not sure we want that at all! @@ -1140,7 +1140,7 @@ static bool mesh_calc_islands_loop_poly_uv(MVert *UNUSED(verts), poly_indices = MEM_mallocN(sizeof(*poly_indices) * (size_t)totpoly, __func__); loop_indices = MEM_mallocN(sizeof(*loop_indices) * (size_t)totloop, __func__); - /* Note: here we ignore '0' invalid group - this should *never* happen in this case anyway? */ + /* NOTE: here we ignore '0' invalid group - this should *never* happen in this case anyway? */ for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) { num_pidx = num_lidx = 0; if (num_edge_borders) { diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c index 1e51ee73c7c..d3d835378ca 100644 --- a/source/blender/blenkernel/intern/mesh_merge.c +++ b/source/blender/blenkernel/intern/mesh_merge.c @@ -259,7 +259,7 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh, STACK_DECLARE(mvert); STACK_DECLARE(oldv); - /* Note: create (totedge + totloop) elements because partially invalid polys due to merge may + /* NOTE: create (totedge + totloop) elements because partially invalid polys due to merge may * require generating new edges, and while in 99% cases we'll still end with less final edges * than totedge, cases can be forged that would end requiring more. */ MEdge *med, *medge = MEM_malloc_arrayN((totedge + totloop), sizeof(*medge), __func__); diff --git a/source/blender/blenkernel/intern/mesh_normals.c b/source/blender/blenkernel/intern/mesh_normals.cc index 9f09ce46e11..2fe132fc684 100644 --- a/source/blender/blenkernel/intern/mesh_normals.c +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -25,7 +25,7 @@ * \see bmesh_mesh_normals.c for the equivalent #BMesh functionality. */ -#include <limits.h> +#include <climits> #include "CLG_log.h" @@ -90,15 +90,15 @@ void BKE_mesh_calc_normals_mapping_simple(struct Mesh *mesh) mesh->mpoly, mesh->totloop, mesh->totpoly, - NULL, + nullptr, mesh->mface, mesh->totface, - NULL, - NULL, + nullptr, + nullptr, only_face_normals); } -/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-NULL +/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-nullptr * and vertex normals are stored in actual mverts. */ void BKE_mesh_calc_normals_mapping(MVert *mverts, @@ -150,13 +150,13 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, } /* if we are not calculating verts and no verts were passes then we have nothing to do */ - if ((only_face_normals == true) && (r_polyNors == NULL) && (r_faceNors == NULL)) { + if ((only_face_normals == true) && (r_polyNors == nullptr) && (r_faceNors == nullptr)) { CLOG_WARN(&LOG, "called with nothing to do"); return; } if (!pnors) { - pnors = MEM_calloc_arrayN((size_t)numPolys, sizeof(float[3]), __func__); + pnors = (float(*)[3])MEM_calloc_arrayN((size_t)numPolys, sizeof(float[3]), __func__); } /* NO NEED TO ALLOC YET */ /* if (!fnors) fnors = MEM_calloc_arrayN(numFaces, sizeof(float[3]), "face nors mesh.c"); */ @@ -165,7 +165,7 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, /* vertex normals are optional, they require some extra calculations, * so make them optional */ BKE_mesh_calc_normals_poly( - mverts, NULL, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false); + mverts, nullptr, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false); } else { /* only calc poly normals */ @@ -177,7 +177,7 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, if (origIndexFace && /* fnors == r_faceNors */ /* NO NEED TO ALLOC YET */ - fnors != NULL && + fnors != nullptr && numFaces) { const MFace *mf = mfaces; for (int i = 0; i < numFaces; i++, mf++, origIndexFace++) { @@ -196,23 +196,23 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, } /* if (fnors != r_faceNors) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */ - fnors = pnors = NULL; + fnors = pnors = nullptr; } -typedef struct MeshCalcNormalsData { +struct MeshCalcNormalsData { const MPoly *mpolys; const MLoop *mloop; MVert *mverts; float (*pnors)[3]; float (*lnors_weighted)[3]; float (*vnors)[3]; -} MeshCalcNormalsData; +}; static void mesh_calc_normals_poly_cb(void *__restrict userdata, const int pidx, const TaskParallelTLS *__restrict UNUSED(tls)) { - MeshCalcNormalsData *data = userdata; + MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata; const MPoly *mp = &data->mpolys[pidx]; BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]); @@ -222,7 +222,7 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata, const int pidx, const TaskParallelTLS *__restrict UNUSED(tls)) { - MeshCalcNormalsData *data = userdata; + MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata; const MPoly *mp = &data->mpolys[pidx]; const MLoop *ml = &data->mloop[mp->loopstart]; const MVert *mverts = data->mverts; @@ -232,7 +232,7 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata, float(*lnors_weighted)[3] = data->lnors_weighted; const int nverts = mp->totloop; - float(*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, (size_t)nverts); + float(*edgevecbuf)[3] = (float(*)[3])BLI_array_alloca(edgevecbuf, (size_t)nverts); /* Polygon Normal and edge-vector */ /* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */ @@ -285,7 +285,7 @@ static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata, const int vidx, const TaskParallelTLS *__restrict UNUSED(tls)) { - MeshCalcNormalsData *data = userdata; + MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata; MVert *mv = &data->mverts[vidx]; float *no = data->vnors[vidx]; @@ -315,42 +315,40 @@ void BKE_mesh_calc_normals_poly(MVert *mverts, settings.min_iter_per_thread = 1024; if (only_face_normals) { - BLI_assert((pnors != NULL) || (numPolys == 0)); - BLI_assert(r_vertnors == NULL); - - MeshCalcNormalsData data = { - .mpolys = mpolys, - .mloop = mloop, - .mverts = mverts, - .pnors = pnors, - }; + BLI_assert((pnors != nullptr) || (numPolys == 0)); + BLI_assert(r_vertnors == nullptr); + + MeshCalcNormalsData data; + data.mpolys = mpolys; + data.mloop = mloop; + data.mverts = mverts; + data.pnors = pnors; BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_cb, &settings); return; } float(*vnors)[3] = r_vertnors; - float(*lnors_weighted)[3] = MEM_malloc_arrayN( + float(*lnors_weighted)[3] = (float(*)[3])MEM_malloc_arrayN( (size_t)numLoops, sizeof(*lnors_weighted), __func__); bool free_vnors = false; /* first go through and calculate normals for all the polys */ - if (vnors == NULL) { - vnors = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__); + if (vnors == nullptr) { + vnors = (float(*)[3])MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__); free_vnors = true; } else { memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts); } - MeshCalcNormalsData data = { - .mpolys = mpolys, - .mloop = mloop, - .mverts = mverts, - .pnors = pnors, - .lnors_weighted = lnors_weighted, - .vnors = vnors, - }; + MeshCalcNormalsData data; + data.mpolys = mpolys; + data.mloop = mloop; + data.mverts = mverts; + data.pnors = pnors; + data.lnors_weighted = lnors_weighted; + data.vnors = vnors; /* Compute poly normals, and prepare weighted loop normals. */ BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings); @@ -400,19 +398,21 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh) } } - float(*poly_nors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL); + float(*poly_nors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL); const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0; - const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || poly_nors == NULL); + const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || + poly_nors == nullptr); if (do_vert_normals || do_poly_normals) { - const bool do_add_poly_nors_cddata = (poly_nors == NULL); + const bool do_add_poly_nors_cddata = (poly_nors == nullptr); if (do_add_poly_nors_cddata) { - poly_nors = MEM_malloc_arrayN((size_t)mesh->totpoly, sizeof(*poly_nors), __func__); + poly_nors = (float(*)[3])MEM_malloc_arrayN( + (size_t)mesh->totpoly, sizeof(*poly_nors), __func__); } /* calculate poly/vert normals */ BKE_mesh_calc_normals_poly(mesh->mvert, - NULL, + nullptr, mesh->totvert, mesh->mloop, mesh->mpoly, @@ -438,13 +438,13 @@ void BKE_mesh_calc_normals(Mesh *mesh) TIMEIT_START_AVERAGED(BKE_mesh_calc_normals); #endif BKE_mesh_calc_normals_poly(mesh->mvert, - NULL, + nullptr, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, - NULL, + nullptr, false); #ifdef DEBUG_TIME TIMEIT_END_AVERAGED(BKE_mesh_calc_normals); @@ -459,10 +459,10 @@ void BKE_mesh_calc_normals_looptri(MVert *mverts, int looptri_num, float (*r_tri_nors)[3]) { - float(*tnorms)[3] = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms"); - float(*fnors)[3] = (r_tri_nors) ? - r_tri_nors : - MEM_calloc_arrayN((size_t)looptri_num, sizeof(*fnors), "meshnormals"); + float(*tnorms)[3] = (float(*)[3])MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms"); + float(*fnors)[3] = (r_tri_nors) ? r_tri_nors : + (float(*)[3])MEM_calloc_arrayN( + (size_t)looptri_num, sizeof(*fnors), "meshnormals"); if (!tnorms || !fnors) { goto cleanup; @@ -519,9 +519,10 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, lnors_spacearr->mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); } mem = lnors_spacearr->mem; - lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, - sizeof(MLoopNorSpace *) * (size_t)numLoops); - lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops); + lnors_spacearr->lspacearr = (MLoopNorSpace **)BLI_memarena_calloc( + mem, sizeof(MLoopNorSpace *) * (size_t)numLoops); + lnors_spacearr->loops_pool = (LinkNode *)BLI_memarena_alloc( + mem, sizeof(LinkNode) * (size_t)numLoops); lnors_spacearr->num_spaces = 0; } @@ -532,9 +533,9 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr) { lnors_spacearr->num_spaces = 0; - lnors_spacearr->lspacearr = NULL; - lnors_spacearr->loops_pool = NULL; - if (lnors_spacearr->mem != NULL) { + lnors_spacearr->lspacearr = nullptr; + lnors_spacearr->loops_pool = nullptr; + if (lnors_spacearr->mem != nullptr) { BLI_memarena_clear(lnors_spacearr->mem); } } @@ -542,16 +543,16 @@ void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr) void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr) { lnors_spacearr->num_spaces = 0; - lnors_spacearr->lspacearr = NULL; - lnors_spacearr->loops_pool = NULL; + lnors_spacearr->lspacearr = nullptr; + lnors_spacearr->loops_pool = nullptr; BLI_memarena_free(lnors_spacearr->mem); - lnors_spacearr->mem = NULL; + lnors_spacearr->mem = nullptr; } MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr) { lnors_spacearr->num_spaces++; - return BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace)); + return (MLoopNorSpace *)BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace)); } /* This threshold is a bit touchy (usual float precision issue), this value seems OK. */ @@ -592,12 +593,12 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space, float alpha = 0.0f; int nbr = 0; while (!BLI_stack_is_empty(edge_vectors)) { - const float *vec = BLI_stack_peek(edge_vectors); + const float *vec = (const float *)BLI_stack_peek(edge_vectors); alpha += saacosf(dot_v3v3(vec, lnor)); BLI_stack_discard(edge_vectors); nbr++; } - /* Note: In theory, this could be 'nbr > 2', + /* NOTE: In theory, this could be 'nbr > 2', * but there is one case where we only have two edges for two loops: * a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.). */ @@ -637,10 +638,10 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space, /** * Add a new given loop to given lnor_space. * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct - * (in case of BMLOOP_PTR), or NULL (in case of LOOP_INDEX), loop index is then stored in pointer. - * If \a is_single is set, the BMLoop or loop index is directly stored in \a lnor_space->loops - * pointer (since there is only one loop in this fan), - * else it is added to the linked list of loops in the fan. + * (in case of BMLOOP_PTR), or nullptr (in case of LOOP_INDEX), loop index is then stored in + * pointer. If \a is_single is set, the BMLoop or loop index is directly stored in \a + * lnor_space->loops pointer (since there is only one loop in this fan), else it is added to the + * linked list of loops in the fan. */ void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, @@ -648,17 +649,17 @@ void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, void *bm_loop, const bool is_single) { - BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == NULL) || - (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != NULL)); + BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == nullptr) || + (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != nullptr)); lnors_spacearr->lspacearr[ml_index] = lnor_space; - if (bm_loop == NULL) { + if (bm_loop == nullptr) { bm_loop = POINTER_FROM_INT(ml_index); } if (is_single) { - BLI_assert(lnor_space->loops == NULL); + BLI_assert(lnor_space->loops == nullptr); lnor_space->flags |= MLNOR_SPACE_IS_SINGLE; - lnor_space->loops = bm_loop; + lnor_space->loops = (LinkNode *)bm_loop; } else { BLI_assert((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0); @@ -688,8 +689,8 @@ void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, } { - /* TODO Check whether using sincosf() gives any noticeable benefit - * (could not even get it working under linux though)! */ + /* TODO: Check whether using #sincosf() gives any noticeable benefit + * (could not even get it working under linux though)! */ const float pi2 = (float)(M_PI * 2.0); const float alphafac = unit_short_to_float(clnor_data[0]); const float alpha = (alphafac > 0.0f ? lnor_space->ref_alpha : pi2 - lnor_space->ref_alpha) * @@ -715,7 +716,8 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float custom_lnor[3], short r_clnor_data[2]) { - /* We use null vector as NOP custom normal (can be simpler than giving auto-computed `lnor`). */ + /* We use nullptr vector as NOP custom normal (can be simpler than giving auto-computed `lnor`). + */ if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_space->vec_lnor, custom_lnor, 1e-4f)) { r_clnor_data[0] = r_clnor_data[1] = 0; return; @@ -765,7 +767,7 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, #define LOOP_SPLIT_TASK_BLOCK_SIZE 1024 -typedef struct LoopSplitTaskData { +struct LoopSplitTaskData { /* Specific to each instance (each task). */ /** We have to create those outside of tasks, since #MemArena is not thread-safe. */ @@ -784,9 +786,9 @@ typedef struct LoopSplitTaskData { BLI_Stack *edge_vectors; char pad_c; -} LoopSplitTaskData; +}; -typedef struct LoopSplitTaskDataCommon { +struct LoopSplitTaskDataCommon { /* Read/write. * Note we do not need to protect it, though, since two different tasks will *always* affect * different elements in the arrays. */ @@ -806,7 +808,7 @@ typedef struct LoopSplitTaskDataCommon { int numEdges; int numLoops; int numPolys; -} LoopSplitTaskDataCommon; +}; #define INDEX_UNSET INT_MIN #define INDEX_INVALID -1 @@ -827,13 +829,13 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data, const int numEdges = data->numEdges; const int numPolys = data->numPolys; - float(*loopnors)[3] = data->loopnors; /* Note: loopnors may be NULL here. */ + float(*loopnors)[3] = data->loopnors; /* NOTE: loopnors may be nullptr here. */ const float(*polynors)[3] = data->polynors; int(*edge_to_loops)[2] = data->edge_to_loops; int *loop_to_poly = data->loop_to_poly; - BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : NULL; + BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : nullptr; const MPoly *mp; int mp_index; @@ -879,7 +881,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data, */ if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) || ml_curr->v == mloops[e2l[0]].v || is_angle_sharp) { - /* Note: we are sure that loop != 0 here ;) */ + /* NOTE: we are sure that loop != 0 here ;). */ e2l[1] = INDEX_INVALID; /* We want to avoid tagging edges as sharp when it is already defined as such by @@ -943,22 +945,22 @@ void BKE_edges_sharp_from_angle_set(const struct MVert *mverts, } /* Mapping edge -> loops. See BKE_mesh_normals_loop_split() for details. */ - int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__); + int(*edge_to_loops)[2] = (int(*)[2])MEM_calloc_arrayN( + (size_t)numEdges, sizeof(*edge_to_loops), __func__); /* Simple mapping from a loop to its polygon index. */ - int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); - - LoopSplitTaskDataCommon common_data = { - .mverts = mverts, - .medges = medges, - .mloops = mloops, - .mpolys = mpolys, - .edge_to_loops = edge_to_loops, - .loop_to_poly = loop_to_poly, - .polynors = polynors, - .numEdges = numEdges, - .numPolys = numPolys, - }; + int *loop_to_poly = (int *)MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); + + LoopSplitTaskDataCommon common_data; + common_data.mverts = mverts; + common_data.medges = medges; + common_data.mloops = mloops; + common_data.mpolys = mpolys; + common_data.edge_to_loops = edge_to_loops; + common_data.loop_to_poly = loop_to_poly; + common_data.polynors = polynors; + common_data.numEdges = numEdges; + common_data.numPolys = numPolys; mesh_edges_sharp_tag(&common_data, true, split_angle, true); @@ -1065,10 +1067,10 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS sub_v3_v3v3(vec_prev, mv_3->co, mv_pivot->co); normalize_v3(vec_prev); - BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL); + BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, nullptr); /* We know there is only one loop in this space, * no need to create a linklist in this case... */ - BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, NULL, true); + BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, nullptr, true); if (clnors_data) { BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor); @@ -1125,7 +1127,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli /* We validate clnors data on the fly - cheapest way to do! */ int clnors_avg[2] = {0, 0}; - short(*clnor_ref)[2] = NULL; + short(*clnor_ref)[2] = nullptr; int clnors_nbr = 0; bool clnors_invalid = false; @@ -1205,7 +1207,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli if (lnors_spacearr) { /* Assign current lnor space to current 'vertex' loop. */ - BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, NULL, false); + BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, nullptr, false); if (me_curr != me_org) { /* We store here all edges-normalized vectors processed. */ BLI_stack_push(edge_vectors, vec_curr); @@ -1261,7 +1263,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli if (G.debug & G_DEBUG) { printf("Invalid clnors in this fan!\n"); } - while ((clnor = BLI_SMALLSTACK_POP(clnors))) { + while ((clnor = (short *)BLI_SMALLSTACK_POP(clnors))) { // print_v2("org clnor", clnor); clnor[0] = (short)clnors_avg[0]; clnor[1] = (short)clnors_avg[1]; @@ -1280,7 +1282,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli /* Copy back the final computed normal into all related loop-normals. */ float *nor; - while ((nor = BLI_SMALLSTACK_POP(normal))) { + while ((nor = (float *)BLI_SMALLSTACK_POP(normal))) { copy_v3_v3(nor, lnor); } } @@ -1295,7 +1297,7 @@ static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data, { BLI_assert(data->ml_curr); if (data->e2l_prev) { - BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors)); + BLI_assert((edge_vectors == nullptr) || BLI_stack_is_empty(edge_vectors)); data->edge_vectors = edge_vectors; split_loop_nor_fan_do(common_data, data); } @@ -1307,21 +1309,21 @@ static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data, static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) { - LoopSplitTaskDataCommon *common_data = BLI_task_pool_user_data(pool); - LoopSplitTaskData *data = taskdata; + LoopSplitTaskDataCommon *common_data = (LoopSplitTaskDataCommon *)BLI_task_pool_user_data(pool); + LoopSplitTaskData *data = (LoopSplitTaskData *)taskdata; /* Temp edge vectors stack, only used when computing lnor spacearr. */ BLI_Stack *edge_vectors = common_data->lnors_spacearr ? BLI_stack_new(sizeof(float[3]), __func__) : - NULL; + nullptr; #ifdef DEBUG_TIME TIMEIT_START_AVERAGED(loop_split_worker); #endif for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) { - /* A NULL ml_curr is used to tag ended data! */ - if (data->ml_curr == NULL) { + /* A nullptr ml_curr is used to tag ended data! */ + if (data->ml_curr == nullptr) { break; } @@ -1434,12 +1436,12 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common BLI_bitmap *skip_loops = BLI_BITMAP_NEW(numLoops, __func__); - LoopSplitTaskData *data_buff = NULL; + LoopSplitTaskData *data_buff = nullptr; int data_idx = 0; /* Temp edge vectors stack, only used when computing lnor spacearr * (and we are not multi-threading). */ - BLI_Stack *edge_vectors = NULL; + BLI_Stack *edge_vectors = nullptr; #ifdef DEBUG_TIME TIMEIT_START_AVERAGED(loop_split_generator); @@ -1481,7 +1483,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge * as 'entry point', otherwise we can skip it. */ - /* Note: In theory, we could make #loop_split_generator_check_cyclic_smooth_fan() store + /* NOTE: In theory, we could make #loop_split_generator_check_cyclic_smooth_fan() store * mlfan_vert_index'es and edge indexes in two stacks, to avoid having to fan again around * the vert during actual computation of `clnor` & `clnorspace`. * However, this would complicate the code, add more memory usage, and despite its logical @@ -1508,7 +1510,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common if (pool) { if (data_idx == 0) { - data_buff = MEM_calloc_arrayN( + data_buff = (LoopSplitTaskData *)MEM_calloc_arrayN( LOOP_SPLIT_TASK_BLOCK_SIZE, sizeof(*data_buff), __func__); } data = &data_buff[data_idx]; @@ -1525,7 +1527,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common data->ml_curr_index = ml_curr_index; #if 0 /* Not needed for 'single' loop. */ data->ml_prev_index = ml_prev_index; - data->e2l_prev = NULL; /* Tag as 'single' task. */ + data->e2l_prev = nullptr; /* Tag as 'single' task. */ #endif data->mp_index = mp_index; if (lnors_spacearr) { @@ -1559,7 +1561,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common if (pool) { data_idx++; if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) { - BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL); + BLI_task_pool_push(pool, loop_split_worker, data_buff, true, nullptr); data_idx = 0; } } @@ -1573,10 +1575,10 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common } } - /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, + /* Last block of data... Since it is calloc'ed and we use first nullptr item as stopper, * everything is fine. */ if (pool && data_idx) { - BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL); + BLI_task_pool_push(pool, loop_split_worker, data_buff, true, nullptr); } if (edge_vectors) { @@ -1659,17 +1661,18 @@ void BKE_mesh_normals_loop_split(const MVert *mverts, * However, if needed, we can store the negated value of loop index instead of INDEX_INVALID * to retrieve the real value later in code). * Note also that loose edges always have both values set to 0! */ - int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__); + int(*edge_to_loops)[2] = (int(*)[2])MEM_calloc_arrayN( + (size_t)numEdges, sizeof(*edge_to_loops), __func__); /* Simple mapping from a loop to its polygon index. */ - int *loop_to_poly = r_loop_to_poly ? - r_loop_to_poly : - MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); + int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : + (int *)MEM_malloc_arrayN( + (size_t)numLoops, sizeof(*loop_to_poly), __func__); /* When using custom loop normals, disable the angle feature! */ - const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL); + const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == nullptr); - MLoopNorSpaceArray _lnors_spacearr = {NULL}; + MLoopNorSpaceArray _lnors_spacearr = {nullptr}; #ifdef DEBUG_TIME TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split); @@ -1684,28 +1687,27 @@ void BKE_mesh_normals_loop_split(const MVert *mverts, } /* Init data common to all tasks. */ - LoopSplitTaskDataCommon common_data = { - .lnors_spacearr = r_lnors_spacearr, - .loopnors = r_loopnors, - .clnors_data = clnors_data, - .mverts = mverts, - .medges = medges, - .mloops = mloops, - .mpolys = mpolys, - .edge_to_loops = edge_to_loops, - .loop_to_poly = loop_to_poly, - .polynors = polynors, - .numEdges = numEdges, - .numLoops = numLoops, - .numPolys = numPolys, - }; + LoopSplitTaskDataCommon common_data; + common_data.lnors_spacearr = r_lnors_spacearr; + common_data.loopnors = r_loopnors; + common_data.clnors_data = clnors_data; + common_data.mverts = mverts; + common_data.medges = medges; + common_data.mloops = mloops; + common_data.mpolys = mpolys; + common_data.edge_to_loops = edge_to_loops; + common_data.loop_to_poly = loop_to_poly; + common_data.polynors = polynors; + common_data.numEdges = numEdges; + common_data.numLoops = numLoops; + common_data.numPolys = numPolys; /* This first loop check which edges are actually smooth, and compute edge vectors. */ mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false); if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { /* Not enough loops to be worth the whole threading overhead... */ - loop_split_generator(NULL, &common_data); + loop_split_generator(nullptr, &common_data); } else { TaskPool *task_pool = BLI_task_pool_create(&common_data, TASK_PRIORITY_HIGH); @@ -1766,10 +1768,10 @@ static void mesh_normals_loop_custom_set(const MVert *mverts, * (and perhaps from some editing tools later?). * So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice! */ - MLoopNorSpaceArray lnors_spacearr = {NULL}; + MLoopNorSpaceArray lnors_spacearr = {nullptr}; BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__); - float(*lnors)[3] = MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__); - int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(int), __func__); + float(*lnors)[3] = (float(*)[3])MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__); + int *loop_to_poly = (int *)MEM_malloc_arrayN((size_t)numLoops, sizeof(int), __func__); /* In this case we always consider split nors as ON, * and do not want to use angle to define smooth fans! */ const bool use_split_normals = true; @@ -1791,7 +1793,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts, use_split_normals, split_angle, &lnors_spacearr, - NULL, + nullptr, loop_to_poly); /* Set all given zero vectors to their default value. */ @@ -1823,12 +1825,12 @@ static void mesh_normals_loop_custom_set(const MVert *mverts, for (int i = 0; i < numLoops; i++) { if (!lnors_spacearr.lspacearr[i]) { /* This should not happen in theory, but in some rare case (probably ugly geometry) - * we can get some NULL loopspacearr at this point. :/ + * we can get some nullptr loopspacearr at this point. :/ * Maybe we should set those loops' edges as sharp? */ BLI_BITMAP_ENABLE(done_loops, i); if (G.debug & G_DEBUG) { - printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i); + printf("WARNING! Getting invalid nullptr loop space for loop %d!\n", i); } continue; } @@ -1849,8 +1851,8 @@ static void mesh_normals_loop_custom_set(const MVert *mverts, } LinkNode *loops = lnors_spacearr.lspacearr[i]->loops; - MLoop *prev_ml = NULL; - const float *org_nor = NULL; + MLoop *prev_ml = nullptr; + const float *org_nor = nullptr; while (loops) { const int lidx = POINTER_AS_INT(loops->link); @@ -1916,7 +1918,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts, use_split_normals, split_angle, &lnors_spacearr, - NULL, + nullptr, loop_to_poly); } else { @@ -1929,7 +1931,8 @@ static void mesh_normals_loop_custom_set(const MVert *mverts, if (!lnors_spacearr.lspacearr[i]) { BLI_BITMAP_DISABLE(done_loops, i); if (G.debug & G_DEBUG) { - printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i); + printf("WARNING! Still getting invalid nullptr loop space in second loop for loop %d!\n", + i); } continue; } @@ -1970,7 +1973,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts, mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors); BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], avg_nor, clnor_data_tmp); - while ((clnor_data = BLI_SMALLSTACK_POP(clnors_data))) { + while ((clnor_data = (short *)BLI_SMALLSTACK_POP(clnors_data))) { clnor_data[0] = clnor_data_tmp[0]; clnor_data[1] = clnor_data_tmp[1]; } @@ -2041,20 +2044,21 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const short(*clnors)[2]; const int numloops = mesh->totloop; - clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); - if (clnors != NULL) { + clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + if (clnors != nullptr) { memset(clnors, 0, sizeof(*clnors) * (size_t)numloops); } else { - clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, numloops); + clnors = (short(*)[2])CustomData_add_layer( + &mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, nullptr, numloops); } - float(*polynors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL); + float(*polynors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL); bool free_polynors = false; - if (polynors == NULL) { - polynors = MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__); + if (polynors == nullptr) { + polynors = (float(*)[3])MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__); BKE_mesh_calc_normals_poly(mesh->mvert, - NULL, + nullptr, mesh->totvert, mesh->mloop, mesh->mpoly, @@ -2119,7 +2123,8 @@ void BKE_mesh_normals_loop_to_vertex(const int numVerts, const float (*clnors)[3], float (*r_vert_clnors)[3]) { - int *vert_loops_nbr = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vert_loops_nbr), __func__); + int *vert_loops_nbr = (int *)MEM_calloc_arrayN( + (size_t)numVerts, sizeof(*vert_loops_nbr), __func__); copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f); diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index b7cff624a04..c5e8858ea12 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -216,7 +216,7 @@ static void mesh_calc_eigen_matrix(const MVert *verts, } unit_m4(r_mat); - /* Note: here we apply sample correction to covariance matrix, since we consider the vertices + /* NOTE: here we apply sample correction to covariance matrix, since we consider the vertices * as a sample of the whole 'surface' population of our mesh. */ BLI_covariance_m3_v3n(vcos, numverts, true, covmat, center); @@ -256,7 +256,7 @@ static void mesh_calc_eigen_matrix(const MVert *verts, float evi = eigen_val[i]; /* Protect against 1D/2D degenerated cases! */ - /* Note: not sure why we need square root of eigen values here + /* NOTE: not sure why we need square root of eigen values here * (which are equivalent to singular values, as far as I have understood), * but it seems to heavily reduce (if not completely nullify) * the error due to non-uniform scalings... */ @@ -470,7 +470,7 @@ typedef struct IslandResult { } IslandResult; /** - * \note About all bvh/raycasting stuff below: + * \note About all BVH/ray-casting stuff below: * * * We must use our ray radius as BVH epsilon too, else rays not hitting anything but * 'passing near' an item would be missed (since BVH handling would not detect them, @@ -478,8 +478,8 @@ typedef struct IslandResult { * * However, in 'islands' case where each hit gets a weight, 'precise' hits should have a better * weight than 'approximate' hits. * To address that, we simplify things with: - * * A first raycast with default, given rayradius; - * * If first one fails, we do more raycasting with bigger radius, but if hit is found + * * A first ray-cast with default, given ray-radius; + * * If first one fails, we do more ray-casting with bigger radius, but if hit is found * it will get smaller weight. * * This only concerns loops, currently (because of islands), and 'sampled' edges/polys norproj. @@ -1035,7 +1035,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, if (!weights[j]) { continue; } - /* Note: sources_num is always <= j! */ + /* NOTE: sources_num is always <= j! */ weights[sources_num] = weights[j] / totweights; indices[sources_num] = j; sources_num++; @@ -2332,7 +2332,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, for (i = 0; i < numpolys_dst; i++) { /* For each dst poly, we sample some rays from it (2D grid in pnor space) * and use their hits to interpolate from source polys. */ - /* Note: dst poly is early-converted into src space! */ + /* NOTE: dst poly is early-converted into src space! */ MPoly *mp = &polys_dst[i]; int tot_rays, done_rays = 0; @@ -2465,7 +2465,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, if (!weights[j]) { continue; } - /* Note: sources_num is always <= j! */ + /* NOTE: sources_num is always <= j! */ weights[sources_num] = weights[j] / totweights; indices[sources_num] = j; sources_num++; diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index 011dd7e25ee..7ac4c29f0ee 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -158,8 +158,12 @@ static void mesh_runtime_looptri_recalc_isolated(void *userdata) BKE_mesh_runtime_looptri_recalc(mesh); } -/* This is a ported copy of dm_getLoopTriArray(dm). */ -const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh) +/** + * \note This function only fills a cache, and therefore the mesh argument can + * be considered logically const. Concurrent access is protected by a mutex. + * \note This is a ported copy of dm_getLoopTriArray(dm). + */ +const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh) { ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex; BLI_mutex_lock(mesh_eval_mutex); @@ -171,7 +175,7 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh) } else { /* Must isolate multithreaded tasks while holding a mutex lock. */ - BLI_task_isolate(mesh_runtime_looptri_recalc_isolated, mesh); + BLI_task_isolate(mesh_runtime_looptri_recalc_isolated, (void *)mesh); looptri = mesh->runtime.looptris.array; } @@ -286,7 +290,7 @@ static void mesh_runtime_debug_info_layers(DynStr *dynstr, CustomData *cd) for (type = 0; type < CD_NUMTYPES; type++) { if (CustomData_has_layer(cd, type)) { - /* note: doesn't account for multiple layers */ + /* NOTE: doesn't account for multiple layers. */ const char *name = CustomData_layertype_name(type); const int size = CustomData_sizeof(type); const void *pt = CustomData_get_layer(cd, type); diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c index 2e22e521a13..e5e971fd574 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.c +++ b/source/blender/blenkernel/intern/mesh_tangent.c @@ -119,7 +119,7 @@ static void set_tspace(const SMikkTSpaceContext *pContext, * Compute simplified tangent space normals, i.e. * tangent vector + sign of bi-tangent one, which combined with * split normals can be used to recreate the full tangent space. - * Note: * The mesh should be made of only tris and quads! + * NOTE: * The mesh should be made of only tris and quads! */ void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts, const int UNUSED(numVerts), @@ -675,7 +675,7 @@ void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert, mesh2tangent->mpoly = mpoly; mesh2tangent->mloop = mloop; mesh2tangent->looptri = looptri; - /* Note, we assume we do have tessellated loop normals at this point + /* NOTE: we assume we do have tessellated loop normals at this point * (in case it is object-enabled), have to check this is valid. */ mesh2tangent->precomputedLoopNormals = loop_normals; mesh2tangent->precomputedFaceNormals = poly_normals; diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index bfdbf844a26..08668d55cf4 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -154,7 +154,7 @@ static int search_face_cmp(const void *v1, const void *v2) return 0; } -/* TODO check there is not some standard define of this somewhere! */ +/* TODO: check there is not some standard define of this somewhere! */ static int int_cmp(const void *v1, const void *v2) { return *(int *)v1 > *(int *)v2 ? 1 : *(int *)v1 < *(int *)v2 ? -1 : 0; @@ -819,7 +819,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, MDeformWeight *dw; for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) { - /* note, greater than max defgroups is accounted for in our code, but not < 0 */ + /* NOTE: greater than max defgroups is accounted for in our code, but not < 0. */ if (!isfinite(dw->weight)) { PRINT_ERR("\tVertex deform %u, group %u has weight: %f", i, dw->def_nr, dw->weight); if (do_fixes) { @@ -1287,7 +1287,7 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me) } /* And now, update polys' start loop index. */ - /* Note: At this point, there should never be any poly using a striped loop! */ + /* NOTE: At this point, there should never be any poly using a striped loop! */ for (a = 0, p = me->mpoly; a < me->totpoly; a++, p++) { p->loopstart = new_idx[p->loopstart]; } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e60f0102b9a..2088c4268e6 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -156,7 +156,7 @@ ModifierData *BKE_modifier_new(int type) const ModifierTypeInfo *mti = BKE_modifier_get_info(type); ModifierData *md = MEM_callocN(mti->structSize, mti->structName); - /* note, this name must be made unique later */ + /* NOTE: this name must be made unique later. */ BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name)); md->type = type; diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 3a7910d1a9f..f32b0c434c1 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -287,7 +287,7 @@ static void movieclip_blend_read_data(BlendDataReader *reader, ID *id) clip->tracking_context = NULL; clip->tracking.stats = NULL; - /* TODO we could store those in undo cache storage as well, and preserve them instead of + /* TODO: we could store those in undo cache storage as well, and preserve them instead of * re-creating them... */ BLI_listbase_clear(&clip->runtime.gputextures); @@ -1849,7 +1849,7 @@ static void movieclip_build_proxy_ibuf( IMB_freeImBuf(scaleibuf); } -/* note: currently used by proxy job for movies, threading happens within single frame +/* NOTE: currently used by proxy job for movies, threading happens within single frame * (meaning scaling shall be threaded) */ void BKE_movieclip_build_proxy_frame(MovieClip *clip, @@ -1893,7 +1893,7 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, } } -/* note: currently used by proxy job for sequences, threading happens within sequence +/* NOTE: currently used by proxy job for sequences, threading happens within sequence * (different threads handles different frames, no threading within frame is needed) */ void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, diff --git a/source/blender/blenkernel/intern/multires_inline.h b/source/blender/blenkernel/intern/multires_inline.h index e85aa12781e..f88b5dd3143 100644 --- a/source/blender/blenkernel/intern/multires_inline.h +++ b/source/blender/blenkernel/intern/multires_inline.h @@ -53,7 +53,7 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3] mul_v3_fl(tangent_matrix[0], -1.0f); } else { - BLI_assert(!"Unhandled corner index"); + BLI_assert_msg(0, "Unhandled corner index"); } cross_v3_v3v3(tangent_matrix[2], dPdu, dPdv); normalize_v3(tangent_matrix[0]); diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index aed8c3122a2..9fb158d2f84 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -1354,7 +1354,7 @@ static void evaluate_higher_grid_positions_with_details_callback( { const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - /* Position of the original veretx at top level. */ + /* Position of the original vertex at top level. */ float orig_final_P[3]; evaluate_final_original_point(reshape_smooth_context, grid_coord, orig_final_P); diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c index 4210f26a694..501e3f27389 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.c +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -603,7 +603,7 @@ static void write_loop_in_face_grid( step_y[1] = 0; break; default: - BLI_assert(!"Should never happen"); + BLI_assert_msg(0, "Should never happen"); break; } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index bf18765aa94..7e524da0f53 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -631,10 +631,10 @@ float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode) { NlaStrip *strip; - /* sanity checks - * - obviously we've got to have some starting data - * - when not in tweakmode, the active Action does not have any scaling applied :) - * - when in tweakmode, if the no-mapping flag is set, do not map + /* Sanity checks: + * - Obviously we've got to have some starting data. + * - When not in tweak-mode, the active Action does not have any scaling applied :) + * - When in tweak-mode, if the no-mapping flag is set, do not map. */ if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON) == 0 || (adt->flag & ADT_NLA_EDIT_NOMAP)) { return cframe; @@ -2089,9 +2089,8 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) return false; } - /* if block is already in tweakmode, just leave, but we should report - * that this block is in tweakmode (as our returncode) - */ + /* If block is already in tweak-mode, just leave, but we should report + * that this block is in tweak-mode (as our returncode). */ if (adt->flag & ADT_NLA_EDIT_ON) { return true; } @@ -2111,8 +2110,8 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) } } - /* There are situations where we may have multiple strips selected and we want to enter tweakmode - * on all of those at once. Usually in those cases, + /* There are situations where we may have multiple strips selected and we want to enter + * tweak-mode on all of those at once. Usually in those cases, * it will usually just be a single strip per AnimData. * In such cases, compromise and take the last selected track and/or last selected strip, T28468. */ @@ -2142,7 +2141,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) { if (G.debug & G_DEBUG) { - printf("NLA tweakmode enter - neither active requirement found\n"); + printf("NLA tweak-mode enter - neither active requirement found\n"); printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip); } return false; @@ -2192,7 +2191,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) return true; } -/* Exit tweakmode for this AnimData block */ +/* Exit tweak-mode for this AnimData block. */ void BKE_nla_tweakmode_exit(AnimData *adt) { NlaStrip *strip; diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 1b68c38e4ba..79caeaf7617 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -69,7 +69,6 @@ #include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_node_ui_storage.hh" #include "BLI_ghash.h" #include "BLI_threads.h" @@ -220,10 +219,6 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c /* node tree will generate its own interface type */ ntree_dst->interface_type = nullptr; - - /* Don't copy error messages in the runtime struct. - * They should be filled during execution anyway. */ - ntree_dst->ui_storage = nullptr; } static void ntree_free_data(ID *id) @@ -277,8 +272,6 @@ static void ntree_free_data(ID *id) if (ntree->id.tag & LIB_TAG_LOCALIZED) { BKE_libblock_free_data(&ntree->id, true); } - - delete ntree->ui_storage; } static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock) @@ -365,7 +358,7 @@ static void node_foreach_cache(ID *id, key.offset_in_ID = offsetof(bNodeTree, previews); key.cache_v = nodetree->previews; - /* TODO, see also `direct_link_nodetree()` in readfile.c. */ + /* TODO: see also `direct_link_nodetree()` in readfile.c. */ #if 0 function_callback(id, &key, (void **)&nodetree->previews, 0, user_data); #endif @@ -407,7 +400,7 @@ static ID *node_owner_get(Main *bmain, ID *id) } } - BLI_assert(!"Embedded node tree with no owner. Critical Main inconsistency."); + BLI_assert_msg(0, "Embedded node tree with no owner. Critical Main inconsistency."); return nullptr; } @@ -517,7 +510,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) if (node->storage) { /* could be handlerized at some point, now only 1 exception still */ - if ((ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY)) && + if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY) && ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) { BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } @@ -625,7 +618,6 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres ntree->interface_type = nullptr; ntree->progress = nullptr; ntree->execdata = nullptr; - ntree->ui_storage = nullptr; BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id); @@ -649,7 +641,7 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock) /* ntree itself has been read! */ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) { - /* note: writing and reading goes in sync, for speed */ + /* NOTE: writing and reading goes in sync, for speed. */ ntree->init = 0; /* to set callbacks and force setting types */ ntree->is_updating = false; ntree->typeinfo = nullptr; @@ -657,7 +649,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) ntree->progress = nullptr; ntree->execdata = nullptr; - ntree->ui_storage = nullptr; BLO_read_data_address(reader, &ntree->adt); BKE_animdata_blend_read_data(reader, ntree->adt); @@ -800,7 +791,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) BLO_read_data_address(reader, &link->tosock); } - /* TODO, should be dealt by new generic cache handling of IDs... */ + /* TODO: should be dealt by new generic cache handling of IDs... */ ntree->previews = nullptr; /* type verification is in lib-link */ @@ -1048,7 +1039,7 @@ static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType } } -/* Note: This function is called to initialize node data based on the type. +/* NOTE: This function is called to initialize node data based on the type. * The bNodeType may not be registered at creation time of the node, * so this can be delayed until the node type gets registered. */ @@ -1070,7 +1061,7 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node) node->height = ntype->height; node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */ /* initialize the node name with the node label. - * note: do this after the initfunc so nodes get their data set which may be used in naming + * NOTE: do this after the initfunc so nodes get their data set which may be used in naming * (node groups for example) */ /* XXX Do not use nodeLabel() here, it returns translated content for UI, * which should *only* be used in UI, *never* in data... @@ -1431,6 +1422,12 @@ GHashIterator *nodeSocketTypeGetIterator(void) return BLI_ghashIterator_new(nodesockettypes_hash); } +const char *nodeSocketTypeLabel(const bNodeSocketType *stype) +{ + /* Use socket type name as a fallback if label is undefined. */ + return stype->label[0] != '\0' ? stype->label : RNA_struct_ui_name(stype->ext_socket.srna); +} + struct bNodeSocket *nodeFindSocket(const bNode *node, eNodeSocketInOut in_out, const char *identifier) @@ -1593,13 +1590,15 @@ static void socket_id_user_decrement(bNodeSocket *sock) } } -void nodeModifySocketType( - bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, int type, int subtype) +void nodeModifySocketType(bNodeTree *ntree, + bNode *UNUSED(node), + bNodeSocket *sock, + const char *idname) { - const char *idname = nodeStaticSocketType(type, subtype); + bNodeSocketType *socktype = nodeSocketTypeFind(idname); - if (!idname) { - CLOG_ERROR(&LOG, "static node socket type %d undefined", type); + if (!socktype) { + CLOG_ERROR(&LOG, "node socket type %s undefined", idname); return; } @@ -1609,9 +1608,21 @@ void nodeModifySocketType( sock->default_value = nullptr; } - sock->type = type; BLI_strncpy(sock->idname, idname, sizeof(sock->idname)); - node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(idname)); + node_socket_set_typeinfo(ntree, sock, socktype); +} + +void nodeModifySocketTypeStatic( + bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype) +{ + const char *idname = nodeStaticSocketType(type, subtype); + + if (!idname) { + CLOG_ERROR(&LOG, "static node socket type %d undefined", type); + return; + } + + nodeModifySocketType(ntree, node, sock, idname); } bNodeSocket *nodeAddSocket(bNodeTree *ntree, @@ -1655,6 +1666,15 @@ bNodeSocket *nodeInsertSocket(bNodeTree *ntree, return sock; } +bool nodeIsStaticSocketType(const struct bNodeSocketType *stype) +{ + /* + * Cannot rely on type==SOCK_CUSTOM here, because type is 0 by default + * and can be changed on custom sockets. + */ + return RNA_struct_is_a(stype->ext_socket.srna, &RNA_NodeSocketStandard); +} + const char *nodeStaticSocketType(int type, int subtype) { switch (type) { @@ -1813,6 +1833,39 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype) return nullptr; } +const char *nodeStaticSocketLabel(int type, int UNUSED(subtype)) +{ + switch (type) { + case SOCK_FLOAT: + return "Float"; + case SOCK_INT: + return "Integer"; + case SOCK_BOOLEAN: + return "Boolean"; + case SOCK_VECTOR: + return "Vector"; + case SOCK_RGBA: + return "Color"; + case SOCK_STRING: + return "String"; + case SOCK_SHADER: + return "Shader"; + case SOCK_OBJECT: + return "Object"; + case SOCK_IMAGE: + return "Image"; + case SOCK_GEOMETRY: + return "Geometry"; + case SOCK_COLLECTION: + return "Collection"; + case SOCK_TEXTURE: + return "Texture"; + case SOCK_MATERIAL: + return "Material"; + } + return nullptr; +} + bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree, bNode *node, eNodeSocketInOut in_out, @@ -2895,7 +2948,7 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo BKE_node_instance_hash_insert(to_ntree->previews, key, preview); } - /* Note: null free function here, + /* NOTE: null free function here, * because pointers have already been moved over to to_ntree->previews! */ BKE_node_instance_hash_free(from_ntree->previews, nullptr); from_ntree->previews = nullptr; @@ -3102,7 +3155,7 @@ static void free_localized_node_groups(bNodeTree *ntree) } LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) { + if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) { bNodeTree *ngroup = (bNodeTree *)node->id; ntreeFreeTree(ngroup); MEM_freeN(ngroup); @@ -3163,8 +3216,8 @@ void ntreeSetOutput(bNodeTree *ntree) if (ntree->type == NTREE_COMPOSIT) { /* same type, exception for viewer */ if (tnode->type == node->type || - (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && - ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) { + (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER) && + ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER))) { if (tnode->flag & NODE_DO_OUTPUT) { output++; if (output > 1) { @@ -3286,7 +3339,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) { if (ntree) { /* Make full copy outside of Main database. - * Note: previews are not copied here. + * NOTE: previews are not copied here. */ bNodeTree *ltree = (bNodeTree *)BKE_id_copy_ex( nullptr, &ntree->id, nullptr, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA)); @@ -3294,7 +3347,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) ltree->id.tag |= LIB_TAG_LOCALIZED; LISTBASE_FOREACH (bNode *, node, <ree->nodes) { - if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) { + if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) { node->id = (ID *)ntreeLocalize((bNodeTree *)node->id); } } @@ -4763,7 +4816,7 @@ static bool node_undefined_poll(bNodeType *UNUSED(ntype), /* register fallback types used for undefined tree, nodes, sockets */ static void register_undefined_types() { - /* Note: these types are not registered in the type hashes, + /* NOTE: these types are not registered in the type hashes, * they are just used as placeholders in case the actual types are not registered. */ @@ -5057,27 +5110,30 @@ static void registerGeometryNodes() register_node_type_geo_attribute_mix(); register_node_type_geo_attribute_proximity(); register_node_type_geo_attribute_randomize(); + register_node_type_geo_attribute_remove(); register_node_type_geo_attribute_separate_xyz(); register_node_type_geo_attribute_set(); register_node_type_geo_attribute_transfer(); register_node_type_geo_attribute_vector_math(); register_node_type_geo_attribute_vector_rotate(); - register_node_type_geo_attribute_remove(); register_node_type_geo_boolean(); register_node_type_geo_bounding_box(); register_node_type_geo_collection_info(); register_node_type_geo_convex_hull(); + register_node_type_geo_curve_endpoints(); register_node_type_geo_curve_length(); register_node_type_geo_curve_primitive_bezier_segment(); register_node_type_geo_curve_primitive_circle(); + register_node_type_geo_curve_primitive_line(); register_node_type_geo_curve_primitive_quadratic_bezier(); + register_node_type_geo_curve_primitive_quadrilateral(); register_node_type_geo_curve_primitive_spiral(); register_node_type_geo_curve_primitive_star(); - register_node_type_geo_curve_to_mesh(); - register_node_type_geo_curve_to_points(); register_node_type_geo_curve_resample(); register_node_type_geo_curve_reverse(); register_node_type_geo_curve_subdivide(); + register_node_type_geo_curve_to_mesh(); + register_node_type_geo_curve_to_points(); register_node_type_geo_delete_geometry(); register_node_type_geo_edge_split(); register_node_type_geo_input_material(); @@ -5093,6 +5149,7 @@ static void registerGeometryNodes() register_node_type_geo_mesh_primitive_ico_sphere(); register_node_type_geo_mesh_primitive_line(); register_node_type_geo_mesh_primitive_uv_sphere(); + register_node_type_geo_mesh_subdivide(); register_node_type_geo_mesh_to_curve(); register_node_type_geo_object_info(); register_node_type_geo_point_distribute(); @@ -5106,11 +5163,11 @@ static void registerGeometryNodes() register_node_type_geo_sample_texture(); register_node_type_geo_select_by_material(); register_node_type_geo_separate_components(); - register_node_type_geo_subdivide(); register_node_type_geo_subdivision_surface(); register_node_type_geo_switch(); register_node_type_geo_transform(); register_node_type_geo_triangulate(); + register_node_type_geo_viewer(); register_node_type_geo_volume_to_mesh(); } @@ -5118,6 +5175,7 @@ static void registerFunctionNodes() { register_node_type_fn_boolean_math(); register_node_type_fn_float_compare(); + register_node_type_fn_float_to_int(); register_node_type_fn_input_string(); register_node_type_fn_input_vector(); register_node_type_fn_random_float(); diff --git a/source/blender/blenkernel/intern/node_ui_storage.cc b/source/blender/blenkernel/intern/node_ui_storage.cc deleted file mode 100644 index e5e9f00c7c3..00000000000 --- a/source/blender/blenkernel/intern/node_ui_storage.cc +++ /dev/null @@ -1,169 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "CLG_log.h" - -#include <mutex> - -#include "BLI_map.hh" -#include "BLI_string_ref.hh" -#include "BLI_vector.hh" - -#include "DNA_node_types.h" -#include "DNA_object_types.h" - -#include "BKE_context.h" -#include "BKE_node_ui_storage.hh" -#include "BKE_object.h" - -static CLG_LogRef LOG = {"bke.node_ui_storage"}; - -using blender::Map; -using blender::StringRef; -using blender::Vector; - -/* Use a global mutex because otherwise it would have to be stored directly in the - * bNodeTree struct in DNA. This could change if the node tree had a runtime struct. */ -static std::mutex global_ui_storage_mutex; - -static NodeTreeUIStorage &ui_storage_ensure(bNodeTree &ntree) -{ - /* As an optimization, only acquire a lock if the UI storage doesn't exist, - * because it only needs to be allocated once for every node tree. */ - if (ntree.ui_storage == nullptr) { - std::lock_guard<std::mutex> lock(global_ui_storage_mutex); - /* Check again-- another thread may have allocated the storage while this one waited. */ - if (ntree.ui_storage == nullptr) { - ntree.ui_storage = new NodeTreeUIStorage(); - } - } - return *ntree.ui_storage; -} - -const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C, - const bNodeTree &ntree, - const bNode &node) -{ - const NodeTreeUIStorage *ui_storage = ntree.ui_storage; - if (ui_storage == nullptr) { - return nullptr; - } - - const Object *active_object = CTX_data_active_object(C); - if (active_object == nullptr) { - return nullptr; - } - - const ModifierData *active_modifier = BKE_object_active_modifier(active_object); - if (active_modifier == nullptr) { - return nullptr; - } - - const NodeTreeEvaluationContext context(*active_object, *active_modifier); - const Map<std::string, NodeUIStorage> *storage = ui_storage->context_map.lookup_ptr(context); - if (storage == nullptr) { - return nullptr; - } - - return storage->lookup_ptr_as(StringRef(node.name)); -} - -/** - * Removes only the UI data associated with a particular evaluation context. The same node tree - * can be used for execution in multiple places, but the entire UI storage can't be removed when - * one execution starts, or all of the data associated with the node tree would be lost. - */ -void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree, - const NodeTreeEvaluationContext &context) -{ - NodeTreeUIStorage *ui_storage = ntree.ui_storage; - if (ui_storage != nullptr) { - std::lock_guard<std::mutex> lock(ui_storage->mutex); - ui_storage->context_map.remove(context); - } -} - -static void node_error_message_log(bNodeTree &ntree, - const bNode &node, - const StringRef message, - const NodeWarningType type) -{ - switch (type) { - case NodeWarningType::Error: - CLOG_ERROR(&LOG, - "Node Tree: \"%s\", Node: \"%s\", %s", - ntree.id.name + 2, - node.name, - message.data()); - break; - case NodeWarningType::Warning: - CLOG_WARN(&LOG, - "Node Tree: \"%s\", Node: \"%s\", %s", - ntree.id.name + 2, - node.name, - message.data()); - break; - case NodeWarningType::Info: - CLOG_INFO(&LOG, - 2, - "Node Tree: \"%s\", Node: \"%s\", %s", - ntree.id.name + 2, - node.name, - message.data()); - break; - } -} - -static NodeUIStorage &node_ui_storage_ensure(NodeTreeUIStorage &locked_ui_storage, - const NodeTreeEvaluationContext &context, - const bNode &node) -{ - Map<std::string, NodeUIStorage> &node_tree_ui_storage = - locked_ui_storage.context_map.lookup_or_add_default(context); - NodeUIStorage &node_ui_storage = node_tree_ui_storage.lookup_or_add_default_as( - StringRef(node.name)); - return node_ui_storage; -} - -void BKE_nodetree_error_message_add(bNodeTree &ntree, - const NodeTreeEvaluationContext &context, - const bNode &node, - const NodeWarningType type, - std::string message) -{ - NodeTreeUIStorage &ui_storage = ui_storage_ensure(ntree); - std::lock_guard lock{ui_storage.mutex}; - - node_error_message_log(ntree, node, message, type); - - NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ui_storage, context, node); - node_ui_storage.warnings.append({type, std::move(message)}); -} - -void BKE_nodetree_attribute_hint_add(bNodeTree &ntree, - const NodeTreeEvaluationContext &context, - const bNode &node, - const StringRef attribute_name, - const AttributeDomain domain, - const CustomDataType data_type) -{ - NodeTreeUIStorage &ui_storage = ui_storage_ensure(ntree); - std::lock_guard lock{ui_storage.mutex}; - - NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ui_storage, context, node); - node_ui_storage.attribute_hints.add_as( - AvailableAttributeInfo{attribute_name, domain, data_type}); -} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index a5e16172e75..941db80b76c 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -205,7 +205,8 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in } else if (ob_dst->mat != NULL || ob_dst->matbits != NULL) { /* This shall not be needed, but better be safe than sorry. */ - BLI_assert(!"Object copy: non-NULL material pointers with zero counter, should not happen."); + BLI_assert_msg( + 0, "Object copy: non-NULL material pointers with zero counter, should not happen."); ob_dst->mat = NULL; ob_dst->matbits = NULL; } @@ -234,7 +235,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in BKE_pose_rebuild(bmain, ob_dst, ob_dst->data, do_pose_id_user); } } - BKE_defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase); + BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps); BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true); @@ -251,7 +252,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in BLI_listbase_clear(&ob_dst->modifiers); BLI_listbase_clear(&ob_dst->greasepencil_modifiers); - /* Note: Also takes care of softbody and particle systems copying. */ + /* NOTE: Also takes care of softbody and particle systems copying. */ BKE_object_modifier_stack_copy(ob_dst, ob_src, true, flag_subdata); BLI_listbase_clear((ListBase *)&ob_dst->drawdata); @@ -262,7 +263,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in /* Do not copy object's preview * (mostly due to the fact renderers create temp copy of objects). */ - if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO: temp hack. */ BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id); } else { @@ -285,7 +286,6 @@ static void object_free_data(ID *id) MEM_SAFE_FREE(ob->iuser); MEM_SAFE_FREE(ob->runtime.bb); - BLI_freelistN(&ob->defbase); BLI_freelistN(&ob->fmaps); if (ob->pose) { BKE_pose_free_ex(ob->pose, false); @@ -510,13 +510,6 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data) } } -static void write_defgroups(BlendWriter *writer, ListBase *defbase) -{ - LISTBASE_FOREACH (bDeformGroup *, defgroup, defbase) { - BLO_write_struct(writer, bDeformGroup, defgroup); - } -} - static void write_fmaps(BlendWriter *writer, ListBase *fbase) { LISTBASE_FOREACH (bFaceMap *, fmap, fbase) { @@ -561,7 +554,6 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre } BKE_pose_blend_write(writer, ob->pose, arm); - write_defgroups(writer, &ob->defbase); write_fmaps(writer, &ob->fmaps); BKE_constraint_blend_write(writer, &ob->constraints); animviz_motionpath_blend_write(writer, ob->mpath); @@ -644,7 +636,9 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id) animviz_motionpath_blend_read_data(reader, ob->mpath); } + /* Only for versioning, vertex group names are now stored on object data. */ BLO_read_list(reader, &ob->defbase); + BLO_read_list(reader, &ob->fmaps); /* XXX deprecated - old animation system <<< */ direct_link_nlastrips(reader, &ob->nlastrips); @@ -1041,6 +1035,8 @@ static void object_blend_read_expand(BlendExpander *expander, ID *id) BLO_expand(expander, ob->data); + BLO_expand(expander, ob->parent); + /* expand_object_expandModifier() */ if (ob->modifiers.first) { BKE_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, expander); @@ -1537,7 +1533,8 @@ bool BKE_object_modifier_stack_copy(Object *ob_dst, const int flag_subdata) { if ((ob_dst->type == OB_GPENCIL) != (ob_src->type == OB_GPENCIL)) { - BLI_assert(!"Trying to copy a modifier stack between a GPencil object and another type."); + BLI_assert_msg(0, + "Trying to copy a modifier stack between a GPencil object and another type."); return false; } @@ -1758,10 +1755,6 @@ void BKE_object_free_derived_caches(Object *ob) BKE_geometry_set_free(ob->runtime.geometry_set_eval); ob->runtime.geometry_set_eval = NULL; } - if (ob->runtime.geometry_set_previews != NULL) { - BLI_ghash_free(ob->runtime.geometry_set_previews, NULL, (GHashValFreeFP)BKE_geometry_set_free); - ob->runtime.geometry_set_previews = NULL; - } } void BKE_object_free_caches(Object *object) @@ -1812,24 +1805,6 @@ void BKE_object_free_caches(Object *object) } } -/* Can be called from multiple threads. */ -void BKE_object_preview_geometry_set_add(Object *ob, - const uint64_t key, - struct GeometrySet *geometry_set) -{ - static ThreadMutex mutex = BLI_MUTEX_INITIALIZER; - BLI_mutex_lock(&mutex); - if (ob->runtime.geometry_set_previews == NULL) { - ob->runtime.geometry_set_previews = BLI_ghash_int_new(__func__); - } - BLI_ghash_reinsert(ob->runtime.geometry_set_previews, - POINTER_FROM_UINT(key), - geometry_set, - NULL, - (GHashValFreeFP)BKE_geometry_set_free); - BLI_mutex_unlock(&mutex); -} - /** * Actual check for internal data, not context or flags. */ @@ -2380,8 +2355,8 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag); } - /* XXX - from reading existing code this seems correct but intended usage of - * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ + /* XXX(campbell): from reading existing code this seems correct but intended usage of + * pointcache should /w cloth should be added in 'ParticleSystem'. */ if (psysn->clmd) { psysn->clmd->point_cache = psysn->pointcache; } @@ -2439,7 +2414,7 @@ void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const static void copy_object_pose(Object *obn, const Object *ob, const int flag) { - /* note: need to clear obn->pose pointer first, + /* NOTE: need to clear obn->pose pointer first, * so that BKE_pose_copy_data works (otherwise there's a crash) */ obn->pose = NULL; BKE_pose_copy_data_ex(&obn->pose, ob->pose, flag, true); /* true = copy constraints */ @@ -2833,7 +2808,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target) /* add new animdata block */ if (!ob->adt) { - ob->adt = BKE_animdata_add_id(&ob->id); + ob->adt = BKE_animdata_ensure_id(&ob->id); } /* make a copy of all the drivers (for now), then correct any links that need fixing */ @@ -2921,9 +2896,6 @@ void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob) ob->data = target->data; id_us_plus((ID *)ob->data); /* ensures lib data becomes LIB_TAG_EXTERN */ - /* copy vertex groups */ - BKE_defgroup_copy_list(&ob->defbase, &target->defbase); - /* copy material and index information */ ob->actcol = ob->totcol = 0; if (ob->mat) { @@ -3365,7 +3337,7 @@ static void give_parvert(Object *par, int nr, float vec[3]) } BLI_mutex_unlock(&vparent_lock); #else - BLI_assert(!"Not safe for threading"); + BLI_assert_msg(0, "Not safe for threading"); BM_mesh_elem_table_ensure(em->bm, BM_VERT); #endif } @@ -3860,7 +3832,7 @@ void BKE_object_boundbox_flag(Object *ob, int flag, const bool set) } } -void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval) +void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval) { float min[3], max[3]; @@ -4089,7 +4061,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re if ((visibility_flag & (OB_EMPTY_IMAGE_HIDE_BACK | OB_EMPTY_IMAGE_HIDE_FRONT)) != 0) { float eps, dot; if (rv3d->is_persp) { - /* Note, we could normalize the 'view_dir' then use 'eps' + /* NOTE: we could normalize the 'view_dir' then use 'eps' * however the issue with empty objects being visible when viewed from the side * is only noticeable in orthographic views. */ float view_dir[3]; @@ -4163,13 +4135,37 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph, return ok; } +struct GPencilStrokePointIterData { + const float (*obmat)[4]; + + void (*point_func_cb)(const float co[3], void *user_data); + void *user_data; +}; + +static void foreach_display_point_gpencil_stroke_fn(bGPDlayer *UNUSED(layer), + bGPDframe *UNUSED(frame), + bGPDstroke *stroke, + void *thunk) +{ + struct GPencilStrokePointIterData *iter_data = thunk; + { + bGPDspoint *pt; + int i; + for (i = 0, pt = stroke->points; i < stroke->totpoints; i++, pt++) { + float co[3]; + mul_v3_m4v3(co, iter_data->obmat, &pt->x); + iter_data->point_func_cb(co, iter_data->user_data); + } + } +} + void BKE_object_foreach_display_point(Object *ob, const float obmat[4][4], void (*func_cb)(const float[3], void *), void *user_data) { /* TODO: pointcloud and hair objects support */ - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); float co[3]; if (mesh_eval != NULL) { @@ -4180,6 +4176,13 @@ void BKE_object_foreach_display_point(Object *ob, func_cb(co, user_data); } } + else if (ob->type == OB_GPENCIL) { + struct GPencilStrokePointIterData iter_data = { + .obmat = obmat, .point_func_cb = func_cb, .user_data = user_data}; + + BKE_gpencil_visible_stroke_iter( + ob->data, NULL, foreach_display_point_gpencil_stroke_fn, &iter_data); + } else if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) { DispList *dl; @@ -5616,7 +5619,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, } } - /* was originally ID_RECALC_ALL - TODO - which flags are really needed??? */ + /* was originally ID_RECALC_ALL - TODO: which flags are really needed??? */ /* TODO(sergey): What about animation? */ const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, frame); diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index 1e7624d0d7d..c69326a23c6 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -33,6 +33,7 @@ #include "DNA_armature_types.h" #include "DNA_cloth_types.h" #include "DNA_curve_types.h" +#include "DNA_gpencil_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -123,8 +124,7 @@ bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name) } defgroup = BKE_object_defgroup_new(ob, name); - - ob->actdef = BLI_listbase_count(&ob->defbase); + BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_count(ob)); return defgroup; } @@ -171,7 +171,8 @@ MDeformVert *BKE_object_defgroup_data_create(ID *id) bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection) { MDeformVert *dv; - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); bool changed = false; if (ob->type == OB_MESH) { @@ -249,7 +250,9 @@ bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection) bDeformGroup *dg; bool changed = false; - for (dg = ob->defbase.first; dg; dg = dg->next) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + + for (dg = defbase->first; dg; dg = dg->next) { if (BKE_object_defgroup_clear(ob, dg, use_selection)) { changed = true; } @@ -265,7 +268,7 @@ bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection) static void object_defgroup_remove_update_users(Object *ob, const int idx) { - int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1; + int i, defbase_tot = BKE_object_defgroup_count(ob) + 1; int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del"); map[idx] = map[0] = 0; @@ -285,15 +288,18 @@ static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const in object_defgroup_remove_update_users(ob, def_nr + 1); /* Remove the group */ - BLI_freelinkN(&ob->defbase, dg); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + BLI_freelinkN(defbase, dg); /* Update the active deform index if necessary */ - if (ob->actdef > def_nr) { - ob->actdef--; + const int active_index = BKE_object_defgroup_active_index_get(ob); + if (active_index > def_nr) { + BKE_object_defgroup_active_index_set(ob, active_index - 1); } /* remove all dverts */ - if (BLI_listbase_is_empty(&ob->defbase)) { + if (BLI_listbase_is_empty(defbase)) { if (ob->type == OB_MESH) { Mesh *me = ob->data; CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); @@ -307,8 +313,9 @@ static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const in } } } - else if (ob->actdef < 1) { /* Keep a valid active index if we still have some vgroups. */ - ob->actdef = 1; + else if (BKE_object_defgroup_active_index_get(ob) < 1) { + /* Keep a valid active index if we still have some vgroups. */ + BKE_object_defgroup_active_index_set(ob, 1); } } @@ -316,7 +323,9 @@ static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg) { MDeformVert *dvert_array = NULL; int dvert_tot = 0; - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + + const int def_nr = BLI_findindex(defbase, dg); BLI_assert(def_nr != -1); @@ -347,7 +356,8 @@ static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg) static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg) { int i; - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); BLI_assert(def_nr != -1); @@ -425,7 +435,9 @@ void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup) */ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked) { - bDeformGroup *dg = (bDeformGroup *)ob->defbase.first; + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + bDeformGroup *dg = (bDeformGroup *)defbase->first; const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob); if (dg) { @@ -444,7 +456,7 @@ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked) dg = next_dg; } } - else { /* ob->defbase is empty... */ + else { /* defbase is empty... */ /* remove all dverts */ if (ob->type == OB_MESH) { Mesh *me = ob->data; @@ -459,7 +471,7 @@ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked) } } /* Fix counters/indices */ - ob->actdef = 0; + BKE_object_defgroup_active_index_set(ob, 0); } } @@ -478,20 +490,23 @@ void BKE_object_defgroup_remove_all(struct Object *ob) */ int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len) { + const ListBase *src_defbase = BKE_object_defgroup_list(ob_src); + const ListBase *dst_defbase = BKE_object_defgroup_list(ob_dst); + /* Build src to merged mapping of vgroup indices. */ - if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) { + if (BLI_listbase_is_empty(src_defbase) || BLI_listbase_is_empty(dst_defbase)) { *r_map_len = 0; return NULL; } bDeformGroup *dg_src; - *r_map_len = BLI_listbase_count(&ob_src->defbase); + *r_map_len = BLI_listbase_count(src_defbase); int *vgroup_index_map = MEM_malloc_arrayN( *r_map_len, sizeof(*vgroup_index_map), "defgroup index map create"); bool is_vgroup_remap_needed = false; int i; - for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) { + for (dg_src = src_defbase->first, i = 0; dg_src; dg_src = dg_src->next, i++) { vgroup_index_map[i] = BKE_object_defgroup_name_index(ob_dst, dg_src->name); is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i); } @@ -576,17 +591,17 @@ bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_t /** * gets the status of "flag" for each bDeformGroup - * in ob->defbase and returns an array containing them + * in the object data's vertex group list and returns an array containing them */ bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot) { bool is_locked = false; int i; - // int defbase_tot = BLI_listbase_count(&ob->defbase); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags"); bDeformGroup *defgroup; - for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; + for (i = 0, defgroup = defbase->first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0); is_locked |= lock_flags[i]; @@ -606,17 +621,17 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot) bool *defgroup_validmap; GHash *gh; int i, step1 = 1; - // int defbase_tot = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); VirtualModifierData virtualModifierData; - if (BLI_listbase_is_empty(&ob->defbase)) { + if (BLI_listbase_is_empty(defbase)) { return NULL; } gh = BLI_ghash_str_new_ex(__func__, defbase_tot); /* add all names to a hash table */ - for (dg = ob->defbase.first; dg; dg = dg->next) { + for (dg = defbase->first; dg; dg = dg->next) { BLI_ghash_insert(gh, dg->name, NULL); } @@ -655,7 +670,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot) defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map"); /* add all names to a hash table */ - for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL); } @@ -676,9 +691,11 @@ bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_fl Object *armob = BKE_object_pose_armature_get(ob); (*r_dg_flags_sel_tot) = 0; + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (armob) { bPose *pose = armob->pose; - for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; + for (i = 0, defgroup = defbase->first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name); if (pchan && (pchan->bone->flag & BONE_SELECTED)) { @@ -774,11 +791,13 @@ void BKE_object_defgroup_mirror_selection(struct Object *ob, bool *dg_flags_sel, int *r_dg_flags_sel_tot) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *defgroup; unsigned int i; int i_mirr; - for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; + for (i = 0, defgroup = defbase->first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { if (dg_selection[i]) { char name_flip[MAXBONENAME]; @@ -804,11 +823,12 @@ bool *BKE_object_defgroup_subset_from_select_type(Object *ob, int *r_subset_count) { bool *defgroup_validmap = NULL; - *r_defgroup_tot = BLI_listbase_count(&ob->defbase); + + *r_defgroup_tot = BKE_object_defgroup_count(ob); switch (subset_type) { case WT_VGROUP_ACTIVE: { - const int def_nr_active = ob->actdef - 1; + const int def_nr_active = BKE_object_defgroup_active_index_get(ob) - 1; defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__); memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap)); if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) { diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 768fa9373c1..77969328365 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -335,14 +335,14 @@ static void make_child_duplis(const DupliContext *ctx, /** \name Internal Data Access Utilities * \{ */ -static Mesh *mesh_data_from_duplicator_object(Object *ob, - BMEditMesh **r_em, - const float (**r_vert_coords)[3], - const float (**r_vert_normals)[3]) +static const Mesh *mesh_data_from_duplicator_object(Object *ob, + BMEditMesh **r_em, + const float (**r_vert_coords)[3], + const float (**r_vert_normals)[3]) { /* Gather mesh info. */ BMEditMesh *em = BKE_editmesh_from_object(ob); - Mesh *me_eval; + const Mesh *me_eval; *r_em = nullptr; *r_vert_coords = nullptr; @@ -603,7 +603,7 @@ static void make_duplis_verts(const DupliContext *ctx) BMEditMesh *em = nullptr; const float(*vert_coords)[3] = nullptr; const float(*vert_normals)[3] = nullptr; - Mesh *me_eval = mesh_data_from_duplicator_object( + const Mesh *me_eval = mesh_data_from_duplicator_object( parent, &em, &vert_coords, use_rotation ? &vert_normals : nullptr); if (em == nullptr && me_eval == nullptr) { return; @@ -1151,7 +1151,7 @@ static void make_duplis_faces(const DupliContext *ctx) /* Gather mesh info. */ BMEditMesh *em = nullptr; const float(*vert_coords)[3] = nullptr; - Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, nullptr); + const Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, nullptr); if (em == nullptr && me_eval == nullptr) { return; } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index ab247ef5507..7cdea14e9bd 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -123,7 +123,7 @@ void BKE_object_eval_parent(Depsgraph *depsgraph, Object *ob) void BKE_object_eval_constraints(Depsgraph *depsgraph, Scene *scene, Object *ob) { bConstraintOb *cob; - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); @@ -388,12 +388,31 @@ void BKE_object_batch_cache_dirty_tag(Object *ob) BKE_object_data_batch_cache_dirty_tag(ob->data); } +void BKE_object_data_eval_batch_cache_dirty_tag(Depsgraph *depsgraph, ID *object_data) +{ + DEG_debug_print_eval(depsgraph, __func__, object_data->name, object_data); + BKE_object_data_batch_cache_dirty_tag(object_data); +} + +void BKE_object_data_eval_batch_cache_deform_tag(Depsgraph *depsgraph, ID *object_data) +{ + DEG_debug_print_eval(depsgraph, __func__, object_data->name, object_data); + switch (GS(object_data->name)) { + case ID_ME: + BKE_mesh_batch_cache_dirty_tag((Mesh *)object_data, BKE_MESH_BATCH_DIRTY_DEFORM); + break; + default: + /* Only mesh is currently supported. Fallback to dirty all for other datablocks types. */ + BKE_object_data_batch_cache_dirty_tag(object_data); + break; + } +} + void BKE_object_eval_uber_data(Depsgraph *depsgraph, Scene *scene, Object *ob) { DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); BLI_assert(ob->type != OB_ARMATURE); BKE_object_handle_data_update(depsgraph, scene, ob); - BKE_object_batch_cache_dirty_tag(ob); } void BKE_object_eval_ptcache_reset(Depsgraph *depsgraph, Scene *scene, Object *object) diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 2e7152302c7..3aee5cd639d 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -62,7 +62,7 @@ static float nextfr(RNG *rng, float min, float max) static float gaussRand(RNG *rng) { - /* Note: to avoid numerical problems with very small numbers, we make these variables + /* NOTE: to avoid numerical problems with very small numbers, we make these variables * singe-precision floats, but later we call the double-precision log() and sqrt() functions * instead of logf() and sqrtf(). */ float x; @@ -1381,9 +1381,9 @@ void BKE_ocean_bake(struct Ocean *o, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data) { - /* note: some of these values remain uninitialized unless certain options + /* NOTE(campbell): some of these values remain uninitialized unless certain options * are enabled, take care that BKE_ocean_eval_ij() initializes a member - * before use - campbell */ + * before use. */ OceanResult ocr; ImageFormatData imf = {0}; @@ -1437,7 +1437,7 @@ void BKE_ocean_bake(struct Ocean *o, rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4 * (res_x * y + x)], ocr.disp); if (o->_do_jacobian) { - /* TODO: cleanup unused code - campbell */ + /* TODO(campbell): cleanup unused code. */ float /* r, */ /* UNUSED */ pr = 0.0f, foam_result; float neg_disp, neg_eplus; diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 87239d160b4..78e7e11c248 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -527,7 +527,7 @@ static void unpack_generate_paths(const char *name, BLI_split_dirfile(name, tempdir, tempname, sizeof(tempdir), sizeof(tempname)); if (tempname[0] == '\0') { - /* Note: we generally do not have any real way to re-create extension out of data. */ + /* NOTE: we generally do not have any real way to re-create extension out of data. */ BLI_strncpy(tempname, id->name + 2, sizeof(tempname)); printf("%s\n", tempname); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index a7c6dc2deb9..1af66fa090b 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -128,8 +128,8 @@ static void palette_blend_read_data(BlendDataReader *reader, ID *id) static void palette_undo_preserve(BlendLibReader *UNUSED(reader), ID *id_new, ID *id_old) { /* Whole Palette is preserved across undo-steps, and it has no extra pointer, simple. */ - /* Note: We do not care about potential internal references to self here, Palette has none. */ - /* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be + /* NOTE: We do not care about potential internal references to self here, Palette has none. */ + /* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be * fairly delicate. */ BKE_lib_id_swap(NULL, id_new, id_old); SWAP(IDProperty *, id_new->properties, id_old->properties); @@ -2067,7 +2067,7 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object) /* If a sculpt session is active, ensure we have its faceset data porperly up-to-date. */ object->sculpt->face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); - /* Note: In theory we could add that on the fly when required by sculpt code. + /* NOTE: In theory we could add that on the fly when required by sculpt code. * But this then requires proper update of depsgraph etc. For now we play safe, optimization is * always possible later if it's worth it. */ BKE_sculpt_mask_layers_ensure(object, mmd); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d386967bf8b..db1fbb56125 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2811,7 +2811,7 @@ static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim) task->rng_path = BLI_rng_new(seed); } -/* note: this function must be thread safe, except for branching! */ +/* NOTE: this function must be thread safe, except for branching! */ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cpa, ParticleCacheKey *child_keys, @@ -3961,7 +3961,7 @@ static ModifierData *object_add_or_copy_particle_system( psys->totpart = 0; psys->flag = PSYS_CURRENT; if (scene != NULL) { - psys->cfra = BKE_scene_frame_to_ctime(scene, CFRA + 1); + psys->cfra = BKE_scene_frame_to_ctime(scene, scene->r.cfra + 1); } DEG_relations_tag_update(bmain); @@ -5400,8 +5400,8 @@ void BKE_particle_system_blend_read_lib(BlendLibReader *reader, BLO_read_id_address(reader, id->lib, &psys->target_ob); if (psys->clmd) { - /* XXX - from reading existing code this seems correct but intended usage of - * pointcache /w cloth should be added in 'ParticleSystem' - campbell */ + /* XXX(campbell): from reading existing code this seems correct but intended usage of + * pointcache /w cloth should be added in 'ParticleSystem'. */ psys->clmd->point_cache = psys->pointcache; psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = NULL; BLO_read_id_address(reader, id->lib, &psys->clmd->coll_parms->group); diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index 2231731287d..415147fb36a 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -331,7 +331,7 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, int totkeys, k; float max_length; - /* TODO for the future: use true particle modifiers that work on the whole curve */ + /* TODO: for the future: use true particle modifiers that work on the whole curve. */ (void)modifiers; (void)mod; diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 1fd99bb2cbd..863476c6638 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -472,7 +472,7 @@ static int distribute_binary_search(const float *sum, int n, float value) * be sure to keep up to date if this changes */ #define PSYS_RND_DIST_SKIP 3 -/* note: this function must be thread safe, for from == PART_FROM_CHILD */ +/* NOTE: this function must be thread safe, for `from == PART_FROM_CHILD`. */ #define ONLY_WORKING_WITH_PA_VERTS 0 static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p) { @@ -1214,7 +1214,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, * It allows us to consider pos as 'midpoint between v and v+1' * (or 'p and p+1', depending whether we have more vertices than particles or not), * and avoid stumbling over float impression in element_sum. - * Note: moved face and volume distribution to this as well (instead of starting at zero), + * NOTE: moved face and volume distribution to this as well (instead of starting at zero), * for the same reasons, see T52682. */ pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index c35f703b072..06d3daaf4d6 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -447,9 +447,9 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, Partic MEM_freeN(nodedmelem); } else { - /* TODO PARTICLE, make the following line unnecessary, each function + /* TODO_PARTICLE: make the following line unnecessary, each function * should know to use the num or num_dmcache, set the num_dmcache to - * an invalid value, just in case */ + * an invalid value, just in case. */ LOOP_PARTICLES { @@ -992,9 +992,9 @@ void psys_get_birth_coords( /* (part->rotmode == PART_ROT_NOR_TAN) */ float tmat[3][3]; - /* note: utan_local is not taken from 'utan', we calculate from rot_vec/vtan */ - /* note: it looks like rotation phase may be applied twice (once with vtan, again below) - * however this isn't the case - campbell */ + /* NOTE: utan_local is not taken from 'utan', we calculate from rot_vec/vtan. */ + /* NOTE(campbell): it looks like rotation phase may be applied twice + * (once with vtan, again below) however this isn't the case. */ float *rot_vec_local = tmat[0]; float *vtan_local = tmat[1]; float *utan_local = tmat[2]; @@ -1014,7 +1014,7 @@ void psys_get_birth_coords( cross_v3_v3v3(utan_local, vtan_local, rot_vec_local); cross_v3_v3v3(vtan_local, utan_local, rot_vec_local); - /* note: no need to normalize */ + /* NOTE: no need to normalize. */ mat3_to_quat(q2, tmat); } @@ -2617,7 +2617,7 @@ static float collision_newton_rhapson(ParticleCollision *col, * here. */ if (d1 == d0) { /* If first iteration, try from other end where the gradient may be - * greater. Note: code duplicated below. */ + * greater. NOTE: code duplicated below. */ if (iter == 0) { t0 = 1.0f; collision_interpolate_element(pce, t0, col->f, col); @@ -2638,7 +2638,7 @@ static float collision_newton_rhapson(ParticleCollision *col, t1 -= d1 * dd; /* Particle moving away from plane could also mean a strangely rotating - * face, so check from end. Note: code duplicated above. */ + * face, so check from end. NOTE: code duplicated above. */ if (iter == 0 && t1 < 0.0f) { t0 = 1.0f; collision_interpolate_element(pce, t0, col->f, col); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 0d84022da77..461ffa7765e 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1053,7 +1053,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, const int v = vtri[j]; if (pbvh->verts[v].flag & ME_VERT_PBVH_UPDATE) { - /* Note: This avoids `lock, add_v3_v3, unlock` + /* NOTE: This avoids `lock, add_v3_v3, unlock` * and is five to ten times quicker than a spin-lock. * Not exact equivalent though, since atomicity is only ensured for one component * of the vector at a time, but here it shall not make any sensible difference. */ @@ -2157,7 +2157,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, const float *co[3]; if (origco) { - /* intersect with backuped original coordinates */ + /* Intersect with backed up original coordinates. */ co[0] = origco[face_verts[0]]; co[1] = origco[face_verts[1]]; co[2] = origco[face_verts[2]]; @@ -2798,7 +2798,7 @@ float (*BKE_pbvh_vert_coords_alloc(PBVH *pbvh))[3] void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int totvert) { if (totvert != pbvh->totvert) { - BLI_assert(!"PBVH: Given deforming vcos number does not natch PBVH vertex number!"); + BLI_assert_msg(0, "PBVH: Given deforming vcos number does not natch PBVH vertex number!"); return; } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index c2483b265a5..d3d7f02ecad 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -1324,7 +1324,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh, /* For all remaining faces of v_del, create a new face that is the * same except it uses v_conn instead of v_del */ - /* Note: this could be done with BM_vert_splice(), but that + /* NOTE: this could be done with BM_vert_splice(), but that * requires handling other issues like duplicate edges, so doesn't * really buy anything. */ BLI_buffer_clear(deleted_faces); diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 948b57578dc..84c4ae4dead 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -30,7 +30,7 @@ typedef struct { float bmin[3], bmax[3], bcentroid[3]; } BBC; -/* Note: this structure is getting large, might want to split it into +/* NOTE: this structure is getting large, might want to split it into * union'd structs */ struct PBVHNode { /* Opaque handle for drawing code */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index a05eb6962ce..9ed5b0230e6 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -849,7 +849,7 @@ static void ptcache_rigidbody_interpolate(int index, dfra = cfra2 - cfra1; - /* note: keys[0] and keys[3] unused for type < 1 (crappy) */ + /* NOTE: keys[0] and keys[3] unused for type < 1 (crappy). */ psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true); interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); @@ -1837,7 +1837,7 @@ static void ptcache_data_copy(void *from[], void *to[]) { int i; for (i = 0; i < BPHYS_TOT_DATA; i++) { - /* note, durian file 03.4b_comp crashes if to[i] is not tested + /* NOTE: durian file 03.4b_comp crashes if to[i] is not tested * its NULL, not sure if this should be fixed elsewhere but for now its needed */ if (from[i] && to[i]) { memcpy(to[i], from[i], ptcache_data_size[i]); @@ -2807,8 +2807,8 @@ void BKE_ptcache_id_time( cache = pid->cache; if (timescale) { - time = BKE_scene_frame_get(scene); - nexttime = BKE_scene_frame_to_ctime(scene, CFRA + 1.0f); + time = BKE_scene_ctime_get(scene); + nexttime = BKE_scene_frame_to_ctime(scene, scene->r.cfra + 1); *timescale = MAX2(nexttime - time, 0.0f); } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 2d4cce4b953..328c54fc21b 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -367,7 +367,7 @@ static Mesh *rigidbody_get_mesh(Object *ob) } /* Just return something sensible so that at least Blender won't crash. */ - BLI_assert(!"Unknown mesh source"); + BLI_assert_msg(0, "Unknown mesh source"); return BKE_object_get_evaluated_mesh(ob); } @@ -1787,7 +1787,7 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, rigidbody_update_sim_world(scene, rbw); - /* XXX TODO For rebuild: remove all constraints first. + /* XXX TODO: For rebuild: remove all constraints first. * Otherwise we can end up deleting objects that are still * referenced by constraints, corrupting bullet's internal list. * @@ -1811,11 +1811,12 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, /* validate that we've got valid object set up here... */ RigidBodyOb *rbo = ob->rigidbody_object; - /* TODO remove this whole block once we are sure we never get NULL rbo here anymore. */ + /* TODO: remove this whole block once we are sure we never get NULL rbo here anymore. */ /* This cannot be done in CoW evaluation context anymore... */ if (rbo == NULL) { - BLI_assert(!"CoW object part of RBW object collection without RB object data, " - "should not happen.\n"); + BLI_assert_msg(0, + "CoW object part of RBW object collection without RB object data, " + "should not happen.\n"); /* Since this object is included in the sim group but doesn't have * rigid body settings (perhaps it was added manually), add! * - assume object to be active? That is the default for newly added settings... @@ -1868,11 +1869,12 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, /* validate that we've got valid object set up here... */ RigidBodyCon *rbc = ob->rigidbody_constraint; - /* TODO remove this whole block once we are sure we never get NULL rbo here anymore. */ + /* TODO: remove this whole block once we are sure we never get NULL rbo here anymore. */ /* This cannot be done in CoW evaluation context anymore... */ if (rbc == NULL) { - BLI_assert(!"CoW object part of RBW constraints collection without RB constraint data, " - "should not happen.\n"); + BLI_assert_msg(0, + "CoW object part of RBW constraints collection without RB constraint data, " + "should not happen.\n"); /* Since this object is included in the group but doesn't have * constraint settings (perhaps it was added manually), add! */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 84741038164..cc5a8536a5a 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -192,7 +192,7 @@ static void scene_init_data(ID *id) BLI_strncpy(scene->r.pic, U.renderdir, sizeof(scene->r.pic)); - /* Note; in header_info.c the scene copy happens..., + /* NOTE: in header_info.c the scene copy happens..., * if you add more to renderdata it has to be checked there. */ /* multiview - stereo */ @@ -1045,7 +1045,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres static void direct_link_paint_helper(BlendDataReader *reader, const Scene *scene, Paint **paint) { - /* TODO. is this needed */ + /* TODO: is this needed. */ BLO_read_data_address(reader, paint); if (*paint) { @@ -1899,14 +1899,14 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src) sce_dst->eevee = sce_src->eevee; sce_dst->eevee.light_cache_data = NULL; sce_dst->eevee.light_cache_info[0] = '\0'; - /* TODO Copy the cache. */ + /* TODO: Copy the cache. */ } Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) { Scene *sce_copy; - /* TODO this should/could most likely be replaced by call to more generic code at some point... + /* TODO: this should/could most likely be replaced by call to more generic code at some point... * But for now, let's keep it well isolated here. */ if (type == SCE_COPY_EMPTY) { ListBase rv; @@ -2299,10 +2299,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene) return NULL; } - const int cfra = ((scene->r.images == scene->r.framapto) ? - scene->r.cfra : - (int)(scene->r.cfra * - ((float)scene->r.framapto / (float)scene->r.images))); + const int ctime = (int)BKE_scene_ctime_get(scene); int frame = -(MAXFRAME + 1); int min_frame = MAXFRAME + 1; Object *camera = NULL; @@ -2310,11 +2307,11 @@ Object *BKE_scene_camera_switch_find(Scene *scene) LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) { if (m->camera && (m->camera->restrictflag & OB_RESTRICT_RENDER) == 0) { - if ((m->frame <= cfra) && (m->frame > frame)) { + if ((m->frame <= ctime) && (m->frame > frame)) { camera = m->camera; frame = m->frame; - if (frame == cfra) { + if (frame == ctime) { break; } } @@ -2396,13 +2393,13 @@ const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame) return best_marker ? best_marker->name : NULL; } -int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int cfra) +int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int frame) { const int fps = round_db_to_int(FPS * interval_in_seconds); - const int second_prev = cfra - mod_i(cfra, fps); + const int second_prev = frame - mod_i(frame, fps); const int second_next = second_prev + fps; - const int delta_prev = cfra - second_prev; - const int delta_next = second_next - cfra; + const int delta_prev = frame - second_prev; + const int delta_next = second_next - frame; return (delta_prev < delta_next) ? second_prev : second_next; } @@ -2444,16 +2441,17 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) return true; } -/** - * This function is needed to cope with fractional frames, needed for motion blur & physics. - */ -float BKE_scene_frame_get(const Scene *scene) +/* Return fractional frame number taking into account subframes and time + * remapping. This the time value used by animation, modifiers and physics + * evaluation. */ +float BKE_scene_ctime_get(const Scene *scene) { return BKE_scene_frame_to_ctime(scene, scene->r.cfra); } -/* This function is used to obtain arbitrary fractional frames */ -float BKE_scene_frame_to_ctime(const Scene *scene, const float frame) +/* Convert integer frame number to fractional frame number taking into account + * subframes and time remapping. */ +float BKE_scene_frame_to_ctime(const Scene *scene, const int frame) { float ctime = frame; ctime += scene->r.subframe; @@ -2461,13 +2459,18 @@ float BKE_scene_frame_to_ctime(const Scene *scene, const float frame) return ctime; } -/** - * Sets the frame int/float components. - */ -void BKE_scene_frame_set(struct Scene *scene, double cfra) + +/* Get current fractional frame based on frame and subframe. */ +float BKE_scene_frame_get(const Scene *scene) +{ + return scene->r.cfra + scene->r.subframe; +} + +/* Set current frame and subframe based on a fractional frame. */ +void BKE_scene_frame_set(Scene *scene, float frame) { double intpart; - scene->r.subframe = modf(cfra, &intpart); + scene->r.subframe = modf((double)frame, &intpart); scene->r.cfra = (int)intpart; } @@ -2736,8 +2739,8 @@ void BKE_scene_graph_update_for_newframe_ex(Depsgraph *depsgraph, const bool cle * edits from callback are properly taken into account. Doing a time update on those would * lose any possible unkeyed changes made by the handler. */ if (pass == 0) { - const float ctime = BKE_scene_frame_get(scene); - DEG_evaluate_on_framechange(depsgraph, ctime); + const float frame = BKE_scene_frame_get(scene); + DEG_evaluate_on_framechange(depsgraph, frame); } else { DEG_evaluate_on_refresh(depsgraph); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 608317933f5..c3885b5dcf7 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -101,7 +101,7 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area { BKE_LIB_FOREACHID_PROCESS(data, area->full, IDWALK_CB_NOP); - /* TODO this should be moved to a callback in `SpaceType`, defined in each editor's own code. + /* TODO: this should be moved to a callback in `SpaceType`, defined in each editor's own code. * Will be for a later round of cleanup though... */ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { switch (sl->spacetype) { @@ -289,7 +289,7 @@ bool BKE_screen_blend_read_data(BlendDataReader *reader, bScreen *screen) return success; } -/* note: file read without screens option G_FILE_NO_UI; +/* NOTE: file read without screens option G_FILE_NO_UI; * check lib pointers in call below */ static void screen_blend_read_lib(BlendLibReader *reader, ID *id) { @@ -682,19 +682,13 @@ void BKE_area_region_free(SpaceType *st, ARegion *region) BKE_area_region_panels_free(®ion->panels); LISTBASE_FOREACH (uiList *, uilst, ®ion->ui_lists) { - if (uilst->dyn_data) { - uiListDyn *dyn_data = uilst->dyn_data; - if (dyn_data->items_filter_flags) { - MEM_freeN(dyn_data->items_filter_flags); - } - if (dyn_data->items_filter_neworder) { - MEM_freeN(dyn_data->items_filter_neworder); - } - MEM_freeN(dyn_data); + if (uilst->dyn_data && uilst->dyn_data->free_runtime_data_fn) { + uilst->dyn_data->free_runtime_data_fn(uilst); } if (uilst->properties) { IDP_FreeProperty(uilst->properties); } + MEM_SAFE_FREE(uilst->dyn_data); } if (region->gizmo_map != NULL) { @@ -1734,6 +1728,12 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) sfile->runtime = NULL; BLO_read_data_address(reader, &sfile->params); BLO_read_data_address(reader, &sfile->asset_params); + if (sfile->params) { + sfile->params->rename_id = NULL; + } + if (sfile->asset_params) { + sfile->asset_params->base_params.rename_id = NULL; + } } else if (sl->spacetype == SPACE_ACTION) { SpaceAction *saction = (SpaceAction *)sl; diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c index b537bdc5479..29cbe05f4d1 100644 --- a/source/blender/blenkernel/intern/shader_fx.c +++ b/source/blender/blenkernel/intern/shader_fx.c @@ -81,7 +81,7 @@ ShaderFxData *BKE_shaderfx_new(int type) const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(type); ShaderFxData *fx = MEM_callocN(fxi->struct_size, fxi->struct_name); - /* note, this name must be made unique later */ + /* NOTE: this name must be made unique later. */ BLI_strncpy(fx->name, DATA_(fxi->name), sizeof(fx->name)); fx->type = type; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index aeb8133974e..7c0c28d664e 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -493,7 +493,7 @@ bool BKE_shrinkwrap_project_normal(char options, } if (options & MOD_SHRINKWRAP_CULL_TARGET_MASK) { - /* apply backface */ + /* Apply back-face. */ const float dot = dot_v3v3(dir, hit_tmp.no); if (((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) || ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f)) { @@ -502,7 +502,7 @@ bool BKE_shrinkwrap_project_normal(char options, } if (transf) { - /* Inverting space transform (TODO make coeherent with the initial dist readjust) */ + /* Inverting space transform (TODO: make coherent with the initial dist readjust). */ BLI_space_transform_invert(transf, hit_tmp.co); #ifdef USE_DIST_CORRECT hit_tmp.dist = len_v3v3(vert, hit_tmp.co); @@ -1440,7 +1440,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob_target = DEG_get_evaluated_object(ctx->depsgraph, smd->target); calc.target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); - /* TODO there might be several "bugs" with non-uniform scales matrices + /* TODO: there might be several "bugs" with non-uniform scales matrices * because it will no longer be nearest surface, not sphere projection * because space has been deformed */ BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, ob_target); @@ -1460,7 +1460,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, ssmd.subdivType = ME_CC_SUBSURF; /* catmull clark */ ssmd.levels = smd->subsurfLevels; /* levels */ - /* TODO to be moved to Mesh once we are done with changes in subsurf code. */ + /* TODO: to be moved to Mesh once we are done with changes in subsurf code. */ DerivedMesh *dm = CDDM_from_mesh(mesh); ss_mesh = subsurf_make_derived_from_derived( diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 9d871777c61..e4e2ed94b41 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -901,7 +901,7 @@ static void free_softbody_baked(SoftBody *sb) static void free_scratch(SoftBody *sb) { if (sb->scratch) { - /* todo make sure everything is cleaned up nicly */ + /* TODO: make sure everything is cleaned up nicely. */ if (sb->scratch->colliderhash) { BLI_ghash_free(sb->scratch->colliderhash, NULL, @@ -973,7 +973,7 @@ static void free_softbody_intern(SoftBody *sb) * and need to tell their neighbors exactly what happens via spring forces * unless sbObjectStep( .. ) is called on sub frame timing level * BTW that also questions the use of a 'implicit' solvers on softbodies - * since that would only valid for 'slow' moving collision targets and dito particles + * since that would only valid for 'slow' moving collision targets and ditto particles. */ /* +++ dependency information functions. */ @@ -1907,7 +1907,7 @@ static void sb_spring_force( #endif } else { - /* TODO make this debug option */ + /* TODO: make this debug option. */ CLOG_WARN(&LOG, "bodypoint <bpi> is not attached to spring <*bs>"); return; } @@ -1994,12 +1994,12 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, return 999; } - /* debugerin */ + /* Debugging. */ if (sb->totpoint < ifirst) { printf("Aye 998"); return 998; } - /* debugerin */ + /* Debugging. */ bp = &sb->bpoint[ifirst]; for (bb = number_of_points_here; bb > 0; bb--, bp++) { @@ -2413,9 +2413,9 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float * copy_v3_v3(dx, bp->vec); } - /* so here is (x)'= v(elocity) */ - /* the euler step for location then becomes */ - /* x(t + dt) = x(t) + v(t~) * dt */ + /* So here is: `(x)'= v(elocity)`. + * The euler step for location then becomes: + * `x(t + dt) = x(t) + v(t~) * dt` */ mul_v3_fl(dx, forcetime); /* the freezer coming sooner or later */ @@ -2644,7 +2644,7 @@ static void interpolate_exciter(Object *ob, int timescale, int time) */ /* Resetting a Mesh SB object's springs */ -/* Spring length are caculted from'raw' mesh vertices that are NOT altered by modifier stack. */ +/* Spring length are calculated from 'raw' mesh vertices that are NOT altered by modifier stack. */ static void springs_from_mesh(Object *ob) { SoftBody *sb; @@ -2704,8 +2704,8 @@ static void mesh_to_softbody(Object *ob) bp = sb->bpoint; defgroup_index = me->dvert ? (sb->vertgroup - 1) : -1; - defgroup_index_mass = me->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Mass) : -1; - defgroup_index_spring = me->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Spring_K) : + defgroup_index_mass = me->dvert ? BKE_id_defgroup_name_index(&me->id, sb->namedVG_Mass) : -1; + defgroup_index_spring = me->dvert ? BKE_id_defgroup_name_index(&me->id, sb->namedVG_Spring_K) : -1; for (a = 0; a < me->totvert; a++, bp++) { @@ -2934,8 +2934,8 @@ static void lattice_to_softbody(Object *ob) bp = sb->bpoint; defgroup_index = lt->dvert ? (sb->vertgroup - 1) : -1; - defgroup_index_mass = lt->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Mass) : -1; - defgroup_index_spring = lt->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Spring_K) : + defgroup_index_mass = lt->dvert ? BKE_id_defgroup_name_index(<->id, sb->namedVG_Mass) : -1; + defgroup_index_spring = lt->dvert ? BKE_id_defgroup_name_index(<->id, sb->namedVG_Spring_K) : -1; /* same code used as for mesh vertices */ @@ -3009,7 +3009,7 @@ static void curve_surf_to_softbody(Object *ob) for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->bezt) { - /* Bezier case; this is nicly said naive; who ever wrote this part, + /* Bezier case; this is nicely said naive; who ever wrote this part, * it was not me (JOW) :). * * a: never ever make tangent handles (sub) and or (ob)ject to collision. @@ -3086,7 +3086,7 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, if (sb->solverflags & SBSO_ESTIMATEIPO) { SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale); } - /* inverse matrix is not uptodate... */ + /* Inverse matrix is not up to date. */ invert_m4_m4(ob->imat, ob->obmat); for (a = 0; a < numVerts; a++, bp++) { diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index f4a9d328d86..fcb992e1535 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -824,7 +824,7 @@ void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated) void BKE_sound_update_sequencer(Main *main, bSound *sound) { - BLI_assert(!"is not supposed to be used, is weird function."); + BLI_assert_msg(0, "is not supposed to be used, is weird function."); Scene *scene; diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index aa0d95d4d61..6234cdf87e2 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -512,6 +512,10 @@ void Spline::sample_with_index_factors(const GVArray &src, using T = decltype(dummy); const GVArray_Typed<T> src_typed = src.typed<T>(); MutableSpan<T> dst_typed = dst.typed<T>(); + if (src.size() == 1) { + dst_typed.fill(src_typed[0]); + return; + } blender::threading::parallel_for(dst_typed.index_range(), 1024, [&](IndexRange range) { for (const int i : range) { const LookupResult interp = this->lookup_data_from_index_factor(index_factors[i]); diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index 02d26ac715b..b6764f65631 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -333,6 +333,46 @@ void BezierSpline::correct_end_tangents() const } } +/** + * De Casteljau Bezier subdivision. + * \param index: The index of the segment's start control point. + * \param next_index: The index of the control point at the end of the segment. Could be 0, + * if the spline is cyclic. + * \param parameter: The factor along the segment, between 0 and 1. Note that this is used + * directly by the calculation, it doesn't correspond to a portion of the evaluated length. + * + * <pre> + * handle_prev handle_next + * x----------------x + * / \ + * / x---O---x \ + * / result \ + * / \ + * O O + * point_prev point_next + * </pre> + */ +BezierSpline::InsertResult BezierSpline::calculate_segment_insertion(const int index, + const int next_index, + const float parameter) +{ + BLI_assert(parameter <= 1.0f && parameter >= 0.0f); + BLI_assert(next_index == 0 || next_index == index + 1); + const float3 &point_prev = positions_[index]; + const float3 &handle_prev = handle_positions_right_[index]; + const float3 &handle_next = handle_positions_left_[next_index]; + const float3 &point_next = positions_[next_index]; + const float3 center_point = float3::interpolate(handle_prev, handle_next, parameter); + + BezierSpline::InsertResult result; + result.handle_prev = float3::interpolate(point_prev, handle_prev, parameter); + result.handle_next = float3::interpolate(handle_next, point_next, parameter); + result.left_handle = float3::interpolate(result.handle_prev, center_point, parameter); + result.right_handle = float3::interpolate(center_point, result.handle_next, parameter); + result.position = float3::interpolate(result.left_handle, result.right_handle, parameter); + return result; +} + static void bezier_forward_difference_3d(const float3 &point_0, const float3 &point_1, const float3 &point_2, diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index 76d046337c0..ac6f1bd082c 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -346,7 +346,10 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const const int size = this->size(); const int eval_size = this->evaluated_points_size(); - BLI_assert(this->evaluated_edges_size() > 0); + if (eval_size == 0) { + return {}; + } + basis_cache_.resize(eval_size); const int order = this->order(); diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index 4cc2d101b02..dc5162f201e 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -1352,7 +1352,7 @@ static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl) ITER_PIXELS_END; } -void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4]) +void BKE_studiolight_default(SolidLight lights[4], float light_ambient[3]) { copy_v3_fl3(light_ambient, 0.0, 0.0, 0.0); diff --git a/source/blender/blenkernel/intern/subdiv.c b/source/blender/blenkernel/intern/subdiv.c index e6b51c586c3..fd32f52351a 100644 --- a/source/blender/blenkernel/intern/subdiv.c +++ b/source/blender/blenkernel/intern/subdiv.c @@ -68,7 +68,7 @@ eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int case SUBSURF_UV_SMOOTH_ALL: return SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE; } - BLI_assert(!"Unknown uv smooth flag"); + BLI_assert_msg(0, "Unknown uv smooth flag"); return SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL; } @@ -81,7 +81,7 @@ eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsu case SUBSURF_BOUNDARY_SMOOTH_ALL: return SUBDIV_VTX_BOUNDARY_EDGE_ONLY; } - BLI_assert(!"Unknown boundary smooth flag"); + BLI_assert_msg(0, "Unknown boundary smooth flag"); return SUBDIV_VTX_BOUNDARY_EDGE_ONLY; } diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index 8b672b2cb49..95f51a72b70 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -1509,7 +1509,7 @@ static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_cc ++result.y; } else { - BLI_assert(!"non-boundary element given"); + BLI_assert_msg(0, "non-boundary element given"); } return result; } diff --git a/source/blender/blenkernel/intern/subdiv_converter.c b/source/blender/blenkernel/intern/subdiv_converter.c index d5c75503500..39b701da262 100644 --- a/source/blender/blenkernel/intern/subdiv_converter.c +++ b/source/blender/blenkernel/intern/subdiv_converter.c @@ -44,7 +44,7 @@ int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSe case SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER: return OSD_VTX_BOUNDARY_EDGE_AND_CORNER; } - BLI_assert(!"Unknown vtx boundary interpolation"); + BLI_assert_msg(0, "Unknown vtx boundary interpolation"); return OSD_VTX_BOUNDARY_EDGE_ONLY; } @@ -65,6 +65,6 @@ int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSe case SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL: return OSD_FVAR_LINEAR_INTERPOLATION_ALL; } - BLI_assert(!"Unknown fvar linear interpolation"); + BLI_assert_msg(0, "Unknown fvar linear interpolation"); return OSD_FVAR_LINEAR_INTERPOLATION_NONE; } diff --git a/source/blender/blenkernel/intern/subdiv_eval.c b/source/blender/blenkernel/intern/subdiv_eval.c index 693827f99ac..0001eb8a205 100644 --- a/source/blender/blenkernel/intern/subdiv_eval.c +++ b/source/blender/blenkernel/intern/subdiv_eval.c @@ -137,7 +137,7 @@ bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv, { if (subdiv->evaluator == NULL) { /* NOTE: This situation is supposed to be handled by begin(). */ - BLI_assert(!"Is not supposed to happen"); + BLI_assert_msg(0, "Is not supposed to happen"); return false; } /* Set coordinates of base mesh vertices. */ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 0dbfeaaaadb..cff2c5cc562 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2352,7 +2352,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm, const bool ignore_simplify = (flags & SUBSURF_IGNORE_SIMPLIFY); CCGDerivedMesh *result; - /* note: editmode calculation can only run once per + /* NOTE: editmode calculation can only run once per * modifier stack evaluation (uses freed cache) T36299. */ if (flags & SUBSURF_FOR_EDIT_MODE) { int levels = (scene != NULL && !ignore_simplify) ? diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 74845e3f1b9..80ff8ce9162 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -176,7 +176,7 @@ static void text_blend_write(BlendWriter *writer, ID *id, const void *id_address } Text *text = (Text *)id; - /* Note: we are clearing local temp data here, *not* the flag in the actual 'real' ID. */ + /* NOTE: we are clearing local temp data here, *not* the flag in the actual 'real' ID. */ if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) { text->flags &= ~TXT_ISEXT; } @@ -2397,7 +2397,7 @@ int text_check_bracket(const char ch) return 0; } -/* TODO, have a function for operators - +/* TODO: have a function for operators - * http://docs.python.org/py3k/reference/lexical_analysis.html#operators */ bool text_check_delim(const char ch) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index f3d6bc4a6e3..068d048fd08 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1525,7 +1525,7 @@ MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int fram const int num_markers = track->markersnr; if (num_markers == 0) { - BLI_assert(!"Detected degenerated track, should never happen."); + BLI_assert_msg(0, "Detected degenerated track, should never happen."); return NULL; } diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c index ef36acdc3d5..179def0a6f2 100644 --- a/source/blender/blenkernel/intern/tracking_region_tracker.c +++ b/source/blender/blenkernel/intern/tracking_region_tracker.c @@ -155,7 +155,7 @@ static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, return tracking_context_get_frame_ibuf(clip, user, clip_flag, keyed_framenr); } -/* Get image buffer which si used as reference for track. */ +/* Get image buffer which is used as reference for track. */ static ImBuf *tracking_context_get_reference_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag, diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 3dff750edfb..d5585116f7e 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -376,7 +376,7 @@ static MovieTrackingMarker *get_tracking_data_point(StabContext *ctx, * always guesswork. * * As a simple default, we use the weighted average of the location markers - * of the current frame as pivot point. TODO It is planned to add further + * of the current frame as pivot point. TODO: It is planned to add further * options, like e.g. anchoring the pivot point at the canvas. Moreover, * it is planned to allow for a user controllable offset. */ @@ -661,7 +661,7 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_ int next_higher = MAXFRAME; use_values_from_fcurves(ctx, true); LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { - /* Note: we deliberately do not care if this track + /* NOTE: we deliberately do not care if this track * is already initialized for stabilization. */ if (track->flag & TRACK_USE_2D_STAB) { int startpoint = search_closest_marker_index(track, framenr); diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index ea0d92cf78e..16b36e94328 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -523,7 +523,7 @@ static void distortion_model_parameters_from_options( /* Libmv returned distortion model which is not known to Blender. This is a logical error in code * and Blender side is to be updated to match Libmv. */ - BLI_assert(!"Unknown distortion model"); + BLI_assert_msg(0, "Unknown distortion model"); } /* Fill in Libmv C-API camera intrinsics options from tracking structure. */ diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index 14dd286a315..e524bd254bb 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -140,7 +140,7 @@ static void undosys_id_ref_store(void *UNUSED(user_data), UndoRefID *id_ref) static void undosys_id_ref_resolve(void *user_data, UndoRefID *id_ref) { - /* Note: we could optimize this, + /* NOTE: we could optimize this, * for now it's not too bad since it only runs when we access undo! */ Main *bmain = user_data; ListBase *lb = which_libbase(bmain, GS(id_ref->name)); @@ -717,11 +717,31 @@ eUndoStepDir BKE_undosys_step_calc_direction(const UndoStack *ustack, } } - BLI_assert(!"Target undo step not found, this should not happen and may indicate an undo stack corruption"); + BLI_assert_msg(0, + "Target undo step not found, this should not happen and may indicate an undo " + "stack corruption"); return STEP_INVALID; } /** + * When reading undo steps for undo/redo, + * some extra checks are needed when so the correct undo step is decoded. + */ +static UndoStep *undosys_step_iter_first(UndoStep *us_reference, const eUndoStepDir undo_dir) +{ + if (us_reference->type->flags & UNDOTYPE_FLAG_DECODE_ACTIVE_STEP) { + /* Reading this step means an undo action reads undo twice. + * This should be avoided where possible, however some undo systems require it. + * + * Redo skips the current state as this represents the currently loaded state. */ + return (undo_dir == -1) ? us_reference : us_reference->next; + } + + /* Typical case, skip reading the current undo step. */ + return (undo_dir == -1) ? us_reference->prev : us_reference->next; +} + +/** * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one. * * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the @@ -786,15 +806,10 @@ bool BKE_undosys_step_load_data_ex(UndoStack *ustack, us_target->type->name, undo_dir); - /* Undo/Redo steps until we reach given target step (or beyond if it has to be skipped), from - * given reference step. - * - * NOTE: Unlike with redo case, where we can expect current active step to fully reflect current - * data status, in undo case we also do reload the active step. - * FIXME: this feels weak, and should probably not be actually needed? Or should also be done in - * redo case? */ + /* Undo/Redo steps until we reach given target step (or beyond if it has to be skipped), + * from given reference step. */ bool is_processing_extra_skipped_steps = false; - for (UndoStep *us_iter = (undo_dir == -1) ? us_reference : us_reference->next; us_iter != NULL; + for (UndoStep *us_iter = undosys_step_iter_first(us_reference, undo_dir); us_iter != NULL; us_iter = (undo_dir == -1) ? us_iter->prev : us_iter->next) { BLI_assert(us_iter != NULL); diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 290b880934e..d9f02ce4c75 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -833,7 +833,7 @@ static char *find_next_op(const char *str, char *remaining_str, int len_max) return remaining_str + i; } } - BLI_assert(!"String should be NULL terminated"); + BLI_assert_msg(0, "String should be NULL terminated"); return remaining_str + i; } @@ -917,7 +917,7 @@ static int unit_scale_str(char *str, return 0; } - /* XXX - investigate, does not respect len_max properly. */ + /* XXX: investigate, does not respect len_max properly. */ char *str_found = (char *)unit_find_str(str, replace_str, case_sensitive); if (str_found == NULL) { @@ -931,7 +931,7 @@ static int unit_scale_str(char *str, /* Deal with unit bias for temperature units. Order of operations is important, so we * have to add parentheses, add the bias, then multiply by the scalar like usual. * - * Note: If these changes don't fit in the buffer properly unit evaluation has failed, + * NOTE: If these changes don't fit in the buffer properly unit evaluation has failed, * just try not to destroy anything while failing. */ if (unit->bias != 0.0) { /* Add the open parenthesis. */ diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 272ecc71833..b28d17df814 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -197,7 +197,7 @@ static struct VolumeFileCache { Entry &entry = (Entry &)*it; entry.num_metadata_users++; - /* Note: pointers to unordered_set values are not invalidated when adding + /* NOTE: pointers to unordered_set values are not invalidated when adding * or removing other values. */ return &entry; } diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index 533107b2bf6..5cac149c503 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" +#include "BKE_asset.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_idtype.h" @@ -53,6 +54,13 @@ /* -------------------------------------------------------------------- */ +static void workspace_init_data(ID *id) +{ + WorkSpace *workspace = (WorkSpace *)id; + + BKE_asset_library_reference_init_default(&workspace->active_asset_library); +} + static void workspace_free_data(ID *id) { WorkSpace *workspace = (WorkSpace *)id; @@ -180,7 +188,7 @@ IDTypeInfo IDType_ID_WS = { .translation_context = BLT_I18NCONTEXT_ID_WORKSPACE, .flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_MAKELOCAL | IDTYPE_FLAGS_NO_ANIMDATA, - .init_data = NULL, + .init_data = workspace_init_data, .copy_data = NULL, .free_data = workspace_free_data, .make_local = NULL, diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h index 2847bc960ad..52d41173a0e 100644 --- a/source/blender/blenlib/BLI_array_utils.h +++ b/source/blender/blenlib/BLI_array_utils.h @@ -28,52 +28,53 @@ extern "C" { #endif -void _bli_array_reverse(void *arr, unsigned int arr_len, size_t arr_stride); +void _bli_array_reverse(void *arr, uint arr_len, size_t arr_stride); #define BLI_array_reverse(arr, arr_len) _bli_array_reverse(arr, arr_len, sizeof(*(arr))) -void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir); +void _bli_array_wrap(void *arr, uint arr_len, size_t arr_stride, int dir); #define BLI_array_wrap(arr, arr_len, dir) _bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir) -void _bli_array_permute(void *arr, - const unsigned int arr_len, - const size_t arr_stride, - const unsigned int *order, - void *arr_temp); +void _bli_array_permute( + void *arr, const uint arr_len, const size_t arr_stride, const uint *order, void *arr_temp); #define BLI_array_permute(arr, arr_len, order) \ _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, NULL) #define BLI_array_permute_ex(arr, arr_len, order, arr_temp) \ _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp) -int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p); +uint _bli_array_deduplicate_ordered(void *arr, uint arr_len, size_t arr_stride); +#define BLI_array_deduplicate_ordered(arr, arr_len) \ + _bli_array_deduplicate_ordered(arr, arr_len, sizeof(*(arr))) + +int _bli_array_findindex(const void *arr, uint arr_len, size_t arr_stride, const void *p); #define BLI_array_findindex(arr, arr_len, p) _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p) -int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p); +int _bli_array_rfindindex(const void *arr, uint arr_len, size_t arr_stride, const void *p); #define BLI_array_rfindindex(arr, arr_len, p) \ _bli_array_rfindindex(arr, arr_len, sizeof(*(arr)), p) void _bli_array_binary_and( - void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride); + void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride); #define BLI_array_binary_and(arr, arr_a, arr_b, arr_len) \ (CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_a)), \ CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_b)), \ _bli_array_binary_and(arr, arr_a, arr_b, arr_len, sizeof(*(arr)))) void _bli_array_binary_or( - void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride); + void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride); #define BLI_array_binary_or(arr, arr_a, arr_b, arr_len) \ (CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_a)), \ CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_b)), \ _bli_array_binary_or(arr, arr_a, arr_b, arr_len, sizeof(*(arr)))) bool _bli_array_iter_span(const void *arr, - unsigned int arr_len, + uint arr_len, size_t arr_stride, bool use_wrap, bool use_delimit_bounds, bool (*test_fn)(const void *arr_item, void *user_data), void *user_data, - unsigned int span_step[2], - unsigned int *r_span_len); + uint span_step[2], + uint *r_span_len); #define BLI_array_iter_span( \ arr, arr_len, use_wrap, use_delimit_bounds, test_fn, user_data, span_step, r_span_len) \ _bli_array_iter_span(arr, \ @@ -86,7 +87,7 @@ bool _bli_array_iter_span(const void *arr, span_step, \ r_span_len) -bool _bli_array_is_zeroed(const void *arr, unsigned int arr_len, size_t arr_stride); +bool _bli_array_is_zeroed(const void *arr, uint arr_len, size_t arr_stride); #define BLI_array_is_zeroed(arr, arr_len) _bli_array_is_zeroed(arr, arr_len, sizeof(*(arr))) bool _bli_array_iter_spiral_square(const void *arr_v, diff --git a/source/blender/blenlib/BLI_assert.h b/source/blender/blenlib/BLI_assert.h index 685f526b4ad..6019f0f3566 100644 --- a/source/blender/blenlib/BLI_assert.h +++ b/source/blender/blenlib/BLI_assert.h @@ -31,6 +31,7 @@ extern "C" { /* Utility functions. */ void _BLI_assert_print_pos(const char *file, const int line, const char *function, const char *id); +void _BLI_assert_print_extra(const char *str); void _BLI_assert_print_backtrace(void); void _BLI_assert_abort(void); void _BLI_assert_unreachable_print(const char *file, const int line, const char *function); @@ -61,8 +62,17 @@ void _BLI_assert_unreachable_print(const char *file, const int line, const char _BLI_ASSERT_ABORT(), \ NULL)) : \ NULL) +/** A version of #BLI_assert() to pass an additional message to be printed on failure. */ +# define BLI_assert_msg(a, msg) \ + (void)((!(a)) ? ((_BLI_assert_print_backtrace(), \ + _BLI_ASSERT_PRINT_POS(a), \ + _BLI_assert_print_extra(msg), \ + _BLI_ASSERT_ABORT(), \ + NULL)) : \ + NULL) #else # define BLI_assert(a) ((void)0) +# define BLI_assert_msg(a, msg) ((void)0) #endif #if defined(__cplusplus) @@ -96,7 +106,7 @@ void _BLI_assert_unreachable_print(const char *file, const int line, const char #define BLI_assert_unreachable() \ { \ _BLI_assert_unreachable_print(__FILE__, __LINE__, __func__); \ - BLI_assert(!"This line of code is marked to be unreachable."); \ + BLI_assert_msg(0, "This line of code is marked to be unreachable."); \ } \ ((void)0) diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h index d42126fbe61..ec4cfe4801a 100644 --- a/source/blender/blenlib/BLI_endian_switch_inline.h +++ b/source/blender/blenlib/BLI_endian_switch_inline.h @@ -29,7 +29,7 @@ extern "C" { * \ingroup bli */ -/* note: using a temp char to switch endian is a lot slower, +/* NOTE: using a temp char to switch endian is a lot slower, * use bit shifting instead. */ /* *** 16 *** */ diff --git a/source/blender/blenlib/BLI_enumerable_thread_specific.hh b/source/blender/blenlib/BLI_enumerable_thread_specific.hh index a05f7724dd2..3051d980d45 100644 --- a/source/blender/blenlib/BLI_enumerable_thread_specific.hh +++ b/source/blender/blenlib/BLI_enumerable_thread_specific.hh @@ -46,25 +46,72 @@ template<typename T> class EnumerableThreadSpecific : NonCopyable, NonMovable { tbb::enumerable_thread_specific<T> values_; public: + using iterator = typename tbb::enumerable_thread_specific<T>::iterator; + + EnumerableThreadSpecific() = default; + + template<typename F> EnumerableThreadSpecific(F initializer) : values_(std::move(initializer)) + { + } + T &local() { return values_.local(); } + iterator begin() + { + return values_.begin(); + } + + iterator end() + { + return values_.end(); + } + #else /* WITH_TBB */ private: std::mutex mutex_; /* Maps thread ids to their corresponding values. The values are not embedded in the map, so that * their addresses do not change when the map grows. */ - Map<int, std::unique_ptr<T>> values_; + Map<int, std::reference_wrapper<T>> values_; + Vector<std::unique_ptr<T>> owned_values_; + std::function<void(void *)> initializer_; public: + using iterator = typename Map<int, std::reference_wrapper<T>>::MutableValueIterator; + + EnumerableThreadSpecific() : initializer_([](void *buffer) { new (buffer) T(); }) + { + } + + template<typename F> + EnumerableThreadSpecific(F initializer) + : initializer_([=](void *buffer) { new (buffer) T(initializer()); }) + { + } + T &local() { const int thread_id = enumerable_thread_specific_utils::thread_id; std::lock_guard lock{mutex_}; - return *values_.lookup_or_add_cb(thread_id, []() { return std::make_unique<T>(); }); + return values_.lookup_or_add_cb(thread_id, [&]() { + T *value = (T *)::operator new(sizeof(T)); + initializer_(value); + owned_values_.append(std::unique_ptr<T>{value}); + return std::reference_wrapper<T>{*value}; + }); + } + + iterator begin() + { + return values_.values().begin(); + } + + iterator end() + { + return values_.values().end(); } #endif /* WITH_TBB */ diff --git a/source/blender/blenlib/BLI_function_ref.hh b/source/blender/blenlib/BLI_function_ref.hh index 38e1ba593c5..70a064adc5d 100644 --- a/source/blender/blenlib/BLI_function_ref.hh +++ b/source/blender/blenlib/BLI_function_ref.hh @@ -95,7 +95,7 @@ template<typename Ret, typename... Params> class FunctionRef<Ret(Params...)> { * A pointer to the referenced callable object. This can be a C function, a lambda object or any * other callable. * - * The value does not need to be initialized because it is not used unless callback_ is set as + * The value does not need to be initialized because it is not used unless `callback_` is set as * well, in which case it will be initialized as well. * * Use `intptr_t` to avoid warnings when casting to function pointers. diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 43b31d76bb0..9ac14a6edfe 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -255,7 +255,7 @@ void limit_dist_v3(float v1[3], float v2[3], const float dist); /******************************* Intersection ********************************/ -/* TODO int return value consistency */ +/* TODO: int return value consistency. */ /* line-line */ #define ISECT_LINE_LINE_COLINEAR -1 diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 54df88ca541..e38df58c1ca 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -211,6 +211,7 @@ void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]); void mul_m3_v3_double(const float M[3][3], double r[3]); void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4]); +void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4]); void mul_m3_fl(float R[3][3], float f); void mul_m4_fl(float R[4][4], float f); @@ -277,7 +278,7 @@ bool is_orthonormal_m4(const float mat[4][4]); bool is_uniform_scaled_m3(const float mat[3][3]); bool is_uniform_scaled_m4(const float m[4][4]); -/* Note: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix! +/* NOTE: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix! * Nowadays 'adjoint' usually refers to the conjugate transpose, * which for real-valued matrices is simply the transpose. */ diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index ef10d02f10f..461b5a60c9d 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -90,7 +90,7 @@ void tri_to_quat_ex(float quat[4], const float no_orig[3]); float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3]); void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag); -/* note: v1 and v2 must be normalized */ +/* NOTE: v1 and v2 must be normalized. */ void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3]); void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]); void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4]); diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index d7798f12fcc..b2e05b00735 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -50,6 +50,8 @@ void *BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESU void *BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2); +void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src) ATTR_NONNULL(1, 2); + void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1); #ifdef __cplusplus diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index bdbbda9f0c7..14eca49d126 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -309,6 +309,12 @@ template<typename T> void uninitialized_fill_n(T *dst, int64_t n, const T &value } template<typename T> struct DestructValueAtAddress { + DestructValueAtAddress() = default; + + template<typename U> DestructValueAtAddress(const U &) + { + } + void operator()(T *ptr) { ptr->~T(); diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index e5e0df02033..61b572a4943 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -65,7 +65,10 @@ void *BLI_mempool_as_arrayN(BLI_mempool *pool, void BLI_mempool_set_memory_debug(void); #endif -/** iteration stuff. note: this may easy to produce bugs with */ +/** + * Iteration stuff. + * NOTE: this may easy to produce bugs with. + */ /* private structure */ typedef struct BLI_mempool_iter { BLI_mempool *pool; diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh index 6b8e79f376c..f28be9bf59b 100644 --- a/source/blender/blenlib/BLI_mesh_intersect.hh +++ b/source/blender/blenlib/BLI_mesh_intersect.hh @@ -225,6 +225,7 @@ class IMeshArena : NonCopyable, NonMovable { */ const Vert *add_or_find_vert(const mpq3 &co, int orig); const Vert *add_or_find_vert(const double3 &co, int orig); + const Vert *add_or_find_vert(Vert *vert); Face *add_face(Span<const Vert *> verts, int orig, @@ -405,7 +406,7 @@ bool bbs_might_intersect(const BoundingBox &bb_a, const BoundingBox &bb_b); * that the output triangle was a part of (input can have -1 for that field and then * the index in `tri[]` will be used as the original index). * The orig structure of the output #IMesh gives the originals for vertices and edges. - * Note: if the input tm_in has a non-empty orig structure, then it is ignored. + * NOTE: if the input tm_in has a non-empty orig structure, then it is ignored. */ IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena); diff --git a/source/blender/blenlib/BLI_multi_value_map.hh b/source/blender/blenlib/BLI_multi_value_map.hh index fb52ac78243..d3073c98417 100644 --- a/source/blender/blenlib/BLI_multi_value_map.hh +++ b/source/blender/blenlib/BLI_multi_value_map.hh @@ -129,7 +129,7 @@ template<typename Key, typename Value> class MultiValueMap { } /** - * Note: This signature will change when the implementation changes. + * NOTE: This signature will change when the implementation changes. */ typename MapType::ItemIterator items() const { @@ -137,7 +137,7 @@ template<typename Key, typename Value> class MultiValueMap { } /** - * Note: This signature will change when the implementation changes. + * NOTE: This signature will change when the implementation changes. */ typename MapType::KeyIterator keys() const { @@ -145,7 +145,7 @@ template<typename Key, typename Value> class MultiValueMap { } /** - * Note: This signature will change when the implementation changes. + * NOTE: This signature will change when the implementation changes. */ typename MapType::ValueIterator values() const { diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index fa57f0486e5..8f281023177 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -97,15 +97,15 @@ struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v2); enum { - /* note: using BLI_SCANFILL_CALC_REMOVE_DOUBLES + /* NOTE(campbell): using BLI_SCANFILL_CALC_REMOVE_DOUBLES * Assumes ordered edges, otherwise we risk an eternal loop - * removing double verts. - campbell */ + * removing double verts. */ BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1), /* calculate isolated polygons */ BLI_SCANFILL_CALC_POLYS = (1 << 2), - /* note: This flag removes checks for overlapping polygons. + /* NOTE: This flag removes checks for overlapping polygons. * when this flag is set, we'll never get back more faces than (totvert - 2) */ BLI_SCANFILL_CALC_HOLES = (1 << 3), diff --git a/source/blender/blenlib/BLI_set_slots.hh b/source/blender/blenlib/BLI_set_slots.hh index a4d01dfdb68..d50ef95f11e 100644 --- a/source/blender/blenlib/BLI_set_slots.hh +++ b/source/blender/blenlib/BLI_set_slots.hh @@ -249,7 +249,7 @@ template<typename Key> class HashedSetSlot { template<typename ForwardKey, typename IsEqual> bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t hash) const { - /* hash_ might be uninitialized here, but that is ok. */ + /* `hash_` might be uninitialized here, but that is ok. */ if (hash_ == hash) { if (state_ == Occupied) { return is_equal(key, *key_buffer_); diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh index c3876d4eaf8..e04295b0e51 100644 --- a/source/blender/blenlib/BLI_span.hh +++ b/source/blender/blenlib/BLI_span.hh @@ -58,7 +58,7 @@ * its task, without having to worry about memory allocation. Alternatively, a function could * return an Array or Vector. * - * Note: When a function has a MutableSpan<T> output parameter and T is not a trivial type, + * NOTE: When a function has a MutableSpan<T> output parameter and T is not a trivial type, * then the function has to specify whether the referenced array is expected to be initialized or * not. * diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index dbe8ec3dcc0..418db14e2f3 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -129,6 +129,9 @@ typedef struct TaskParallelTLS { typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict tls); + +typedef void (*TaskParallelInitFunc)(const void *__restrict userdata, void *__restrict chunk); + typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata, void *__restrict chunk_join, void *__restrict chunk); @@ -151,6 +154,10 @@ typedef struct TaskParallelSettings { /* Function called from calling thread once whole range have been * processed. */ + /* Function called to initialize user data chunk, + * typically to allocate data, freed by `func_free`. + */ + TaskParallelInitFunc func_init; /* Function called to join user data chunk into another, to reduce * the result to the original userdata_chunk memory. * The reduce functions should have no side effects, so that they diff --git a/source/blender/blenlib/BLI_task.hh b/source/blender/blenlib/BLI_task.hh index 5f5a17f6b58..e2446ad143e 100644 --- a/source/blender/blenlib/BLI_task.hh +++ b/source/blender/blenlib/BLI_task.hh @@ -28,6 +28,7 @@ # define NOMINMAX # define TBB_MIN_MAX_CLEANUP # endif +# include "tbb/parallel_reduce.h" # include <tbb/blocked_range.h> # include <tbb/parallel_for.h> # include <tbb/parallel_for_each.h> @@ -76,6 +77,27 @@ void parallel_for(IndexRange range, int64_t grain_size, const Function &function #endif } +template<typename Value, typename Function, typename Reduction> +Value parallel_reduce(IndexRange range, + int64_t grain_size, + const Value &identity, + const Function &function, + const Reduction &reduction) +{ +#ifdef WITH_TBB + return tbb::parallel_reduce( + tbb::blocked_range<int64_t>(range.first(), range.one_after_last(), grain_size), + identity, + [&](const tbb::blocked_range<int64_t> &subrange, const Value &ident) { + return function(IndexRange(subrange.begin(), subrange.size()), ident); + }, + reduction); +#else + UNUSED_VARS(grain_size, reduction); + return function(range, identity); +#endif +} + /** See #BLI_task_isolate for a description of what isolating a task means. */ template<typename Function> void isolate_task(const Function &function) { diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 677df9db026..ea5572f1c8a 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -188,6 +188,7 @@ set(SRC BLI_dynstr.h BLI_easing.h BLI_edgehash.h + BLI_endian_defines.h BLI_endian_switch.h BLI_endian_switch_inline.h BLI_enumerable_thread_specific.hh diff --git a/source/blender/blenlib/intern/BLI_assert.c b/source/blender/blenlib/intern/BLI_assert.c index 887f583242f..cebc6f8957f 100644 --- a/source/blender/blenlib/intern/BLI_assert.c +++ b/source/blender/blenlib/intern/BLI_assert.c @@ -31,6 +31,11 @@ void _BLI_assert_print_pos(const char *file, const int line, const char *functio fprintf(stderr, "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", file, line, function, id); } +void _BLI_assert_print_extra(const char *str) +{ + fprintf(stderr, " %s\n", str); +} + void _BLI_assert_unreachable_print(const char *file, const int line, const char *function) { fprintf(stderr, "Code marked as unreachable has been executed. Please report this as a bug.\n"); diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index 55fd28667fc..f05dea46dc8 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -432,7 +432,7 @@ void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *s } /** - * Deep-duplicate of an array of direntries, including the array itself. + * Deep-duplicate of a #direntry array including the array itself. */ void BLI_filelist_duplicate(struct direntry **dest_filelist, struct direntry *const src_filelist, @@ -462,7 +462,7 @@ void BLI_filelist_entry_free(struct direntry *entry) } /** - * frees storage for an array of direntries, including the array itself. + * Frees storage for an array of #direntry, including the array itself. */ void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries) { diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 8463c0ec511..46e599b7cf3 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -611,7 +611,7 @@ static Entry *ghash_pop(GHash *gh, GHashIterState *state) return NULL; } - /* Note: using first_bucket_index here allows us to avoid potential + /* NOTE: using first_bucket_index here allows us to avoid potential * huge number of loops over buckets, * in case we are popping from a large ghash with few items in it... */ curr_bucket = ghash_find_next_bucket_index(gh, curr_bucket); @@ -677,7 +677,7 @@ static GHash *ghash_copy(const GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopy * This means entries in buckets in new copy will be in reversed order! * This shall not be an issue though, since order should never be assumed in ghash. */ - /* Note: We can use 'i' here, since we are sure that + /* NOTE: We can use 'i' here, since we are sure that * 'gh' and 'gh_new' have the same number of buckets! */ e_new->next = gh_new->buckets[i]; gh_new->buckets[i] = e_new; diff --git a/source/blender/blenlib/intern/BLI_ghash_utils.c b/source/blender/blenlib/intern/BLI_ghash_utils.c index 83f64043cd0..182c27aed6d 100644 --- a/source/blender/blenlib/intern/BLI_ghash_utils.c +++ b/source/blender/blenlib/intern/BLI_ghash_utils.c @@ -53,7 +53,7 @@ uint BLI_ghashutil_ptrhash(const void *key) /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid * excessive hash collisions for dicts and sets */ - /* Note: Unlike Python 'sizeof(uint)' is used instead of 'sizeof(void *)', + /* NOTE: Unlike Python 'sizeof(uint)' is used instead of 'sizeof(void *)', * Otherwise casting to 'uint' ignores the upper bits on 64bit platforms. */ return (uint)(y >> 4) | ((uint)y << (sizeof(uint[8]) - 4)); } @@ -141,7 +141,7 @@ size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b) * string, is updated: ``hash = hash * 33 + c``. This * function uses the signed value of each byte. * - * note: this is the same hash method that glib 2.34.0 uses. + * NOTE: this is the same hash method that glib 2.34.0 uses. */ uint BLI_ghashutil_strhash_n(const char *key, size_t n) { diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 8f556e0ddb6..25939323b73 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -26,7 +26,7 @@ * * See: http://www.gris.uni-tuebingen.de/people/staff/jmezger/papers/bvh.pdf * - * implements a bvh-tree structure with support for: + * implements a BVH-tree structure with support for: * * - Ray-cast: * #BLI_bvhtree_ray_cast, #BVHRayCastData @@ -98,8 +98,8 @@ struct BVHTree { int totleaf; /* leafs */ int totbranch; axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */ - axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ - char tree_type; /* type of tree (4 => quadtree) */ + axis_t axis; /* KDOP type (6 => OBB, 7 => AABB, ...) */ + char tree_type; /* type of tree (4 => quad-tree). */ }; /* optimization, ensure we stay small */ @@ -726,7 +726,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, /* Save split axis (this can be used on ray-tracing to speedup the query time) */ parent->main_axis = split_axis / 2; - /* Split the children along the split_axis, note: its not needed to sort the whole leafs array + /* Split the children along the split_axis, NOTE: its not needed to sort the whole leafs array * Only to assure that the elements are partitioned on a way that each child takes the elements * it would take in case the whole array was sorted. * Split_leafs takes care of that "sort" problem. */ @@ -881,7 +881,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) /* tree epsilon must be >= FLT_EPSILON * so that tangent rays can still hit a bounding volume.. - * this bug would show up when casting a ray aligned with a kdop-axis + * this bug would show up when casting a ray aligned with a KDOP-axis * and with an edge of 2 faces */ epsilon = max_ff(FLT_EPSILON, epsilon); @@ -1423,7 +1423,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap( static bool tree_intersect_plane_test(const float *bv, const float plane[4]) { - /* TODO(germano): Support other kdop geometries. */ + /* TODO(germano): Support other KDOP geometries. */ const float bb_min[3] = {bv[0], bv[2], bv[4]}; const float bb_max[3] = {bv[1], bv[3], bv[5]}; float bb_near[3], bb_far[3]; @@ -1805,7 +1805,7 @@ static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6]) * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] * - * TODO this doesn't take data->ray.radius into consideration */ + * TODO: this doesn't take data->ray.radius into consideration. */ static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node) { const float *bv = node->bv; diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index fc381c22315..0ab27a5adad 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -45,6 +45,7 @@ # define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) UNUSED_VARS(pool, rzB, is_zeroed) # define VALGRIND_DESTROY_MEMPOOL(pool) UNUSED_VARS(pool) # define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) UNUSED_VARS(pool, addr, size) +# define VALGRIND_MOVE_MEMPOOL(pool_a, pool_b) UNUSED_VARS(pool_a, pool_b) #endif struct MemBuf { @@ -179,6 +180,58 @@ void *BLI_memarena_calloc(MemArena *ma, size_t size) } /** + * Transfer ownership of allocated blocks from `ma_src` into `ma_dst`, + * cleaning the contents of `ma_src`. + * + * \note Useful for multi-threaded tasks that need a thread-local #MemArena + * that is kept after the multi-threaded operation is completed. + * + * \note Avoid accumulating memory pools where possible + * as any unused memory in `ma_src` is wasted every merge. + */ +void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src) +{ + /* Memory arenas must be compatible. */ + BLI_assert(ma_dst != ma_src); + BLI_assert(ma_dst->align == ma_src->align); + BLI_assert(ma_dst->use_calloc == ma_src->use_calloc); + BLI_assert(ma_dst->bufsize == ma_src->bufsize); + + if (ma_src->bufs == NULL) { + return; + } + + if (UNLIKELY(ma_dst->bufs == NULL)) { + BLI_assert(ma_dst->curbuf == NULL); + ma_dst->bufs = ma_src->bufs; + ma_dst->curbuf = ma_src->curbuf; + ma_dst->cursize = ma_src->cursize; + } + else { + /* Keep the 'ma_dst->curbuf' for simplicity. + * Insert buffers after the first. */ + if (ma_dst->bufs->next != NULL) { + /* Loop over `ma_src` instead of `ma_dst` since it's likely the destination is larger + * when used for accumulating from multiple sources. */ + struct MemBuf *mb_src = ma_src->bufs; + mb_src = ma_src->bufs; + while (mb_src && mb_src->next) { + mb_src = mb_src->next; + } + mb_src->next = ma_dst->bufs->next; + } + ma_dst->bufs->next = ma_src->bufs; + } + + ma_src->bufs = NULL; + ma_src->curbuf = NULL; + ma_src->cursize = 0; + + VALGRIND_MOVE_MEMPOOL(ma_src, ma_dst); + VALGRIND_CREATE_MEMPOOL(ma_src, 0, false); +} + +/** * Clear for reuse, avoids re-allocation when an arena may * otherwise be free'd and recreated. */ diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 8196438eb25..5263af2ae56 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -47,7 +47,7 @@ # include "valgrind/memcheck.h" #endif -/* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */ +/* NOTE: copied from BLO_blend_defs.h, don't use here because we're in BLI. */ #ifdef __BIG_ENDIAN__ /* Big Endian */ # define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d)) @@ -387,7 +387,7 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) } } if (!found) { - BLI_assert(!"Attempt to free data which is not in pool.\n"); + BLI_assert_msg(0, "Attempt to free data which is not in pool.\n"); } } diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index 250915383cf..e1a7ee98ce5 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -191,7 +191,7 @@ # define BCHUNK_SIZE_MIN_DIV 8 /* Disallow chunks bigger than the regular chunk size scaled by this value - * note: must be at least 2! + * NOTE: must be at least 2! * however, this code runs won't run in tests unless it's ~1.1 ugh. * so lower only to check splitting works. */ @@ -980,7 +980,7 @@ static const BChunkRef *table_lookup(const BArrayInfo *info, const size_t offset, const hash_key *UNUSED(table_hash_array)) { - const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */ + const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO: cache. */ size_t size_left = data_len - offset; hash_key key = hash_data(&data[offset], MIN2(data_hash_len, size_left)); @@ -1155,7 +1155,7 @@ static BChunkList *bchunk_list_from_data_merge(const BArrayInfo *info, use_aligned = true; } else { - /* TODO, walk over chunks and check if some arbitrary amount align */ + /* TODO: walk over chunks and check if some arbitrary amount align. */ } } #endif /* USE_ALIGN_CHUNKS_TEST */ @@ -1787,7 +1787,7 @@ bool BLI_array_store_is_valid(BArrayStore *bs) } return ok; - /* TODO, dangling pointer checks */ + /* TODO: dangling pointer checks. */ } /** \} */ diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c index 25261e82cc9..9a12a7442b7 100644 --- a/source/blender/blenlib/intern/array_utils.c +++ b/source/blender/blenlib/intern/array_utils.c @@ -40,11 +40,11 @@ * * Access via #BLI_array_reverse */ -void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) +void _bli_array_reverse(void *arr_v, uint arr_len, size_t arr_stride) { - const unsigned int arr_stride_uint = (unsigned int)arr_stride; - const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint; - unsigned int i, i_end; + const uint arr_stride_uint = (uint)arr_stride; + const uint arr_half_stride = (arr_len / 2) * arr_stride_uint; + uint i, i_end; char *arr = arr_v; char *buf = BLI_array_alloca(buf, arr_stride); @@ -62,7 +62,7 @@ void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) * * Access via #BLI_array_wrap */ -void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int dir) +void _bli_array_wrap(void *arr_v, uint arr_len, size_t arr_stride, int dir) { char *arr = arr_v; char *buf = BLI_array_alloca(buf, arr_stride); @@ -88,16 +88,13 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d * * Access via #BLI_array_wrap */ -void _bli_array_permute(void *arr, - const unsigned int arr_len, - const size_t arr_stride, - const unsigned int *order, - void *arr_temp) +void _bli_array_permute( + void *arr, const uint arr_len, const size_t arr_stride, const uint *order, void *arr_temp) { const size_t len = arr_len * arr_stride; - const unsigned int arr_stride_uint = (unsigned int)arr_stride; + const uint arr_stride_uint = (uint)arr_stride; void *arr_orig; - unsigned int i; + uint i; if (arr_temp == NULL) { arr_orig = MEM_mallocN(len, __func__); @@ -121,16 +118,45 @@ void _bli_array_permute(void *arr, } /** + * In-place array de-duplication of an ordered array. + * + * \return The new length of the array. + * + * Access via #BLI_array_deduplicate_ordered + */ +uint _bli_array_deduplicate_ordered(void *arr, uint arr_len, size_t arr_stride) +{ + if (UNLIKELY(arr_len <= 1)) { + return arr_len; + } + + const uint arr_stride_uint = (uint)arr_stride; + uint j = 0; + for (uint i = 0; i < arr_len; i++) { + if ((i == j) || (memcmp(POINTER_OFFSET(arr, arr_stride_uint * i), + POINTER_OFFSET(arr, arr_stride_uint * j), + arr_stride) == 0)) { + continue; + } + j += 1; + memcpy(POINTER_OFFSET(arr, arr_stride_uint * j), + POINTER_OFFSET(arr, arr_stride_uint * i), + arr_stride); + } + return j + 1; +} + +/** * Find the first index of an item in an array. * * Access via #BLI_array_findindex * * \note Not efficient, use for error checks/asserts. */ -int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p) +int _bli_array_findindex(const void *arr, uint arr_len, size_t arr_stride, const void *p) { const char *arr_step = (const char *)arr; - for (unsigned int i = 0; i < arr_len; i++, arr_step += arr_stride) { + for (uint i = 0; i < arr_len; i++, arr_step += arr_stride) { if (memcmp(arr_step, p, arr_stride) == 0) { return (int)i; } @@ -141,10 +167,10 @@ int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_strid /** * A version of #BLI_array_findindex that searches from the end of the list. */ -int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p) +int _bli_array_rfindindex(const void *arr, uint arr_len, size_t arr_stride, const void *p) { const char *arr_step = (const char *)arr + (arr_stride * arr_len); - for (unsigned int i = arr_len; i-- != 0;) { + for (uint i = arr_len; i-- != 0;) { arr_step -= arr_stride; if (memcmp(arr_step, p, arr_stride) == 0) { return (int)i; @@ -154,7 +180,7 @@ int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stri } void _bli_array_binary_and( - void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride) + void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride) { char *dst = arr; const char *src_a = arr_a; @@ -167,7 +193,7 @@ void _bli_array_binary_and( } void _bli_array_binary_or( - void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride) + void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride) { char *dst = arr; const char *src_a = arr_a; @@ -196,14 +222,14 @@ void _bli_array_binary_or( * where calculating the length isn't a simple subtraction. */ bool _bli_array_iter_span(const void *arr, - unsigned int arr_len, + uint arr_len, size_t arr_stride, bool use_wrap, bool use_delimit_bounds, bool (*test_fn)(const void *arr_item, void *user_data), void *user_data, - unsigned int span_step[2], - unsigned int *r_span_len) + uint span_step[2], + uint *r_span_len) { if (arr_len == 0) { return false; @@ -212,11 +238,11 @@ bool _bli_array_iter_span(const void *arr, return false; } - const unsigned int arr_stride_uint = (unsigned int)arr_stride; + const uint arr_stride_uint = (uint)arr_stride; const void *item_prev; bool test_prev; - unsigned int i_curr; + uint i_curr; if ((span_step[0] == arr_len) && (span_step[1] == arr_len)) { if (use_wrap) { @@ -249,11 +275,11 @@ bool _bli_array_iter_span(const void *arr, while (i_curr < arr_len) { bool test_curr = test_fn(item_curr, user_data); if ((test_prev == false) && (test_curr == true)) { - unsigned int span_len; - unsigned int i_step_prev = i_curr; + uint span_len; + uint i_step_prev = i_curr; if (use_wrap) { - unsigned int i_step = i_curr + 1; + uint i_step = i_curr + 1; if (UNLIKELY(i_step == arr_len)) { i_step = 0; } @@ -273,7 +299,7 @@ bool _bli_array_iter_span(const void *arr, } } else { - unsigned int i_step = i_curr + 1; + uint i_step = i_curr + 1; while ((i_step != arr_len) && test_fn(POINTER_OFFSET(arr, i_step * arr_stride_uint), user_data)) { i_step_prev = i_step; @@ -307,7 +333,7 @@ bool _bli_array_iter_span(const void *arr, /** * Simple utility to check memory is zeroed. */ -bool _bli_array_is_zeroed(const void *arr_v, unsigned int arr_len, size_t arr_stride) +bool _bli_array_is_zeroed(const void *arr_v, uint arr_len, size_t arr_stride) { const char *arr_step = (const char *)arr_v; size_t i = arr_stride * arr_len; diff --git a/source/blender/blenlib/intern/bitmap_draw_2d.c b/source/blender/blenlib/intern/bitmap_draw_2d.c index 9d3b66d72d7..b0afe1349ad 100644 --- a/source/blender/blenlib/intern/bitmap_draw_2d.c +++ b/source/blender/blenlib/intern/bitmap_draw_2d.c @@ -496,7 +496,7 @@ void BLI_bitmap_draw_2d_poly_v2i_n(const int xmin, /* Scan for new x-nodes */ while ((span_y_index < span_y_len) && (verts[span_y[span_y_index][0]][1] == pixel_y)) { - /* note, node_x these are just added at the end, + /* NOTE: node_x these are just added at the end, * not ideal but sorting once will resolve. */ /* x is initialized for the next pixel_y */ diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc index eb3e64c49e6..24a58103a10 100644 --- a/source/blender/blenlib/intern/delaunay_2d.cc +++ b/source/blender/blenlib/intern/delaunay_2d.cc @@ -896,7 +896,9 @@ template<typename T> inline bool is_original_vert(const CDTVert<T> *v, CDT_state return (v->index < cdt->input_vert_tot); } -/* Return the Symedge that goes from v1 to v2, if it exists, else return nullptr. */ +/** + * Return the #SymEdge that goes from v1 to v2, if it exists, else return nullptr. + */ template<typename T> SymEdge<T> *find_symedge_between_verts(const CDTVert<T> *v1, const CDTVert<T> *v2) { @@ -2106,7 +2108,7 @@ template<typename T> void add_edge_constraints(CDT_state<T> *cdt_state, const CD * for the boundary of the input face. * fedge_start..fedge_end is the inclusive range of edge input ids that are for the given face. * - * Note: if the input face is not CCW oriented, we'll be labeling the outside, not the inside. + * NOTE: if the input face is not CCW oriented, we'll be labeling the outside, not the inside. * Note 2: if the boundary has self-crossings, this method will arbitrarily pick one of the * contiguous set of faces enclosed by parts of the boundary, leaving the other such un-tagged. * This may be a feature instead of a bug if the first contiguous section is most of the face and diff --git a/source/blender/blenlib/intern/expr_pylike_eval.c b/source/blender/blenlib/intern/expr_pylike_eval.c index a5d4130cb20..4d1ba190c14 100644 --- a/source/blender/blenlib/intern/expr_pylike_eval.c +++ b/source/blender/blenlib/intern/expr_pylike_eval.c @@ -569,7 +569,7 @@ static int opcode_arg_count(eOpCode code) case OPCODE_FUNC3: return 3; default: - BLI_assert(!"unexpected opcode"); + BLI_assert_msg(0, "unexpected opcode"); return -1; } } diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 107c27da6a2..1a00142ddb1 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -64,7 +64,7 @@ #if 0 /* UNUSED */ /* gzip the file in from and write it to "to". * return -1 if zlib fails, -2 if the originating file does not exist - * note: will remove the "from" file + * NOTE: will remove the "from" file */ int BLI_file_gzip(const char *from, const char *to) { @@ -355,7 +355,7 @@ void *BLI_gzopen(const char *filename, const char *mode) BLI_assert(!BLI_path_is_rel(filename)); - /* xxx Creates file before transcribing the path */ + /* XXX: Creates file before transcribing the path. */ if (mode[0] == 'w') { FILE *file = ufopen(filename, "a"); if (file == NULL) { diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h index 2aec3ce082a..0c9de0aa128 100644 --- a/source/blender/blenlib/intern/kdtree_impl.h +++ b/source/blender/blenlib/intern/kdtree_impl.h @@ -132,7 +132,7 @@ void BLI_kdtree_nd_(insert)(KDTree *tree, int index, const float co[KD_DIMS]) BLI_assert(tree->nodes_len <= tree->nodes_len_capacity); #endif - /* note, array isn't calloc'd, + /* NOTE: array isn't calloc'd, * need to initialize all struct members */ node->left = node->right = KD_NODE_UNSET; diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 263c508c07c..da97e697f2f 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -153,7 +153,7 @@ void rgb_to_ycc(float r, float g, float b, float *r_y, float *r_cb, float *r_cr, cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f; break; default: - BLI_assert(!"invalid colorspace"); + BLI_assert_msg(0, "invalid colorspace"); break; } diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 3175bf116a0..80f0008c7eb 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1756,8 +1756,8 @@ bool isect_ray_tri_v3(const float ray_origin[3], float *r_lambda, float r_uv[2]) { - /* note: these values were 0.000001 in 2.4x but for projection snapping on - * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */ + /* NOTE(campbell): these values were 0.000001 in 2.4x but for projection snapping on + * a human head (1BU == 1m), subsurf level 2, this gave many errors. */ const float epsilon = 0.00000001f; float p[3], s[3], e1[3], e2[3], q[3]; float a, f, u, v; @@ -3287,8 +3287,8 @@ bool isect_ray_aabb_v3(const struct IsectRayAABB_Precalc *data, tmin = tzmin; } - /* Note: tmax does not need to be updated since we don't use it - * keeping this here for future reference - jwilkins */ + /* NOTE(jwilkins): tmax does not need to be updated since we don't use it + * keeping this here for future reference. */ // if (tzmax < tmax) tmax = tzmax; if (tmin_out) { @@ -3559,7 +3559,7 @@ static bool point_in_slice(const float p[3], sub_v3_v3v3(rp, p, v1); h = dot_v3v3(q, rp) / dot_v3v3(q, q); - /* note: when 'h' is nan/-nan, this check returns false + /* NOTE: when 'h' is nan/-nan, this check returns false * without explicit check - covering the degenerate case */ return (h >= 0.0f && h <= 1.0f); } @@ -4020,7 +4020,7 @@ void barycentric_weights_v2_persp( /** * same as #barycentric_weights_v2 but works with a quad, - * note: untested for values outside the quad's bounds + * NOTE: untested for values outside the quad's bounds * this is #interp_weights_poly_v2 expanded for quads only */ void barycentric_weights_v2_quad(const float v1[2], @@ -4030,10 +4030,11 @@ void barycentric_weights_v2_quad(const float v1[2], const float co[2], float w[4]) { - /* note: fabsf() here is not needed for convex quads (and not used in interp_weights_poly_v2). - * but in the case of concave/bow-tie quads for the mask rasterizer it gives unreliable results - * without adding absf(). If this becomes an issue for more general usage we could have - * this optional or use a different function - Campbell */ + /* NOTE(campbell): fabsf() here is not needed for convex quads + * (and not used in #interp_weights_poly_v2). + * But in the case of concave/bow-tie quads for the mask rasterizer it + * gives unreliable results without adding absf(). If this becomes an issue for more general + * usage we could have this optional or use a different function. */ #define MEAN_VALUE_HALF_TAN_V2(_area, i1, i2) \ ((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \ fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : \ @@ -4820,7 +4821,7 @@ void orthographic_m4(float matrix[4][4], matrix[3][0] = -(right + left) / Xdelta; matrix[1][1] = 2.0f / Ydelta; matrix[3][1] = -(top + bottom) / Ydelta; - matrix[2][2] = -2.0f / Zdelta; /* note: negate Z */ + matrix[2][2] = -2.0f / Zdelta; /* NOTE: negate Z. */ matrix[3][2] = -(farClip + nearClip) / Zdelta; } @@ -4844,7 +4845,7 @@ void perspective_m4(float mat[4][4], } mat[0][0] = nearClip * 2.0f / Xdelta; mat[1][1] = nearClip * 2.0f / Ydelta; - mat[2][0] = (right + left) / Xdelta; /* note: negate Z */ + mat[2][0] = (right + left) / Xdelta; /* NOTE: negate Z. */ mat[2][1] = (top + bottom) / Ydelta; mat[2][2] = -(farClip + nearClip) / Zdelta; mat[2][3] = -1.0f; diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c index 163a3ab5fe3..04fae6a0e68 100644 --- a/source/blender/blenlib/intern/math_interp.c +++ b/source/blender/blenlib/intern/math_interp.c @@ -655,7 +655,7 @@ void BLI_ewa_filter(const int width, v2 = (int)(ceilf(V0 + ve)); /* sane clamping to avoid unnecessarily huge loops */ - /* note: if eccentricity gets clamped (see above), + /* NOTE: if eccentricity gets clamped (see above), * the ue/ve limits can also be lowered accordingly */ if (U0 - (float)u1 > EWA_MAXIDX) { diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 5eb0125062d..5920788821c 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1290,6 +1290,9 @@ bool invert_m4_m4(float inverse[4][4], const float mat[4][4]) * Combines transformations, handling scale separately in a manner equivalent * to the Aligned Inherit Scale mode, in order to avoid creating shear. * If A scale is uniform, the result is equivalent to ordinary multiplication. + * + * NOTE: this effectively takes output location from simple multiplication, + * and uses mul_m4_m4m4_split_channels for rotation and scale. */ void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4]) { @@ -1307,6 +1310,25 @@ void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B loc_rot_size_to_mat4(R, loc_r, rot_r, size_r); } +/** + * Separately combines location, rotation and scale of the input matrices. + */ +void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4]) +{ + float loc_a[3], rot_a[3][3], size_a[3]; + float loc_b[3], rot_b[3][3], size_b[3]; + float loc_r[3], rot_r[3][3], size_r[3]; + + mat4_to_loc_rot_size(loc_a, rot_a, size_a, A); + mat4_to_loc_rot_size(loc_b, rot_b, size_b, B); + + add_v3_v3v3(loc_r, loc_a, loc_b); + mul_m3_m3m3_uniq(rot_r, rot_a, rot_b); + mul_v3_v3v3(size_r, size_a, size_b); + + loc_rot_size_to_mat4(R, loc_r, rot_r, size_r); +} + /****************************** Linear Algebra *******************************/ void transpose_m3(float R[3][3]) @@ -2252,8 +2274,8 @@ void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]) copy_m3_m4(mat3, wmat); normalize_m3_m3(mat3_n, mat3); - /* so scale doesn't interfere with rotation T24291. */ - /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ + /* So scale doesn't interfere with rotation T24291. */ + /* FIXME: this is a workaround for negative matrix not working for rotation conversion. */ if (is_negative_m3(mat3)) { negate_m3(mat3_n); } diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 52737de227b..34baac6f2a4 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -167,7 +167,7 @@ void invert_qt_qt_normalized(float q1[4], const float q2[4]) invert_qt_normalized(q1); } -/* simple mult */ +/* Simple multiply. */ void mul_qt_fl(float q[4], const float f) { q[0] *= f; @@ -373,7 +373,7 @@ void mat3_normalized_to_quat(float q[4], const float mat[3][3]) q[2] = (mat[2][1] + mat[1][2]) * s; } - /* Make sure w is nonnegative for a canonical result. */ + /* Make sure W is non-negative for a canonical result. */ if (q[0] < 0) { negate_v4(q); } @@ -511,7 +511,7 @@ void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float } } -/* note: expects vectors to be normalized */ +/* NOTE: expects vectors to be normalized. */ void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]) { float axis[3]; diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 9f7824a0029..8b8850c7cdb 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -21,6 +21,7 @@ #ifdef WITH_GMP # include <algorithm> +# include <atomic> # include <fstream> # include <iostream> @@ -50,6 +51,7 @@ # include "BLI_mesh_boolean.hh" # ifdef WITH_TBB +# include "tbb/parallel_reduce.h" # include "tbb/spin_mutex.h" # endif @@ -201,9 +203,14 @@ TriMeshTopology::TriMeshTopology(const IMesh &tm) BLI_assert(edges != nullptr); } edges->append_non_duplicates(e); - auto createf = [t](Vector<int> **pvec) { *pvec = new Vector<int>{t}; }; - auto modifyf = [t](Vector<int> **pvec) { (*pvec)->append_non_duplicates(t); }; - this->edge_tri_.add_or_modify(Edge(v, vnext), createf, modifyf); + + auto p = edge_tri_.lookup_ptr(Edge(v, vnext)); + if (p == nullptr) { + edge_tri_.add_new(e, new Vector<int>{t}); + } + else { + (*p)->append_non_duplicates(t); + } } } /* Debugging. */ @@ -228,9 +235,18 @@ TriMeshTopology::TriMeshTopology(const IMesh &tm) TriMeshTopology::~TriMeshTopology() { - for (const Vector<int> *vec : edge_tri_.values()) { - delete vec; + Vector<Vector<int> *> values; + + /* Deconstructing is faster in parallel, so it is worth building an array of things to delete. */ + for (auto item : edge_tri_.values()) { + values.append(item); } + + threading::parallel_for(values.index_range(), 256, [&](IndexRange range) { + for (int i : range) { + delete values[i]; + } + }); } /** A Patch is a maximal set of triangles that share manifold edges only. */ @@ -719,6 +735,18 @@ static PatchesInfo find_patches(const IMesh &tm, const TriMeshTopology &tmtopo) PatchesInfo pinfo(ntri); /* Algorithm: Grow patches across manifold edges as long as there are unassigned triangles. */ Stack<int> cur_patch_grow; + + /* Create an Array containing indices of adjacent faces. */ + Array<std::array<int, 3>> t_others(tm.face_size()); + threading::parallel_for(tm.face_index_range(), 2048, [&](IndexRange range) { + for (int t : range) { + const Face &tri = *tm.face(t); + for (int i = 0; i < 3; ++i) { + Edge e(tri[i], tri[(i + 1) % 3]); + t_others[t][i] = tmtopo.other_tri_if_manifold(e, t); + } + } + }); for (int t : tm.face_index_range()) { if (pinfo.tri_patch(t) == -1) { cur_patch_grow.push(t); @@ -739,7 +767,7 @@ static PatchesInfo find_patches(const IMesh &tm, const TriMeshTopology &tmtopo) const Face &tri = *tm.face(tcand); for (int i = 0; i < 3; ++i) { Edge e(tri[i], tri[(i + 1) % 3]); - int t_other = tmtopo.other_tri_if_manifold(e, tcand); + int t_other = t_others[tcand][i]; if (dbg_level > 1) { std::cout << " edge " << e << " generates t_other=" << t_other << "\n"; } @@ -953,12 +981,8 @@ static void sort_by_signed_triangle_index(Vector<int> &g, * To accommodate this: * If extra_tri is non-null, then an index of EXTRA_TRI_INDEX should use it for the triangle. */ -static Array<int> sort_tris_around_edge(const IMesh &tm, - const TriMeshTopology &tmtopo, - const Edge e, - const Span<int> tris, - const int t0, - const Face *extra_tri) +static Array<int> sort_tris_around_edge( + const IMesh &tm, const Edge e, const Span<int> tris, const int t0, const Face *extra_tri) { /* Divide and conquer, quick-sort-like sort. * Pick a triangle t0, then partition into groups: @@ -1023,14 +1047,14 @@ static Array<int> sort_tris_around_edge(const IMesh &tm, } } if (g3.size() > 1) { - Array<int> g3sorted = sort_tris_around_edge(tm, tmtopo, e, g3, t0, extra_tri); + Array<int> g3sorted = sort_tris_around_edge(tm, e, g3, t0, extra_tri); std::copy(g3sorted.begin(), g3sorted.end(), g3.begin()); if (dbg_level > 1) { std::cout << "g3 sorted: " << g3 << "\n"; } } if (g4.size() > 1) { - Array<int> g4sorted = sort_tris_around_edge(tm, tmtopo, e, g4, t0, extra_tri); + Array<int> g4sorted = sort_tris_around_edge(tm, e, g4, t0, extra_tri); std::copy(g4sorted.begin(), g4sorted.end(), g4.begin()); if (dbg_level > 1) { std::cout << "g4 sorted: " << g4 << "\n"; @@ -1076,7 +1100,7 @@ static void find_cells_from_edge(const IMesh &tm, const Vector<int> *edge_tris = tmtopo.edge_tris(e); BLI_assert(edge_tris != nullptr); Array<int> sorted_tris = sort_tris_around_edge( - tm, tmtopo, e, Span<int>(*edge_tris), (*edge_tris)[0], nullptr); + tm, e, Span<int>(*edge_tris), (*edge_tris)[0], nullptr); int n_edge_tris = edge_tris->size(); Array<int> edge_patches(n_edge_tris); @@ -1338,34 +1362,46 @@ static bool patch_cell_graph_ok(const CellsInfo &cinfo, const PatchesInfo &pinfo static bool is_pwn(const IMesh &tm, const TriMeshTopology &tmtopo) { constexpr int dbg_level = 0; + std::atomic<bool> is_pwn = true; + Vector<std::pair<Edge, Vector<int> *>> tris; + for (auto item : tmtopo.edge_tri_map_items()) { - const Edge &edge = item.key; - int tot_orient = 0; - /* For each face t attached to edge, add +1 if the edge - * is positively in t, and -1 if negatively in t. */ - for (int t : *item.value) { - const Face &face = *tm.face(t); - BLI_assert(face.size() == 3); - for (int i : face.index_range()) { - if (face[i] == edge.v0()) { - if (face[(i + 1) % 3] == edge.v1()) { - ++tot_orient; - } - else { - BLI_assert(face[(i + 3 - 1) % 3] == edge.v1()); - --tot_orient; + tris.append(std::pair<Edge, Vector<int> *>(item.key, item.value)); + } + + threading::parallel_for(tris.index_range(), 2048, [&](IndexRange range) { + for (int j : range) { + const Edge &edge = tris[j].first; + int tot_orient = 0; + /* For each face t attached to edge, add +1 if the edge + * is positively in t, and -1 if negatively in t. */ + for (int t : *tris[j].second) { + const Face &face = *tm.face(t); + BLI_assert(face.size() == 3); + for (int i : face.index_range()) { + if (face[i] == edge.v0()) { + if (face[(i + 1) % 3] == edge.v1()) { + ++tot_orient; + } + else { + BLI_assert(face[(i + 3 - 1) % 3] == edge.v1()); + --tot_orient; + } } } } - } - if (tot_orient != 0) { - if (dbg_level > 0) { - std::cout << "edge causing non-pwn: " << edge << "\n"; + if (tot_orient != 0) { + if (dbg_level > 0) { + std::cout << "edge causing non-pwn: " << edge << "\n"; + } + is_pwn = false; +# ifdef WITH_TBB + tbb::task::self().cancel_group_execution(); +# endif } - return false; } - } - return true; + }); + return is_pwn.load(); } /** @@ -1396,8 +1432,7 @@ static int find_cell_for_point_near_edge(mpq3 p, Array<int> edge_tris(etris->size() + 1); std::copy(etris->begin(), etris->end(), edge_tris.begin()); edge_tris[edge_tris.size() - 1] = EXTRA_TRI_INDEX; - Array<int> sorted_tris = sort_tris_around_edge( - tm, tmtopo, e, edge_tris, edge_tris[0], dummy_tri); + Array<int> sorted_tris = sort_tris_around_edge(tm, e, edge_tris, edge_tris[0], dummy_tri); if (dbg_level > 0) { std::cout << "sorted tris = " << sorted_tris << "\n"; } @@ -1452,39 +1487,66 @@ static int find_ambient_cell(const IMesh &tm, /* First find a vertex with the maximum x value. */ /* Prefer not to populate the verts in the #IMesh just for this. */ const Vert *v_extreme; - mpq_class extreme_x; + auto max_x_vert = [](const Vert *a, const Vert *b) { + return (a->co_exact.x > b->co_exact.x) ? a : b; + }; if (component_patches == nullptr) { - v_extreme = (*tm.face(0))[0]; - extreme_x = v_extreme->co_exact.x; - for (const Face *f : tm.faces()) { - for (const Vert *v : *f) { - const mpq_class &x = v->co_exact.x; - if (x > extreme_x) { - v_extreme = v; - extreme_x = x; - } - } - } + v_extreme = threading::parallel_reduce( + tm.face_index_range(), + 2048, + (*tm.face(0))[0], + [&](IndexRange range, const Vert *init) { + const Vert *ans = init; + for (int i : range) { + const Face *f = tm.face(i); + for (const Vert *v : *f) { + if (v->co_exact.x > ans->co_exact.x) { + ans = v; + } + } + } + return ans; + }, + max_x_vert); } else { if (dbg_level > 0) { std::cout << "restrict to patches " << *component_patches << "\n"; } int p0 = (*component_patches)[0]; - v_extreme = (*tm.face(pinfo.patch(p0).tri(0)))[0]; - extreme_x = v_extreme->co_exact.x; - for (int p : *component_patches) { - for (int t : pinfo.patch(p).tris()) { - const Face *f = tm.face(t); - for (const Vert *v : *f) { - const mpq_class &x = v->co_exact.x; - if (x > extreme_x) { - v_extreme = v; - extreme_x = x; + v_extreme = threading::parallel_reduce( + component_patches->index_range(), + 2048, + (*tm.face(pinfo.patch(p0).tri(0)))[0], + [&](IndexRange range, const Vert *init) { + const Vert *ans = init; + for (int pi : range) { + int p = (*component_patches)[pi]; + const Vert *tris_ans = threading::parallel_reduce( + IndexRange(pinfo.patch(p).tot_tri()), + 2048, + init, + [&](IndexRange tris_range, const Vert *t_init) { + const Vert *v_ans = t_init; + for (int i : tris_range) { + int t = pinfo.patch(p).tri(i); + const Face *f = tm.face(t); + for (const Vert *v : *f) { + if (v->co_exact.x > v_ans->co_exact.x) { + v_ans = v; + } + } + } + return v_ans; + }, + max_x_vert); + if (tris_ans->co_exact.x > ans->co_exact.x) { + ans = tris_ans; + } } - } - } - } + return ans; + }, + max_x_vert); } if (dbg_level > 0) { std::cout << "v_extreme = " << v_extreme << "\n"; @@ -1493,7 +1555,8 @@ static int find_ambient_cell(const IMesh &tm, * when projected onto the XY plane. That edge is guaranteed to * be on the convex hull of the mesh. */ const Vector<Edge> &edges = tmtopo.vert_edges(v_extreme); - const mpq_class extreme_y = v_extreme->co_exact.y; + const mpq_class &extreme_x = v_extreme->co_exact.x; + const mpq_class &extreme_y = v_extreme->co_exact.y; Edge ehull; mpq_class max_abs_slope = -1; for (Edge e : edges) { @@ -1514,8 +1577,8 @@ static int find_ambient_cell(const IMesh &tm, if (dbg_level > 0) { std::cout << "ehull = " << ehull << " slope = " << max_abs_slope << "\n"; } - /* Sort triangles around ehull, including a dummy triangle that include a known point in ambient - * cell. */ + /* Sort triangles around ehull, including a dummy triangle that include a known point in + * ambient cell. */ mpq3 p_in_ambient = v_extreme->co_exact; p_in_ambient.x += 1; int c_ambient = find_cell_for_point_near_edge(p_in_ambient, ehull, tm, tmtopo, pinfo, arena); @@ -2816,7 +2879,8 @@ static IMesh raycast_patches_boolean(const IMesh &tm, } /** * If \a tri1 and \a tri2 have a common edge (in opposite orientation), - * return the indices into \a tri1 and \a tri2 where that common edge starts. Else return (-1,-1). + * return the indices into \a tri1 and \a tri2 where that common edge starts. Else return + * (-1,-1). */ static std::pair<int, int> find_tris_common_edge(const Face &tri1, const Face &tri2) { @@ -3378,8 +3442,8 @@ static void dissolve_verts(IMesh *imesh, const Array<bool> dissolve, IMeshArena * will have an original edge that is NO_INDEX. * Not all triangulation edges can be removed: if they ended up non-trivially overlapping a real * input edge, then we need to keep it. Also, some are necessary to make the output satisfy - * the "valid #BMesh" property: we can't produce output faces that have repeated vertices in them, - * or have several disconnected boundaries (e.g., faces with holes). + * the "valid #BMesh" property: we can't produce output faces that have repeated vertices in + * them, or have several disconnected boundaries (e.g., faces with holes). */ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out, const IMesh &imesh_in, diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc index 988988179fd..f91dd762e70 100644 --- a/source/blender/blenlib/intern/mesh_intersect.cc +++ b/source/blender/blenlib/intern/mesh_intersect.cc @@ -43,6 +43,7 @@ # include "BLI_set.hh" # include "BLI_span.hh" # include "BLI_task.h" +# include "BLI_task.hh" # include "BLI_threads.h" # include "BLI_vector.hh" # include "BLI_vector_set.hh" @@ -51,6 +52,10 @@ # include "BLI_mesh_intersect.hh" +# ifdef WITH_TBB +# include "tbb/parallel_sort.h" +# endif + // # define PERFDEBUG namespace blender::meshintersect { @@ -406,6 +411,11 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable { return add_or_find_vert(mco, co, orig); } + const Vert *add_or_find_vert(Vert *vert) + { + return add_or_find_vert_(vert); + } + Face *add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs, Span<bool> is_intersect) { Face *f = new Face(verts, next_face_id_++, orig, edge_origs, is_intersect); @@ -486,10 +496,9 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable { private: const Vert *add_or_find_vert(const mpq3 &mco, const double3 &dco, int orig) { - /* Don't allocate Vert yet, in case it is already there. */ - Vert vtry(mco, dco, NO_INDEX, NO_INDEX); + Vert *vtry = new Vert(mco, dco, NO_INDEX, NO_INDEX); const Vert *ans; - VSetKey vskey(&vtry); + VSetKey vskey(vtry); if (intersect_use_threading) { # ifdef USE_SPINLOCK BLI_spin_lock(&lock_); @@ -499,7 +508,9 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable { } const VSetKey *lookup = vset_.lookup_key_ptr(vskey); if (!lookup) { - vskey.vert = new Vert(mco, dco, next_vert_id_++, orig); + vtry->id = next_vert_id_++; + vtry->orig = orig; + vskey.vert = vtry; // new Vert(mco, dco, next_vert_id_++, orig); vset_.add_new(vskey); allocated_verts_.append(std::unique_ptr<Vert>(vskey.vert)); ans = vskey.vert; @@ -510,6 +521,45 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable { * This is the intended semantics: if the Vert already * exists then we are merging verts and using the first-seen * one as the canonical one. */ + delete vtry; + ans = lookup->vert; + } + if (intersect_use_threading) { +# ifdef USE_SPINLOCK + BLI_spin_unlock(&lock_); +# else + BLI_mutex_unlock(mutex_); +# endif + } + return ans; + }; + + const Vert *add_or_find_vert_(Vert *vtry) + { + const Vert *ans; + VSetKey vskey(vtry); + if (intersect_use_threading) { +# ifdef USE_SPINLOCK + BLI_spin_lock(&lock_); +# else + BLI_mutex_lock(mutex_); +# endif + } + const VSetKey *lookup = vset_.lookup_key_ptr(vskey); + if (!lookup) { + vtry->id = next_vert_id_++; + vskey.vert = vtry; // new Vert(mco, dco, next_vert_id_++, orig); + vset_.add_new(vskey); + allocated_verts_.append(std::unique_ptr<Vert>(vskey.vert)); + ans = vskey.vert; + } + else { + /* It was a duplicate, so return the existing one. + * Note that the returned Vert may have a different orig. + * This is the intended semantics: if the Vert already + * exists then we are merging verts and using the first-seen + * one as the canonical one. */ + delete vtry; ans = lookup->vert; } if (intersect_use_threading) { @@ -550,6 +600,11 @@ const Vert *IMeshArena::add_or_find_vert(const mpq3 &co, int orig) return pimpl_->add_or_find_vert(co, orig); } +const Vert *IMeshArena::add_or_find_vert(Vert *vert) +{ + return pimpl_->add_or_find_vert(vert); +} + Face *IMeshArena::add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs, @@ -633,7 +688,11 @@ void IMesh::populate_vert(int max_verts) * TODO: when all debugged, set fix_order = false. */ const bool fix_order = true; if (fix_order) { +# ifdef WITH_TBB + tbb::parallel_sort(vert_.begin(), vert_.end(), [](const Vert *a, const Vert *b) { +# else std::sort(vert_.begin(), vert_.end(), [](const Vert *a, const Vert *b) { +# endif if (a->orig != NO_INDEX && b->orig != NO_INDEX) { return a->orig < b->orig; } @@ -1037,7 +1096,7 @@ static mpq2 project_3d_to_2d(const mpq3 &p3d, int proj_axis) * So the sign of E is the same as the sign of E_exact if * |E| > supremum(E) * index(E) * DBL_EPSILON * - * Note: a possible speedup would be to have a simple function + * NOTE: a possible speedup would be to have a simple function * that calculates the error bound if one knows that all values * are less than some global maximum - most of the function would * be calculated ahead of time. The global max could be passed @@ -1918,9 +1977,22 @@ static Face *cdt_tri_as_imesh_face( return facep; } +/* Like BLI_math's is_quad_flip_v3_first_third_fast_with_normal, with const double3's. */ +static bool is_quad_flip_first_third(const double3 &v1, + const double3 &v2, + const double3 &v3, + const double3 &v4, + const double3 &normal) +{ + double3 dir_v3v1 = v3 - v1; + double3 tangent = double3::cross_high_precision(dir_v3v1, normal); + double dot = double3::dot(v1, tangent); + return (double3::dot(v4, tangent) >= dot) || (double3::dot(v2, tangent) <= dot); +} + /** * Tessellate face f into triangles and return an array of `const Face *` - * giving that triangulation. Intended to be used when f has > 4 vertices. + * giving that triangulation. Intended to be used when f has => 4 vertices. * Care is taken so that the original edge index associated with * each edge in the output triangles either matches the original edge * for the (identical) edge of f, or else is -1. So diagonals added @@ -1932,21 +2004,40 @@ static Face *cdt_tri_as_imesh_face( */ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena) { - /* Similar to loop body in BM_mesh_calc_tesselation. */ + /* Similar to loop body in #BM_mesh_calc_tessellation. */ int flen = f->size(); - BLI_assert(flen > 4); + BLI_assert(flen >= 4); if (!f->plane_populated()) { f->populate_plane(false); } - /* Project along negative face normal so (x,y) can be used in 2d. */ const double3 &poly_normal = f->plane->norm; float no[3] = {float(poly_normal[0]), float(poly_normal[1]), float(poly_normal[2])}; normalize_v3(no); - float axis_mat[3][3]; + if (flen == 4) { + const Vert *v0 = (*f)[0]; + const Vert *v1 = (*f)[1]; + const Vert *v2 = (*f)[2]; + const Vert *v3 = (*f)[3]; + int eo_01 = f->edge_orig[0]; + int eo_12 = f->edge_orig[1]; + int eo_23 = f->edge_orig[2]; + int eo_30 = f->edge_orig[3]; + Face *f0, *f1; + if (UNLIKELY(is_quad_flip_first_third(v0->co, v1->co, v2->co, v3->co, f->plane->norm))) { + f0 = arena->add_face({v0, v1, v3}, f->orig, {eo_01, -1, eo_30}, {false, false, false}); + f1 = arena->add_face({v1, v2, v3}, f->orig, {eo_12, eo_23, -1}, {false, false, false}); + } + else { + f0 = arena->add_face({v0, v1, v2}, f->orig, {eo_01, eo_12, -1}, {false, false, false}); + f1 = arena->add_face({v0, v2, v3}, f->orig, {-1, eo_23, eo_30}, {false, false, false}); + } + return Array<Face *>{f0, f1}; + } + /* Project along negative face normal so (x,y) can be used in 2d. */ float axis_mat[3][3]; float(*projverts)[2]; unsigned int(*tris)[3]; const int totfilltri = flen - 2; - /* Prepare projected vertices and array to receive triangles in tesselation. */ + /* Prepare projected vertices and array to receive triangles in tessellation. */ tris = static_cast<unsigned int(*)[3]>(MEM_malloc_arrayN(totfilltri, sizeof(*tris), __func__)); projverts = static_cast<float(*)[2]>(MEM_malloc_arrayN(flen, sizeof(*projverts), __func__)); axis_dominant_v3_to_m3_negate(axis_mat, no); @@ -1956,7 +2047,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena) mul_v2_m3v3(projverts[j], axis_mat, co); } BLI_polyfill_calc(projverts, flen, 1, tris); - /* Put tesselation triangles into Face form. Record original edges where they exist. */ + /* Put tessellation triangles into Face form. Record original edges where they exist. */ Array<Face *> ans(totfilltri); for (int t = 0; t < totfilltri; ++t) { unsigned int *tri = tris[t]; @@ -1986,11 +2077,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena) /** * Tessellate face f into triangles and return an array of `const Face *` - * giving that triangulation. - * Care is taken so that the original edge index associated with - * each edge in the output triangles either matches the original edge - * for the (identical) edge of f, or else is -1. So diagonals added - * for triangulation can later be identified by having #NO_INDEX for original. + * giving that triangulation, using an exact triangulation method. * * The method used is to use the CDT triangulation. Usually that triangulation * will only use the existing vertices. However, if the face self-intersects @@ -2003,7 +2090,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena) * is by far the usual case, we need to know if the quad is convex when * projected before doing so, and that takes a fair amount of computation by itself. */ -static Array<Face *> triangulate_poly(Face *f, IMeshArena *arena) +static Array<Face *> exact_triangulate_poly(Face *f, IMeshArena *arena) { int flen = f->size(); CDT_input<mpq_class> cdt_in; @@ -2086,6 +2173,68 @@ static Array<Face *> triangulate_poly(Face *f, IMeshArena *arena) return ans; } +static bool face_is_degenerate(const Face *f) +{ + const Face &face = *f; + const Vert *v0 = face[0]; + const Vert *v1 = face[1]; + const Vert *v2 = face[2]; + if (v0 == v1 || v0 == v2 || v1 == v2) { + return true; + } + double3 da = v2->co - v0->co; + double3 db = v2->co - v1->co; + double3 dab = double3::cross_high_precision(da, db); + double dab_length_squared = dab.length_squared(); + double err_bound = supremum_dot_cross(dab, dab) * index_dot_cross * DBL_EPSILON; + if (dab_length_squared > err_bound) { + return false; + } + mpq3 a = v2->co_exact - v0->co_exact; + mpq3 b = v2->co_exact - v1->co_exact; + mpq3 ab = mpq3::cross(a, b); + if (ab.x == 0 && ab.y == 0 && ab.z == 0) { + return true; + } + + return false; +} + +/** Fast check for degenerate tris. Only tests for when verts are identical, + * not cases where there are zero-length edges. */ +static bool any_degenerate_tris_fast(const Array<Face *> triangulation) +{ + for (const Face *f : triangulation) { + const Vert *v0 = (*f)[0]; + const Vert *v1 = (*f)[1]; + const Vert *v2 = (*f)[2]; + if (v0 == v1 || v0 == v2 || v1 == v2) { + return true; + } + } + return false; +} + +/** + * Tessellate face f into triangles and return an array of `const Face *` + * giving that triangulation. + * Care is taken so that the original edge index associated with + * each edge in the output triangles either matches the original edge + * for the (identical) edge of f, or else is -1. So diagonals added + * for triangulation can later be identified by having #NO_INDEX for original. + */ +static Array<Face *> triangulate_poly(Face *f, IMeshArena *arena) +{ + /* Try the much faster method using Blender's BLI_polyfill_calc. */ + Array<Face *> ans = polyfill_triangulate_poly(f, arena); + + /* This may create degenerate triangles. If so, try the exact CDT-based triangulator. */ + if (any_degenerate_tris_fast(ans)) { + return exact_triangulate_poly(f, arena); + } + return ans; +} + /** * Return an #IMesh that is a triangulation of a mesh with general * polygonal faces, #IMesh. @@ -2097,8 +2246,16 @@ IMesh triangulate_polymesh(IMesh &imesh, IMeshArena *arena) Vector<Face *> face_tris; constexpr int estimated_tris_per_face = 3; face_tris.reserve(estimated_tris_per_face * imesh.face_size()); + threading::parallel_for(imesh.face_index_range(), 2048, [&](IndexRange range) { + for (int i : range) { + Face *f = imesh.face(i); + if (!f->plane_populated() && f->size() >= 4) { + f->populate_plane(false); + } + } + }); for (Face *f : imesh.faces()) { - /* Tessellate face f, following plan similar to #BM_face_calc_tesselation. */ + /* Tessellate face f, following plan similar to #BM_face_calc_tessellation. */ int flen = f->size(); if (flen == 3) { face_tris.append(f); @@ -2188,12 +2345,22 @@ class TriOverlaps { if (two_trees_no_self) { tree_b_ = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 6); } + + /* Create a Vector containing face shape. */ + Vector<int> shapes; + shapes.resize(tm.face_size()); + threading::parallel_for(tm.face_index_range(), 2048, [&](IndexRange range) { + for (int t : range) { + shapes[t] = shape_fn(tm.face(t)->orig); + } + }); + float bbpts[6]; for (int t : tm.face_index_range()) { const BoundingBox &bb = tri_bb[t]; copy_v3_v3(bbpts, bb.min); copy_v3_v3(bbpts + 3, bb.max); - int shape = shape_fn(tm.face(t)->orig); + int shape = shapes[t]; if (two_trees_no_self) { if (shape == 0) { BLI_bvhtree_insert(tree_, t, bbpts, 2); @@ -2485,11 +2652,13 @@ static void calc_subdivided_non_cluster_tris(Array<IMesh> &r_tri_subdivided, 0, overlap_tri_range_tot, &data, calc_subdivided_tri_range_func, &settings); /* Now have to put in the triangles that are the same as the input ones, and not in clusters. */ - for (int t : tm.face_index_range()) { - if (r_tri_subdivided[t].face_size() == 0 && clinfo.tri_cluster(t) == NO_INDEX) { - r_tri_subdivided[t] = IMesh({tm.face(t)}); + threading::parallel_for(tm.face_index_range(), 2048, [&](IndexRange range) { + for (int t : range) { + if (r_tri_subdivided[t].face_size() == 0 && clinfo.tri_cluster(t) == NO_INDEX) { + r_tri_subdivided[t] = IMesh({tm.face(t)}); + } } - } + }); } /** @@ -2725,33 +2894,6 @@ static CoplanarClusterInfo find_clusters(const IMesh &tm, return ans; } -static bool face_is_degenerate(const Face *f) -{ - const Face &face = *f; - const Vert *v0 = face[0]; - const Vert *v1 = face[1]; - const Vert *v2 = face[2]; - if (v0 == v1 || v0 == v2 || v1 == v2) { - return true; - } - double3 da = v2->co - v0->co; - double3 db = v2->co - v1->co; - double3 dab = double3::cross_high_precision(da, db); - double dab_length_squared = dab.length_squared(); - double err_bound = supremum_dot_cross(dab, dab) * index_dot_cross * DBL_EPSILON; - if (dab_length_squared > err_bound) { - return false; - } - mpq3 a = v2->co_exact - v0->co_exact; - mpq3 b = v2->co_exact - v1->co_exact; - mpq3 ab = mpq3::cross(a, b); - if (ab.x == 0 && ab.y == 0 && ab.z == 0) { - return true; - } - - return false; -} - /* Data and functions to test triangle degeneracy in parallel. */ struct DegenData { const IMesh &tm; @@ -2873,11 +3015,15 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in, double overlap_time = PIL_check_seconds_timer(); std::cout << "intersect overlaps calculated, time = " << overlap_time - bb_calc_time << "\n"; # endif - for (int t : tm_clean->face_index_range()) { - if (tri_ov.first_overlap_index(t) != -1) { - tm_clean->face(t)->populate_plane(true); + Array<IMesh> tri_subdivided(tm_clean->face_size(), NoInitialization()); + threading::parallel_for(tm_clean->face_index_range(), 1024, [&](IndexRange range) { + for (int t : range) { + if (tri_ov.first_overlap_index(t) != -1) { + tm_clean->face(t)->populate_plane(true); + } + new (static_cast<void *>(&tri_subdivided[t])) IMesh; } - } + }); # ifdef PERFDEBUG double plane_populate = PIL_check_seconds_timer(); std::cout << "planes populated, time = " << plane_populate - overlap_time << "\n"; @@ -2902,7 +3048,6 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in, doperfmax(1, clinfo.tot_cluster()); doperfmax(2, tri_ov.overlap().size()); # endif - Array<IMesh> tri_subdivided(tm_clean->face_size()); calc_subdivided_non_cluster_tris(tri_subdivided, *tm_clean, itt_map, clinfo, tri_ov, arena); # ifdef PERFDEBUG double subdivided_tris_time = PIL_check_seconds_timer(); diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 8e28088c9fa..01aad5b078f 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -884,7 +884,7 @@ static float dist_Real(float x, float y, float z, float e) (void)e; return sqrtf(x * x + y * y + z * z); } -/* manhattan/taxicab/cityblock distance */ +/* Manhattan/Taxi-Cab/City-Block distance. */ static float dist_Manhattan(float x, float y, float z, float e) { (void)e; diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index f3c348b2b44..4d0dc43ed1e 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -235,13 +235,13 @@ void BLI_path_normalize(const char *relabase, char *path) memmove(path + a, eind, strlen(eind) + 1); } else { - /* support for odd paths: eg /../home/me --> /home/me + /* Support for odd paths: eg `/../home/me` --> `/home/me` * this is a valid path in blender but we can't handle this the usual way below * simply strip this prefix then evaluate the path as usual. - * pythons os.path.normpath() does this */ + * Python's `os.path.normpath()` does this. */ - /* Note: previous version of following call used an offset of 3 instead of 4, - * which meant that the "/../home/me" example actually became "home/me". + /* NOTE: previous version of following call used an offset of 3 instead of 4, + * which meant that the `/../home/me` example actually became `home/me`. * Using offset of 3 gives behavior consistent with the aforementioned * Python routine. */ memmove(path, path + 3, strlen(path + 3) + 1); @@ -1070,8 +1070,8 @@ bool BLI_path_abs(char *path, const char *basepath) * paths relative to the .blend file -elubie */ BLI_str_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/'); - /* Paths starting with // will get the blend file as their base, - * this isn't standard in any os but is used in blender all over the place */ + /* Paths starting with `//` will get the blend file as their base, + * this isn't standard in any OS but is used in blender all over the place. */ if (wasrelative) { const char *lslash; BLI_strncpy(base, basepath, sizeof(base)); @@ -1275,7 +1275,7 @@ void BLI_setenv(const char *env, const char *val) { /* free windows */ -#if (defined(WIN32) || defined(WIN64)) +#if (defined(_WIN32) || defined(_WIN64)) uputenv(env, val); #else diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c index dadef979b09..817572ba85c 100644 --- a/source/blender/blenlib/intern/polyfill_2d.c +++ b/source/blender/blenlib/intern/polyfill_2d.c @@ -719,7 +719,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) * the area sign will be positive if the point is strictly inside. * It will be 0 on the edge, which we want to include as well. */ - /* note: check (v3, v1) first since it fails _far_ more often than the other 2 checks + /* NOTE: check (v3, v1) first since it fails _far_ more often than the other 2 checks * (those fail equally). * It's logical - the chance is low that points exist on the * same side as the ear we're clipping off. */ diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index 7425bab885c..7781e3a0f6f 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -175,7 +175,7 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2], len_13 = len_v2v2(v1, v3); len_24 = len_v2v2(v2, v4); - /* note, area is in fact (area * 2), + /* NOTE: area is in fact (area * 2), * but in this case its OK, since we're comparing ratios */ /* edge (2-4), current state */ diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 8c9a229860e..b0d00007580 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -397,7 +397,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx) for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { if (eve->edge_tot == 1) { /* find the edge which has vertex eve, - * note: we _know_ this will crash if 'ed1' becomes NULL + * NOTE: we _know_ this will crash if 'ed1' becomes NULL * but this will never happen. */ for (ed1 = sf_ctx->filledgebase.first; !(ed1->v1 == eve || ed1->v2 == eve); ed1 = ed1->next) { @@ -529,7 +529,7 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl eve->f = SF_VERT_NEW; /* Flag for connect edges later on. */ sc->vert = eve; sc->edge_first = sc->edge_last = NULL; - /* Note, debug print only will work for curve poly-fill, union is in use for mesh. */ + /* NOTE: debug print only will work for curve poly-fill, union is in use for mesh. */ /* if (even->tmp.v == NULL) eve->tmp.u = verts; */ sc++; } diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c index 5961893cae3..6e5a3e961a5 100644 --- a/source/blender/blenlib/intern/smallhash.c +++ b/source/blender/blenlib/intern/smallhash.c @@ -124,7 +124,7 @@ BLI_INLINE SmallHashEntry *smallhash_lookup(const SmallHash *sh, const uintptr_t BLI_assert(key != SMHASH_KEY_UNUSED); - /* note: there are always more buckets than entries, + /* NOTE: there are always more buckets than entries, * so we know there will always be a free bucket if the key isn't found. */ for (e = &sh->buckets[h % sh->nbuckets]; e->val != SMHASH_CELL_FREE; h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) { @@ -353,8 +353,8 @@ void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr /** \name Debugging & Introspection * \{ */ -/* note, this was called _print_smhash in knifetool.c - * it may not be intended for general use - campbell */ +/* NOTE(campbell): this was called _print_smhash in knifetool.c + * it may not be intended for general use. */ #if 0 void BLI_smallhash_print(SmallHash *sh) { diff --git a/source/blender/blenlib/intern/sort.c b/source/blender/blenlib/intern/sort.c index 6a13c0aa6f0..0d52faaa8c6 100644 --- a/source/blender/blenlib/intern/sort.c +++ b/source/blender/blenlib/intern/sort.c @@ -31,7 +31,7 @@ # include "BLI_sort.h" -# ifdef min /* for msvc */ +# ifdef min /* For MSVC. */ # undef min # endif diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 3a02ddaa349..19ff8764259 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -43,7 +43,7 @@ // #define DEBUG_STRSIZE /* array copied from glib's gutf8.c, */ -/* Note: last two values (0xfe and 0xff) are forbidden in utf-8, +/* NOTE: last two values (0xfe and 0xff) are forbidden in utf-8, * so they are considered 1 byte length too. */ static const size_t utf8_skip_data[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -265,7 +265,7 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - /* note: currently we don't attempt to deal with invalid utf8 chars */ + /* NOTE: currently we don't attempt to deal with invalid utf8 chars. */ BLI_STR_UTF8_CPY(dst, src, maxncpy); return r_dst; @@ -281,7 +281,7 @@ size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, s memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - /* note: currently we don't attempt to deal with invalid utf8 chars */ + /* NOTE: currently we don't attempt to deal with invalid utf8 chars. */ BLI_STR_UTF8_CPY(dst, src, maxncpy); return (size_t)(dst - r_dst); @@ -444,8 +444,8 @@ int BLI_str_utf8_char_width_safe(const char *p) /* copied from glib's gutf8.c, added 'Err' arg */ -/* note, glib uses uint for unicode, best we do the same, - * though we don't typedef it - campbell */ +/* NOTE(campbell): glib uses uint for unicode, best we do the same, + * though we don't typedef it. */ #define UTF8_COMPUTE(Char, Mask, Len, Err) \ if (Char < 128) { \ @@ -580,8 +580,10 @@ uint BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__r return result; } -/* another variant that steps over the index, - * note, currently this also falls back to latin1 for text drawing. */ +/** + * Another variant that steps over the index. + * \note currently this also falls back to latin1 for text drawing. + */ uint BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) { int i, len; diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index f4110c65a6d..66d0b44cfb3 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -100,8 +100,8 @@ void BLI_system_backtrace(FILE *fp) # undef SIZE # else - /* ------------------ */ - /* non msvc/osx/linux */ + /* --------------------- */ + /* Non MSVC/Apple/Linux. */ (void)fp; # endif } @@ -184,7 +184,7 @@ size_t BLI_system_memory_max_in_megabytes(void) /* Maximum addressable bytes on this platform. * * NOTE: Due to the shift arithmetic this is a half of the memory. */ - const size_t limit_bytes_half = (((size_t)1) << ((sizeof(size_t[8])) - 1)); + const size_t limit_bytes_half = (((size_t)1) << (sizeof(size_t[8]) - 1)); /* Convert it to megabytes and return. */ return (limit_bytes_half >> 20) * 2; } diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index f67671c65e0..06087869685 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -80,7 +80,7 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin * else 3 if num_tasks < 48; * else 4 if num_tasks < 64; * etc. - * Note: If we wanted to keep the 'power of two' multiplier, we'd need something like: + * NOTE: If we wanted to keep the 'power of two' multiplier, we'd need something like: * 1 << max_ii(0, (int)(sizeof(int) * 8) - 1 - bitscan_reverse_i(num_tasks) - 3) */ const int num_tasks_factor = max_ii(1, num_tasks >> 3); @@ -186,6 +186,9 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin if (use_userdata_chunk) { userdata_chunk_local = MALLOCA(userdata_chunk_size); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(state->userdata, userdata_chunk_local); + } } /* Also marking it as non-threaded for the iterator callback. */ @@ -247,6 +250,9 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(state->userdata, userdata_chunk_local); + } } /* Use this pool's pre-allocated tasks. */ BLI_task_pool_push(task_pool, parallel_iterator_func, userdata_chunk_local, false, NULL); @@ -403,11 +409,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, TaskParallelMempoolFunc func, const TaskParallelSettings *settings) { - TaskPool *task_pool; - ParallelMempoolState state; - int i, num_threads, num_tasks; - - if (BLI_mempool_len(mempool) == 0) { + if (UNLIKELY(BLI_mempool_len(mempool) == 0)) { return; } @@ -422,6 +424,9 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, if (use_userdata_chunk) { userdata_chunk_local = MALLOCA(userdata_chunk_size); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(userdata, userdata_chunk_local); + } tls.userdata_chunk = userdata_chunk_local; } @@ -442,14 +447,15 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, return; } - task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); - num_threads = BLI_task_scheduler_num_threads(); + ParallelMempoolState state; + TaskPool *task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); + const int num_threads = BLI_task_scheduler_num_threads(); /* The idea here is to prevent creating task for each of the loop iterations * and instead have tasks which are evenly distributed across CPU cores and * pull next item to be crunched using the threaded-aware BLI_mempool_iter. */ - num_tasks = num_threads + 2; + const int num_tasks = num_threads + 2; state.userdata = userdata; state.func = func; @@ -461,10 +467,13 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, ParallelMempoolTaskData *mempool_iterator_data = mempool_iter_threadsafe_create( mempool, (size_t)num_tasks); - for (i = 0; i < num_tasks; i++) { + for (int i = 0; i < num_tasks; i++) { if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(userdata, userdata_chunk_local); + } } mempool_iterator_data[i].tls.userdata_chunk = userdata_chunk_local; @@ -477,7 +486,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, if (use_userdata_chunk) { if ((settings->func_free != NULL) || (settings->func_reduce != NULL)) { - for (i = 0; i < num_tasks; i++) { + for (int i = 0; i < num_tasks; i++) { if (settings->func_reduce) { settings->func_reduce( userdata, userdata_chunk, mempool_iterator_data[i].tls.userdata_chunk); diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc index 871d04c1f35..8407be2cb2b 100644 --- a/source/blender/blenlib/intern/task_range.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -156,7 +156,7 @@ int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls)) if (thread_id == -1) { thread_id = atomic_fetch_and_add_int32(&tbb_thread_id_counter, 1); if (thread_id >= BLENDER_MAX_THREADS) { - BLI_assert(!"Maximum number of threads exceeded for sculpting"); + BLI_assert_msg(0, "Maximum number of threads exceeded for sculpting"); thread_id = thread_id % BLENDER_MAX_THREADS; } } diff --git a/source/blender/blenlib/tests/BLI_array_utils_test.cc b/source/blender/blenlib/tests/BLI_array_utils_test.cc index 5d12b8fbd4d..1bf221c5335 100644 --- a/source/blender/blenlib/tests/BLI_array_utils_test.cc +++ b/source/blender/blenlib/tests/BLI_array_utils_test.cc @@ -189,3 +189,53 @@ TEST(array_utils, BinaryOrInt4Mix) BINARY_OR_TEST(data_cmp, data_a, data_b, data_combine, ARRAY_SIZE(data_cmp)); } #undef BINARY_OR_TEST + +/* BLI_array_deduplicate_ordered */ +#define DEDUPLICATE_ORDERED_TEST(data, data_cmp) \ + { \ + const uint data_len_new = BLI_array_deduplicate_ordered(data, ARRAY_SIZE(data)); \ + EXPECT_EQ(data_len_new, ARRAY_SIZE(data_cmp)); \ + EXPECT_EQ_ARRAY(data, data_cmp, data_len_new); \ + /* Ensure running a second time does nothing. */ \ + const uint data_len_test = BLI_array_deduplicate_ordered(data, data_len_new); \ + EXPECT_EQ(data_len_test, ARRAY_SIZE(data_cmp)); \ + EXPECT_EQ_ARRAY(data, data_cmp, data_len_new); \ + } \ + ((void)0) + +TEST(array_utils, DeduplicateOrdered1) +{ + int data[] = {0}; + const int data_cmp[] = {0}; + DEDUPLICATE_ORDERED_TEST(data, data_cmp); +} + +TEST(array_utils, DeduplicateOrdered2) +{ + int data[] = {1, 2}; + const int data_cmp[] = {1, 2}; + DEDUPLICATE_ORDERED_TEST(data, data_cmp); +} + +TEST(array_utils, DeduplicateOrdered2Same) +{ + int data[] = {1, 1}; + const int data_cmp[] = {1}; + DEDUPLICATE_ORDERED_TEST(data, data_cmp); +} + +TEST(array_utils, DeduplicateOrdered3Same) +{ + int data[] = {1, 1, 1}; + const int data_cmp[] = {1}; + DEDUPLICATE_ORDERED_TEST(data, data_cmp); +} + +TEST(array_utils, DeduplicateOrdered3) +{ + int data[] = {3, 3, 2, 2, 1, 1}; + const int data_cmp[] = {3, 2, 1}; + DEDUPLICATE_ORDERED_TEST(data, data_cmp); +} + +#undef DEDUPLICATE_ORDERED_TEST diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc index 59c4be6d952..08a3818e18f 100644 --- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc @@ -353,27 +353,27 @@ void graph_draw(const std::string &label, const vec2<T> &uco = verts[e.first]; const vec2<T> &vco = verts[e.second]; int strokew = thin_line; - f << "<line fill=\"none\" stroke=\"black\" stroke-width=\"" << strokew << "\" x1=\"" + f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\"" << SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\"" << SY(vco[1]) << "\">\n"; f << " <title>[" << e.first << "][" << e.second << "]</title>\n"; f << "</line>\n"; if (draw_edge_labels) { f << "<text x=\"" << SX(0.5 * (uco[0] + vco[0])) << "\" y=\"" << SY(0.5 * (uco[1] + vco[1])) - << "\" font-size=\"small\">"; + << R"(" font-size="small">)"; f << "[" << e.first << "][" << e.second << "]</text>\n"; } } int i = 0; for (const vec2<T> &vco : verts) { - f << "<circle fill=\"black\" cx=\"" << SX(vco[0]) << "\" cy=\"" << SY(vco[1]) << "\" r=\"" + f << R"(<circle fill="black" cx=")" << SX(vco[0]) << "\" cy=\"" << SY(vco[1]) << "\" r=\"" << vert_radius << "\">\n"; f << " <title>[" << i << "]" << vco << "</title>\n"; f << "</circle>\n"; if (draw_vert_labels) { f << "<text x=\"" << SX(vco[0]) + vert_radius << "\" y=\"" << SY(vco[1]) - vert_radius - << "\" font-size=\"small\">[" << i << "]</text>\n"; + << R"(" font-size="small">[)" << i << "]</text>\n"; } ++i; } diff --git a/source/blender/blenlib/tests/BLI_ghash_test.cc b/source/blender/blenlib/tests/BLI_ghash_test.cc index a0b24e96fcc..1eb29a006db 100644 --- a/source/blender/blenlib/tests/BLI_ghash_test.cc +++ b/source/blender/blenlib/tests/BLI_ghash_test.cc @@ -31,7 +31,7 @@ } \ void(0) -/* Note: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here +/* NOTE: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here * we just use mere random integers stored in pointers. */ static void init_keys(unsigned int keys[TESTCASE_SIZE], const int seed) diff --git a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc index c7bea8e15de..c6d3265881d 100644 --- a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc +++ b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc @@ -4,7 +4,7 @@ #include "BLI_hash_mm2a.h" -/* Note: Reference results are taken from reference implementation +/* NOTE: Reference results are taken from reference implementation * (cpp code, CMurmurHash2A variant): * https://smhasher.googlecode.com/svn-history/r130/trunk/MurmurHash2.cpp */ diff --git a/source/blender/blenlib/tests/BLI_math_base_test.cc b/source/blender/blenlib/tests/BLI_math_base_test.cc index d006a2eb59a..f354dd4ce23 100644 --- a/source/blender/blenlib/tests/BLI_math_base_test.cc +++ b/source/blender/blenlib/tests/BLI_math_base_test.cc @@ -72,7 +72,7 @@ TEST(math_base, CompareFFRelativeZero) EXPECT_TRUE(compare_ff_relative(f0, fn1, max_diff, 1)); EXPECT_TRUE(compare_ff_relative(fn1, f0, max_diff, 1)); - /* Note: in theory, this should return false, since 0.0f and -0.0f have 0x80000000 diff, + /* NOTE: in theory, this should return false, since 0.0f and -0.0f have 0x80000000 diff, * but overflow in subtraction seems to break something here * (abs(*(int *)&fn0 - *(int *)&f0) == 0x80000000 == fn0), probably because int32 cannot * hold this abs value. this is yet another illustration of why one shall never use (near-)zero diff --git a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc index 1a9ffbd3403..24fa7f1a476 100644 --- a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc +++ b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc @@ -459,7 +459,7 @@ TEST(mesh_intersect, TwoTris) {4, 13, 6, 2}, /* 11: non-parallel planes, not intersecting, all one side. */ {0, 14, 6, 2}, /* 12: non-paralel planes, not intersecting, alternate sides. */ /* Following are all coplanar cases. */ - {15, 16, 6, 8}, /* 13: T16 inside T15. Note: dup'd tri is expected. */ + {15, 16, 6, 8}, /* 13: T16 inside T15. NOTE: dup'd tri is expected. */ {15, 17, 8, 8}, /* 14: T17 intersects one edge of T15 at (1,1,0)(3,3,0). */ {15, 18, 10, 12}, /* 15: T18 intersects T15 at (1,1,0)(3,3,0)(3,15/4,1/2)(0,3,2). */ {15, 19, 8, 10}, /* 16: T19 intersects T15 at (3,3,0)(0,3,2). */ diff --git a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc index c5b0f86e384..dd1a084037b 100644 --- a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc +++ b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc @@ -21,7 +21,7 @@ static uint gen_pseudo_random_number(uint num) { - /* Note: this is taken from BLI_ghashutil_uinthash(), don't want to depend on external code that + /* NOTE: this is taken from BLI_ghashutil_uinthash(), don't want to depend on external code that * might change here... */ num += ~(num << 16); num ^= (num >> 5); diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 52ef577fceb..04e13fbd1d6 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -74,7 +74,7 @@ typedef struct BlendFileData { int globalf; char filename[1024]; /* 1024 = FILE_MAX */ - struct bScreen *curscreen; /* TODO think this isn't needed anymore? */ + struct bScreen *curscreen; /* TODO: think this isn't needed anymore? */ struct Scene *curscene; struct ViewLayer *cur_view_layer; /* layer to activate in workspaces when reading without UI */ diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 61a00ccdaa4..f5baf0dcb83 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -58,8 +58,8 @@ set(SRC intern/versioning_280.c intern/versioning_290.c intern/versioning_300.c - intern/versioning_cycles.c intern/versioning_common.cc + intern/versioning_cycles.c intern/versioning_defaults.c intern/versioning_dna.c intern/versioning_legacy.c diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 5b668bf12eb..03fb4149d7b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2311,7 +2311,7 @@ static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id) static void lib_link_id(BlendLibReader *reader, ID *id) { - /* Note: WM IDProperties are never written to file, hence they should always be NULL here. */ + /* NOTE: WM IDProperties are never written to file, hence they should always be NULL here. */ BLI_assert((GS(id->name) != ID_WM) || id->properties == NULL); IDP_BlendReadLib(reader, id->properties); @@ -2728,7 +2728,7 @@ static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data) struct IDNameLib_Map *id_map = cb_data->user_data; - /* Note: Handling of usercount here is really bad, defining its own system... + /* NOTE: Handling of usercount here is really bad, defining its own system... * Will have to be refactored at some point, but that is not top priority task for now. * And all user-counts are properly recomputed at the end of the undo management code anyway. */ *id_pointer = restore_pointer_by_name( @@ -3067,7 +3067,7 @@ void blo_lib_link_restore(Main *oldmain, /* keep cursor location through undo */ memcpy(&win->scene->cursor, &oldscene->cursor, sizeof(win->scene->cursor)); - /* Note: even though that function seems to redo part of what is done by + /* NOTE: even though that function seems to redo part of what is done by * `lib_link_workspace_layout_restore()` above, it seems to have a slightly different scope: * while the former updates the whole UI pointers from Main db (going over all layouts of * all workspaces), that one only focuses one current active screen, takes care of @@ -3780,7 +3780,7 @@ BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_a /** \name Read Global Data * \{ */ -/* note, this has to be kept for reading older files... */ +/* NOTE: this has to be kept for reading older files... */ /* also version info is written here */ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead) { @@ -3828,7 +3828,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead) return blo_bhead_next(fd, bhead); } -/* note, this has to be kept for reading older files... */ +/* NOTE: this has to be kept for reading older files... */ static void link_global(FileData *fd, BlendFileData *bfd) { bfd->cur_view_layer = blo_read_get_new_globaldata_address(fd, bfd->cur_view_layer); @@ -5611,7 +5611,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) lib_link_all(mainptr->curlib->filedata, mainptr); } - /* Note: No need to call #do_versions_after_linking() or #BKE_main_id_refcount_recompute() + /* NOTE: No need to call #do_versions_after_linking() or #BKE_main_id_refcount_recompute() * here, as this function is only called for library 'subset' data handling, as part of * either full blendfile reading (#blo_read_file_internal()), or library-data linking * (#library_link_end()). */ diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c index d1f69d35fe5..2eeeac2e8d7 100644 --- a/source/blender/blenloader/intern/undofile.c +++ b/source/blender/blenloader/intern/undofile.c @@ -225,7 +225,7 @@ bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename) MemFileChunk *chunk; int file, oflags; - /* note: This is currently used for autosave and 'quit.blend', + /* NOTE: This is currently used for autosave and 'quit.blend', * where _not_ following symlinks is OK, * however if this is ever executed explicitly by the user, * we may want to allow writing to symlinks. diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 9399af5eb11..8a7bc375ea9 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -1274,7 +1274,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) */ if (ob->pose && ob->data) { bArmature *arm = blo_do_versions_newlibadr(fd, lib, ob->data); - if (arm) { /* XXX - why does this fail in some cases? */ + if (arm) { /* XXX: why does this fail in some cases? */ bAnimVizSettings *avs = &ob->pose->avs; /* path settings --------------------- */ diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 070dd181509..5bf4d3b68b5 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -169,7 +169,7 @@ static void do_versions_image_settings_2_60(Scene *sce) R_JPEG2K_CINE_48FPS = (1 << 9), }; - /* note: rd->subimtype is moved into individual settings now and no longer + /* NOTE: rd->subimtype is moved into individual settings now and no longer * exists */ RenderData *rd = &sce->r; ImageFormatData *imf = &sce->r.im_format; @@ -2594,11 +2594,11 @@ void do_versions_after_linking_260(Main *bmain) * * This assumes valid typeinfo pointers, as set in lib_link_ntree. * - * Note: theoretically only needed in node groups (main->nodetree), + * NOTE: theoretically only needed in node groups (main->nodetree), * but due to a temporary bug such links could have been added in all trees, * so have to clean up all of them ... * - * Note: this always runs, without it links with NULL fromnode and tonode remain + * NOTE: this always runs, without it links with NULL fromnode and tonode remain * which causes problems. */ if (!MAIN_VERSION_ATLEAST(bmain, 266, 3)) { diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 399761ead8d..0645380c4cb 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -670,7 +670,7 @@ static ARegion *do_versions_find_region(ListBase *regionbase, int regiontype) { ARegion *region = do_versions_find_region_or_null(regionbase, regiontype); if (region == NULL) { - BLI_assert(!"Did not find expected region in versioning"); + BLI_assert_msg(0, "Did not find expected region in versioning"); } return region; } @@ -1268,7 +1268,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) /* We need to assign lib pointer to generated hidden collections *after* all have been * created, otherwise we'll end up with several data-blocks sharing same name/library, - * which is FORBIDDEN! Note: we need this to be recursive, since a child collection may be + * which is FORBIDDEN! NOTE: we need this to be recursive, since a child collection may be * sorted before its parent in bmain. */ for (Collection *collection = bmain->collections.first; collection != NULL; collection = collection->id.next) { diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index ecee14d3d58..313ce734bbc 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -28,12 +28,18 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_brush_types.h" +#include "DNA_collection_types.h" #include "DNA_genfile.h" #include "DNA_listBase.h" #include "DNA_modifier_types.h" #include "DNA_text_types.h" +#include "DNA_workspace_types.h" +#include "BKE_action.h" #include "BKE_animsys.h" +#include "BKE_asset.h" +#include "BKE_collection.h" +#include "BKE_deform.h" #include "BKE_fcurve_driver.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -87,6 +93,19 @@ static void assert_sorted_ids(Main *bmain) #endif } +static void move_vertex_group_names_to_object_data(Main *bmain) +{ + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { + ListBase *new_defbase = BKE_object_defgroup_list_mutable(object); + + /* Clear the list in case the it was already assigned from another object. */ + BLI_freelistN(new_defbase); + *new_defbase = object->defbase; + } + } +} + void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports)) { if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) { @@ -131,6 +150,10 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports)) assert_sorted_ids(bmain); } + if (!MAIN_VERSION_ATLEAST(bmain, 300, 11)) { + move_vertex_group_names_to_object_data(bmain); + } + /** * Versioning code until next subversion bump goes here. * @@ -468,6 +491,55 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 300, 8)) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + if (scene->master_collection != NULL) { + BLI_strncpy(scene->master_collection->id.name + 2, + BKE_SCENE_COLLECTION_NAME, + sizeof(scene->master_collection->id.name) - 2); + } + } + } + + if (!MAIN_VERSION_ATLEAST(bmain, 300, 9)) { + /* Fix a bug where reordering FCurves and bActionGroups could cause some corruption. Just + * reconstruct all the action groups & ensure that the FCurves of a group are continuously + * stored (i.e. not mixed with other groups) to be sure. See T89435. */ + LISTBASE_FOREACH (bAction *, act, &bmain->actions) { + BKE_action_groups_reconstruct(act); + } + + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_MESH_SUBDIVIDE) { + strcpy(node->idname, "GeometryNodeMeshSubdivide"); + } + } + } + } + FOREACH_NODETREE_END; + + { + if (!DNA_struct_elem_find( + fd->filesdna, "WorkSpace", "AssetLibraryReference", "active_asset_library")) { + LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { + BKE_asset_library_reference_init_default(&workspace->active_asset_library); + } + } + } + } + + if (!MAIN_VERSION_ATLEAST(bmain, 300, 10)) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + ToolSettings *tool_settings = scene->toolsettings; + if (tool_settings->snap_uv_mode & (1 << 4)) { + tool_settings->snap_uv_mode |= (1 << 6); /* SCE_SNAP_MODE_INCREMENT */ + tool_settings->snap_uv_mode &= ~(1 << 4); + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -479,5 +551,24 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ + + /* Convert Surface Deform to sparse-capable bind structure. */ + if (!DNA_struct_elem_find( + fd->filesdna, "SurfaceDeformModifierData", "int", "num_mesh_verts")) { + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_SurfaceDeform) { + SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; + if (smd->num_bind_verts && smd->verts) { + smd->num_mesh_verts = smd->num_bind_verts; + + for (unsigned int i = 0; i < smd->num_bind_verts; i++) { + smd->verts[i].vertex_idx = i; + } + } + } + } + } + } } } diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 46e25251fd4..95cfc9975d7 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1311,7 +1311,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } } - /* Note: #BKE_pose_rebuild is further only called on leave edit-mode. */ + /* NOTE: #BKE_pose_rebuild is further only called on leave edit-mode. */ if (ob->type == OB_ARMATURE) { if (ob->pose) { BKE_pose_tag_recalc(bmain, ob->pose); @@ -1436,7 +1436,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) bPoseChannel *pchan; bConstraint *con; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - /* note, pchan->bone is also lib-link stuff */ + /* NOTE: pchan->bone is also lib-link stuff. */ if (pchan->limitmin[0] == 0.0f && pchan->limitmax[0] == 0.0f) { pchan->limitmin[0] = pchan->limitmin[1] = pchan->limitmin[2] = -180.0f; pchan->limitmax[0] = pchan->limitmax[1] = pchan->limitmax[2] = 180.0f; @@ -2501,7 +2501,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 248, 2)) { Scene *sce; - /* Note, these will need to be added for painting */ + /* NOTE: these will need to be added for painting. */ for (sce = bmain->scenes.first; sce; sce = sce->id.next) { sce->toolsettings->imapaint.seam_bleed = 2; sce->toolsettings->imapaint.normal_angle = 80; diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 42b27f57e2c..30587418f84 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -894,6 +894,7 @@ void blo_do_versions_userdef(UserDef *userdef) */ { /* Keep this block, even when empty. */ + BKE_addon_ensure(&userdef->addons, "pose_library"); } LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 930ce0ba06f..fc29b1d8915 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -304,7 +304,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, size_t memlen) } if (memlen > INT_MAX) { - BLI_assert(!"Cannot write chunks bigger than INT_MAX."); + BLI_assert_msg(0, "Cannot write chunks bigger than INT_MAX."); return; } @@ -538,7 +538,7 @@ static void writedata(WriteData *wd, int filecode, size_t len, const void *adr) } if (len > INT_MAX) { - BLI_assert(!"Cannot write chunks bigger than INT_MAX."); + BLI_assert_msg(0, "Cannot write chunks bigger than INT_MAX."); return; } @@ -896,9 +896,10 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) writestruct(wd, GLOB, FileGlobal, 1, &fg); } -/* preview image, first 2 values are width and height - * second are an RGBA image (uchar) - * note, this uses 'TEST' since new types will segfault on file load for older blender versions. +/** + * Preview image, first 2 values are width and height + * second are an RGBA image (uchar). + * \note this uses 'TEST' since new types will segfault on file load for older blender versions. */ static void write_thumb(WriteData *wd, const BlendThumbnail *thumb) { diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt index 70e68ca06d7..bfb812ac64d 100644 --- a/source/blender/blentranslation/CMakeLists.txt +++ b/source/blender/blentranslation/CMakeLists.txt @@ -59,7 +59,7 @@ if(WITH_PYTHON) ) endif() -if(WIN32) +if(WIN32 OR APPLE) if(WITH_INPUT_IME) add_definitions(-DWITH_INPUT_IME) endif() diff --git a/source/blender/blentranslation/intern/blt_translation.c b/source/blender/blentranslation/intern/blt_translation.c index b5c0addfdfa..89a2f6c3ac0 100644 --- a/source/blender/blentranslation/intern/blt_translation.c +++ b/source/blender/blentranslation/intern/blt_translation.c @@ -47,7 +47,7 @@ bool BLT_is_default_context(const char *msgctxt) /* We use the "short" test, a more complete one could be: * return (!msgctxt || !msgctxt[0] || STREQ(msgctxt, BLT_I18NCONTEXT_DEFAULT_BPYRNA)) */ - /* Note: trying without the void string check for now, it *should* not be necessary... */ + /* NOTE: trying without the void string check for now, it *should* not be necessary... */ return (!msgctxt || msgctxt[0] == BLT_I18NCONTEXT_DEFAULT_BPYRNA[0]); } diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c index 720be11d3b7..f95bf2a9037 100644 --- a/source/blender/blentranslation/msgfmt/msgfmt.c +++ b/source/blender/blentranslation/msgfmt/msgfmt.c @@ -313,7 +313,7 @@ static int make(const char *input_file_name, const char *output_file_name) const size_t msgid_plural_len = strlen(msgid_plural_kw); const size_t msgstr_len = strlen(msgstr_kw); - /* Note: For now, we assume file encoding is always utf-8. */ + /* NOTE: For now, we assume file encoding is always utf-8. */ eSectionType section = SECTION_NONE; bool is_plural = false; diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index e3efeec951e..423d64ba62c 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -23,6 +23,8 @@ * that benefit from accessing connectivity information. */ +#include "BLI_assert.h" + /* disable holes for now, * these are ifdef'd because they use more memory and can't be saved in DNA currently */ // #define USE_BMESH_HOLES @@ -37,7 +39,7 @@ struct MLoopNorSpaceArray; struct BLI_mempool; -/* note: it is very important for BMHeader to start with two +/* NOTE: it is very important for BMHeader to start with two * pointers. this is a requirement of mempool's method of * iteration. * diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index f79f1925560..6f7b2cbc79f 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -415,7 +415,7 @@ static void bm_vert_attrs_copy( BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, CustomDataMask mask_exclude) { if ((bm_src == bm_dst) && (v_src == v_dst)) { - BLI_assert(!"BMVert: source and target match"); + BLI_assert_msg(0, "BMVert: source and target match"); return; } if ((mask_exclude & CD_MASK_NORMAL) == 0) { @@ -430,7 +430,7 @@ static void bm_edge_attrs_copy( BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, CustomDataMask mask_exclude) { if ((bm_src == bm_dst) && (e_src == e_dst)) { - BLI_assert(!"BMEdge: source and target match"); + BLI_assert_msg(0, "BMEdge: source and target match"); return; } CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->edata, e_dst->head.data, mask_exclude); @@ -442,7 +442,7 @@ static void bm_loop_attrs_copy( BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude) { if ((bm_src == bm_dst) && (l_src == l_dst)) { - BLI_assert(!"BMLoop: source and target match"); + BLI_assert_msg(0, "BMLoop: source and target match"); return; } CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->ldata, l_dst->head.data, mask_exclude); @@ -454,7 +454,7 @@ static void bm_face_attrs_copy( BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, CustomDataMask mask_exclude) { if ((bm_src == bm_dst) && (f_src == f_dst)) { - BLI_assert(!"BMFace: source and target match"); + BLI_assert_msg(0, "BMFace: source and target match"); return; } if ((mask_exclude & CD_MASK_NORMAL) == 0) { @@ -800,7 +800,7 @@ short BM_edge_flag_to_mflag(BMEdge *e) ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) | ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) | - ((BM_edge_is_wire(e)) ? ME_LOOSEEDGE : 0) | /* not typical */ + (BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */ ME_EDGERENDER); } char BM_face_flag_to_mflag(BMFace *f) diff --git a/source/blender/bmesh/intern/bmesh_delete.c b/source/blender/bmesh/intern/bmesh_delete.c index f470361e5fb..9f2fb1370bb 100644 --- a/source/blender/bmesh/intern/bmesh_delete.c +++ b/source/blender/bmesh/intern/bmesh_delete.c @@ -205,7 +205,7 @@ void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type) /* BM functions * - * note! this is just a duplicate of the code above (bad!) + * NOTE: this is just a duplicate of the code above (bad!) * but for now keep in sync, its less hassle than having to create bmesh operator flags, * each time we need to remove some geometry. */ diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h index e9cdc120657..7694d4dbfb6 100644 --- a/source/blender/bmesh/intern/bmesh_error.h +++ b/source/blender/bmesh/intern/bmesh_error.h @@ -24,17 +24,46 @@ /*----------- bmop error system ----------*/ +/** + * \note More can be added as needed. + */ +typedef enum eBMOpErrorLevel { + /** + * Use when the operation could not succeed, + * typically from input that isn't sufficient for completing the operation. + */ + BMO_ERROR_CANCEL = 0, + /** + * Use this when one or more operations could not succeed, + * when the resulting mesh can be used (since some operations succeeded or no change was made). + * This is used by default. + */ + BMO_ERROR_WARN = 1, + /** + * The mesh resulting from this operation should not be used (where possible). + * It should not be left in a corrupt state either. + * + * See #BMBackup type & function calls. + */ + BMO_ERROR_FATAL = 2, +} eBMOpErrorLevel; + /* Pushes an error onto the bmesh error stack. * if msg is null, then the default message for the `errcode` is used. */ -void BMO_error_raise(BMesh *bm, BMOperator *owner, const char *msg) ATTR_NONNULL(1, 2, 3); +void BMO_error_raise(BMesh *bm, BMOperator *owner, eBMOpErrorLevel level, const char *msg) + ATTR_NONNULL(1, 2, 4); /* Gets the topmost error from the stack. * returns error code or 0 if no error. */ -bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op); -bool BMO_error_occurred(BMesh *bm); +bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level); +bool BMO_error_get_at_level(BMesh *bm, + eBMOpErrorLevel level, + const char **r_msg, + BMOperator **r_op); +bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level); /* Same as #BMO_error_get, only pops the error off the stack as well. */ -bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op); +bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level); void BMO_error_clear(BMesh *bm); /* This is meant for handling errors, like self-intersection test failures. diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index ff6274cff12..bd28022de4b 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -221,21 +221,21 @@ void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], { BMOIter iter; BMElem *ele; - int count = BMO_slot_buffer_count(slot_args, slot_name); + const int slot_len = BMO_slot_buffer_len(slot_args, slot_name); BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); - if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && count > 0) { - BMElem **array = count > stack_array_size ? MEM_mallocN(sizeof(ele) * count, __func__) : - stack_array; + if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && slot_len > 0) { + BMElem **array = slot_len > stack_array_size ? MEM_mallocN(sizeof(ele) * slot_len, __func__) : + stack_array; int i = 0; do { array[i++] = ele; } while ((ele = BMO_iter_step(&iter))); - BLI_assert(i <= count); + BLI_assert(i <= slot_len); - if (i != count) { + if (i != slot_len) { if ((void **)array != stack_array) { array = MEM_reallocN(array, sizeof(ele) * i); } diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 470aceeb756..4bb83492548 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -158,7 +158,7 @@ typedef void (*BMIter__begin_cb)(void *); typedef void *(*BMIter__step_cb)(void *); /* Iterator Structure */ -/* note: some of these vars are not used, +/* NOTE: some of these vars are not used, * so they have been commented to save stack space since this struct is used all over */ typedef struct BMIter { /* keep union first */ @@ -180,7 +180,7 @@ typedef struct BMIter { BMIter__begin_cb begin; BMIter__step_cb step; - int count; /* note, only some iterators set this, don't rely on it */ + int count; /* NOTE: only some iterators set this, don't rely on it. */ char itype; } BMIter; diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 40eed6238ca..9033e43374b 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -397,7 +397,7 @@ static BMLogEntry *bm_log_entry_create(void) /* Free the data in a log entry * - * Note: does not free the log entry itself */ + * NOTE: does not free the log entry itself. */ static void bm_log_entry_free(BMLogEntry *entry) { BLI_ghash_free(entry->deleted_verts, NULL, NULL); @@ -740,7 +740,7 @@ void BM_log_entry_drop(BMLogEntry *entry) bm_log_id_ghash_release(log, entry->added_verts); } else { - BLI_assert(!"Cannot drop BMLogEntry from middle"); + BLI_assert_msg(0, "Cannot drop BMLogEntry from middle"); } if (log->current_entry == entry) { diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 190698f504c..b70e26f51ea 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -1386,7 +1386,7 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); - /* note, better not attempt a fast path for selection as done with de-select + /* NOTE: better not attempt a fast path for selection as done with de-select * because hidden geometry and different selection modes can give different results, * we could of course check for no hidden faces and then use * quicker method but its not worth it. */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 456275cf157..bd0504b038a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -24,8 +24,8 @@ struct BMAllocTemplate; struct BMLoopNorEditDataArray; -struct MLoopNorSpaceArray; struct BMPartialUpdate; +struct MLoopNorSpaceArray; void BM_mesh_elem_toolflags_ensure(BMesh *bm); void BM_mesh_elem_toolflags_clear(BMesh *bm); diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c index 6ab7b8a2057..dea6561fe9a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.c +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c @@ -19,7 +19,7 @@ * * BM mesh normal calculation functions. * - * \see mesh_normals.c for the equivalent #Mesh functionality. + * \see mesh_normals.cc for the equivalent #Mesh functionality. */ #include "MEM_guardedalloc.h" @@ -33,6 +33,7 @@ #include "BLI_task.h" #include "BLI_utildefines.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_mesh.h" @@ -525,7 +526,7 @@ bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr) } /** - * BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c + * BMesh version of BKE_mesh_normals_loop_split() in `mesh_evaluate.cc` * Will use first clnors_data array, and fallback to cd_loop_clnors_offset * (use NULL and -1 to not use clnors). * @@ -604,7 +605,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge * as 'entry point', otherwise we can skip it. */ - /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store + /* NOTE: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store * mlfan_pivot's in a stack, to avoid having to fan again around * the vert during actual computation of clnor & clnorspace. However, this would complicate * the code, add more memory usage, and @@ -630,11 +631,14 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, { const BMVert *v_pivot = l_curr->v; const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co; - const BMVert *v_1 = BM_edge_other_vert(l_curr->e, v_pivot); + const BMVert *v_1 = l_curr->next->v; const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co; - const BMVert *v_2 = BM_edge_other_vert(l_curr->prev->e, v_pivot); + const BMVert *v_2 = l_curr->prev->v; const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; + BLI_assert(v_1 == BM_edge_other_vert(l_curr->e, v_pivot)); + BLI_assert(v_2 == BM_edge_other_vert(l_curr->prev->e, v_pivot)); + sub_v3_v3v3(vec_curr, co_1, co_pivot); normalize_v3(vec_curr); sub_v3_v3v3(vec_prev, co_2, co_pivot); @@ -700,9 +704,11 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, /* Only need to compute previous edge's vector once, * then we can just reuse old current one! */ { - const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot); + const BMVert *v_2 = lfan_pivot->next->v; const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; + BLI_assert(v_2 == BM_edge_other_vert(e_next, v_pivot)); + sub_v3_v3v3(vec_org, co_2, co_pivot); normalize_v3(vec_org); copy_v3_v3(vec_curr, vec_org); @@ -1281,7 +1287,7 @@ void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all) BMVert *v; BMLoop *l; BMIter viter, liter; - /* Note: we could use temp tag of BMItem for that, + /* NOTE: we could use temp tag of BMItem for that, * but probably better not use it in such a low-level func? * --mont29 */ BLI_bitmap *done_verts = BLI_BITMAP_NEW(bm->totvert, __func__); diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index f75497f2f19..5fa12397a07 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -183,7 +183,7 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v) } /* collapse the vertex */ - /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */ + /* NOTE: the baseedge can be a boundary of manifold, use this as join_faces arg. */ e = BM_vert_collapse_faces( bm, baseedge, v, 1.0, true, !BM_edge_is_boundary(baseedge), true, true); @@ -873,7 +873,7 @@ bool BM_edge_rotate_check(BMEdge *e) */ bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) { - /* note: for these vars 'old' just means initial edge state. */ + /* NOTE: for these vars 'old' just means initial edge state. */ float ed_dir_old[3]; /* edge vector */ float ed_dir_new[3]; /* edge vector */ @@ -1054,7 +1054,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f return NULL; } - /* note, this assumes joining the faces _didnt_ also remove the verts. + /* NOTE: this assumes joining the faces _didnt_ also remove the verts. * the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits * break this */ if ((l1 = BM_face_vert_share_loop(f, v1)) && (l2 = BM_face_vert_share_loop(f, v2)) && diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index a5cce41eee4..3978959a425 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -567,7 +567,7 @@ static BMOpDefine bmo_contextual_create_def = { }, /* slots_out */ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */ - /* note, this is for stand-alone edges only, not edges which are a part of newly created faces */ + /* NOTE: this is for stand-alone edges only, not edges which are a part of newly created faces. */ {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */ {{'\0'}}, }, @@ -724,7 +724,7 @@ static BMOpDefine bmo_edgenet_fill_def = { }; /* - * Edgenet Prepare. + * Edge-net Prepare. * * Identifies several useful edge loop cases and modifies them so * they'll become a face when edgenet_fill is called. The cases covered are: diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index d09c0ee428d..0f9488bd091 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -537,7 +537,7 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm, const bool do_flush); /* puts every element of type 'type' (which is a bitmask) with header - * flag 'flag', into a slot. note: ignores hidden elements + * flag 'flag', into a slot. NOTE: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set). */ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, @@ -547,7 +547,7 @@ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, const char hflag); /* puts every element of type 'type' (which is a bitmask) without - * header flag 'flag', into a slot. note: ignores hidden elements + * header flag 'flag', into a slot. NOTE: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set). */ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, @@ -565,8 +565,8 @@ void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); void *BMO_slot_buffer_get_single(BMOpSlot *slot); /* counts number of elements inside a slot array. */ -int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 303b5336a5c..cf7697ad35f 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -678,7 +678,7 @@ void BMO_mesh_selected_remap(BMesh *bm, } } -int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); @@ -691,7 +691,7 @@ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot return slot->len; } -int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -829,7 +829,7 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - /* TODO - collapse these loops into one */ + /* TODO: collapse these loops into one. */ if (htype & BM_VERT) { BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { @@ -890,7 +890,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - /* TODO - collapse these loops into one */ + /* TODO: collapse these loops into one. */ if (htype & BM_VERT) { BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { @@ -1061,7 +1061,7 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, ele_array = (BMHeader **)slot->data.buf; - /* TODO - collapse these loops into one */ + /* TODO: collapse these loops into one. */ if (htype & BM_VERT) { BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { @@ -1553,32 +1553,39 @@ typedef struct BMOpError { struct BMOpError *next, *prev; BMOperator *op; const char *msg; + eBMOpErrorLevel level; } BMOpError; void BMO_error_clear(BMesh *bm) { - while (BMO_error_pop(bm, NULL, NULL)) { + while (BMO_error_pop(bm, NULL, NULL, NULL)) { /* pass */ } } -void BMO_error_raise(BMesh *bm, BMOperator *owner, const char *msg) +void BMO_error_raise(BMesh *bm, BMOperator *owner, eBMOpErrorLevel level, const char *msg) { BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error"); err->msg = msg; err->op = owner; + err->level = level; BLI_addhead(&bm->errorstack, err); } -bool BMO_error_occurred(BMesh *bm) +bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level) { - return (BLI_listbase_is_empty(&bm->errorstack) == false); + for (const BMOpError *err = bm->errorstack.first; err; err = err->next) { + if (err->level == level) { + return true; + } + } + return false; } /* returns error code or 0 if no error */ -bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op) +bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level) { BMOpError *err = bm->errorstack.first; if (err == NULL) { @@ -1591,13 +1598,36 @@ bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op) if (r_op) { *r_op = err->op; } + if (r_level) { + *r_level = err->level; + } return true; } -bool BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op) +bool BMO_error_get_at_level(BMesh *bm, + eBMOpErrorLevel level, + const char **r_msg, + BMOperator **r_op) +{ + for (BMOpError *err = bm->errorstack.first; err; err = err->next) { + if (err->level >= level) { + if (r_msg) { + *r_msg = err->msg; + } + if (r_op) { + *r_op = err->op; + } + return true; + } + } + + return false; +} + +bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level) { - bool result = BMO_error_get(bm, msg, op); + bool result = BMO_error_get(bm, r_msg, r_op, r_level); if (result) { BMOpError *err = bm->errorstack.first; @@ -1953,7 +1983,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, return true; error: - /* non urgent todo - explain exactly what is failing */ + /* TODO: explain exactly what is failing (not urgent). */ fprintf(stderr, "%s: error parsing formatting string\n", __func__); fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt)); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 5397098a7f3..0aab10e7b1a 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -1296,7 +1296,7 @@ void BM_face_triangulate(BMesh *bm, r_edges_new[ne_i++] = e; } } - /* note, never disable tag's */ + /* NOTE: never disable tag's. */ } while ((l_iter = l_iter->next) != l_first); } diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 2c32cd39002..5be7f4a5f3b 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -20,8 +20,8 @@ * \ingroup bmesh */ -struct Heap; struct BMPartialUpdate; +struct Heap; #include "BLI_compiler_attrs.h" diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 0754564fa47..86a7d8153f0 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -49,7 +49,7 @@ * * \{ */ -/* Note: All these flags _must_ be cleared on exit */ +/* NOTE: All these flags _must_ be cleared on exit. */ /* face is a part of the edge-net (including the original face we're splitting) */ #define FACE_NET _FLAG_WALK @@ -337,7 +337,7 @@ static bool bm_face_split_edgenet_find_loop_walk(BMVert *v_init, /* in rare cases there may be edges with a single connecting vertex */ if (e_next != e_first) { do { - if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) && + if (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET) && (bm_edge_flagged_radial_count(e_next) < 2)) { BMVert *v_next; @@ -519,7 +519,7 @@ bool BM_face_split_edgenet(BMesh *bm, } while ((l_iter = l_iter->next) != l_first); #endif - /* Note: 'VERT_IN_QUEUE' is often not needed at all, + /* NOTE: 'VERT_IN_QUEUE' is often not needed at all, * however in rare cases verts are added multiple times to the queue, * that on its own is harmless but in _very_ rare cases, * the queue will overflow its maximum size, @@ -1299,7 +1299,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm, BMVert *v_delimit = (&edge_arr[i]->v1)[j]; BMVert *v_other; - /* note, remapping will _never_ map a vertex to an already mapped vertex */ + /* NOTE: remapping will _never_ map a vertex to an already mapped vertex. */ while (UNLIKELY((v_other = bm_face_split_edgenet_partial_connect(bm, v_delimit, f)))) { struct TempVertPair *tvp = BLI_memarena_alloc(mem_arena, sizeof(*tvp)); tvp->next = temp_vert_pairs.list; diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c index 8047b52b625..bc881040e4e 100644 --- a/source/blender/bmesh/intern/bmesh_query.c +++ b/source/blender/bmesh/intern/bmesh_query.c @@ -1544,12 +1544,12 @@ float BM_loop_calc_face_angle(const BMLoop *l) */ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3]) { - /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors + /* NOTE: we cannot use result of normal_tri_v3 here to detect colinear vectors * (vertex on a straight line) from zero value, * because it does not normalize both vectors before making cross-product. * Instead of adding two costly normalize computations, * just check ourselves for colinear case. */ - /* Note: FEPSILON might need some finer tweaking at some point? + /* NOTE: FEPSILON might need some finer tweaking at some point? * Seems to be working OK for now though. */ float v1[3], v2[3], v_tmp[3]; sub_v3_v3v3(v1, l->prev->v->co, l->v->co); @@ -1807,7 +1807,7 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta BM_edge_ordered_verts_ex(e, &v1, &v2, e_loop); sub_v3_v3v3(tvec, v1->co, v2->co); /* use for temp storage */ - /* note, we could average the tangents of both loops, + /* NOTE: we could average the tangents of both loops, * for non flat ngons it will give a better direction */ cross_v3_v3v3(r_tangent, tvec, e_loop->f->no); normalize_v3(r_tangent); @@ -2591,7 +2591,7 @@ double BM_mesh_calc_volume(BMesh *bm, bool is_signed) return vol; } -/* note, almost duplicate of BM_mesh_calc_edge_groups, keep in sync */ +/* NOTE: almost duplicate of #BM_mesh_calc_edge_groups, keep in sync. */ /** * Calculate isolated groups of faces with optional filtering. * @@ -2753,7 +2753,7 @@ int BM_mesh_calc_face_groups(BMesh *bm, return group_curr; } -/* note, almost duplicate of BM_mesh_calc_face_groups, keep in sync */ +/* NOTE: almost duplicate of #BM_mesh_calc_face_groups, keep in sync. */ /** * Calculate isolated groups of edges with optional filtering. * diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index b3b9536618c..ca51a9c39de 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -63,7 +63,7 @@ BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WAR void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL(); void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL(); void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL(); -/* note: +/* NOTE: * bmesh_radial_loop_next(BMLoop *l) / prev. * just use member access l->radial_next, l->radial_prev now */ diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 40f09d7e719..e66afcd88d9 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -842,7 +842,7 @@ static void *bmw_IslandManifoldWalker_step(BMWalker *walker) /* utility function to see if an edge is a part of an ngon boundary */ static bool bm_edge_is_single(BMEdge *e) { - return ((BM_edge_is_boundary(e)) && (e->l->f->len > 4) && + return (BM_edge_is_boundary(e) && (e->l->f->len > 4) && (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e))); } diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c index de26ca5ebd2..a72ff6363ed 100644 --- a/source/blender/bmesh/operators/bmo_beautify.c +++ b/source/blender/bmesh/operators/bmo_beautify.c @@ -59,7 +59,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) /* will over alloc if some edges can't be rotated */ edge_array = MEM_mallocN( - sizeof(*edge_array) * (size_t)BMO_slot_buffer_count(op->slots_in, "edges"), __func__); + sizeof(*edge_array) * (size_t)BMO_slot_buffer_len(op->slots_in, "edges"), __func__); BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c index 2663f271b6e..6296694f121 100644 --- a/source/blender/bmesh/operators/bmo_bisect_plane.c +++ b/source/blender/bmesh/operators/bmo_bisect_plane.c @@ -50,7 +50,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) BMO_slot_vec_get(op->slots_in, "plane_no", plane_no); if (is_zero_v3(plane_no)) { - BMO_error_raise(bm, op, "Zero normal given"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Zero normal given"); return; } @@ -68,7 +68,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) /* Use an array of vertices because 'geom' contains both verts and edges that may use them. * Removing a vert may remove and edge which is later checked by #BMO_ITER. * over-allocate the total possible vert count. */ - const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_count(op->slots_in, "geom")); + const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_len(op->slots_in, "geom")); BMVert **vert_arr = MEM_mallocN(sizeof(*vert_arr) * (size_t)vert_arr_max, __func__); BMOIter siter; BMVert *v; diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index 005b8a2f5e8..fb913d4f19f 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -576,12 +576,12 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) BM_mesh_edgeloops_calc_center(bm, &eloops); if (count < 2) { - BMO_error_raise(bm, op, "Select at least two edge loops"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Select at least two edge loops"); goto cleanup; } if (use_pairs && (count % 2)) { - BMO_error_raise(bm, op, "Select an even number of loops to bridge pairs"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Select an even number of loops to bridge pairs"); goto cleanup; } @@ -595,7 +595,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) } } if (!match) { - BMO_error_raise(bm, op, "Selected loops must have equal edge counts"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Selected loops must have equal edge counts"); goto cleanup; } } diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index b701c1291a6..abc040f7564 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -211,7 +211,7 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) /* connect faces */ while ((f = BLI_LINKSTACK_POP(faces))) { if (bm_face_connect_verts(bm, f, check_degenerate) == -1) { - BMO_error_raise(bm, op, "Could not connect vertices"); + BMO_error_raise(bm, op, BMO_ERROR_FATAL, "Could not connect vertices"); } } diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c index bc1111676a3..15ed930afd8 100644 --- a/source/blender/bmesh/operators/bmo_connect_concave.c +++ b/source/blender/bmesh/operators/bmo_connect_concave.c @@ -51,10 +51,10 @@ static int bm_edge_length_cmp(const void *a_, const void *b_) const BMEdge *e_a = *(const void **)a_; const BMEdge *e_b = *(const void **)b_; - int e_a_concave = ((BM_elem_flag_test(e_a->v1, BM_ELEM_TAG)) && - (BM_elem_flag_test(e_a->v2, BM_ELEM_TAG))); - int e_b_concave = ((BM_elem_flag_test(e_b->v1, BM_ELEM_TAG)) && - (BM_elem_flag_test(e_b->v2, BM_ELEM_TAG))); + int e_a_concave = (BM_elem_flag_test(e_a->v1, BM_ELEM_TAG) && + BM_elem_flag_test(e_a->v2, BM_ELEM_TAG)); + int e_b_concave = (BM_elem_flag_test(e_b->v1, BM_ELEM_TAG) && + BM_elem_flag_test(e_b->v2, BM_ELEM_TAG)); /* merge edges between concave edges last since these * are most likely to remain and be the main dividers */ diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index b57c8686e1c..660633e8a0f 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -571,7 +571,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3]) } /* create a new 'basis_nor' from the best direction. - * note: we could add the directions, + * NOTE: we could add the directions, * but this more often gives 45d rotated matrix, so just use the best one. */ copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor); project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index f38e2e08f33..a740e4d66e8 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -172,7 +172,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op_sub); /* return if edge net create did something */ - if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) { + if (BMO_slot_buffer_len(op_sub.slots_out, "faces.out")) { BMO_slot_copy(&op_sub, slots_out, "faces.out", op, slots_out, "faces.out"); BMO_op_finish(bm, &op_sub); return; @@ -184,14 +184,14 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) /* -------------------------------------------------------------------- */ /* Dissolve Face */ if (totf != 0) { /* should be (totf > 1)... see below */ - /* note: allow this to run on single faces so running on a single face + /* NOTE: allow this to run on single faces so running on a single face * won't go on to create a face, treating them as random */ BMOperator op_sub; BMO_op_initf(bm, &op_sub, op->flag, "dissolve_faces faces=%ff", ELE_NEW); BMO_op_exec(bm, &op_sub); /* if we dissolved anything, then return */ - if (BMO_slot_buffer_count(op_sub.slots_out, "region.out")) { + if (BMO_slot_buffer_len(op_sub.slots_out, "region.out")) { BMO_slot_copy(&op_sub, slots_out, "region.out", op, slots_out, "faces.out"); BMO_op_finish(bm, &op_sub); return; @@ -204,14 +204,14 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) /* Fill EdgeLoop's - fills isolated loops, different from edgenet */ if (tote > 2) { BMOperator op_sub; - /* note: in most cases 'edgenet_fill' will handle this case since in common cases + /* NOTE: in most cases 'edgenet_fill' will handle this case since in common cases * users fill in empty spaces, however its possible to have an edge selection around * existing geometry that makes 'edgenet_fill' fail. */ BMO_op_initf(bm, &op_sub, op->flag, "edgeloop_fill edges=%fe", ELE_NEW); BMO_op_exec(bm, &op_sub); /* return if edge loop fill did something */ - if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) { + if (BMO_slot_buffer_len(op_sub.slots_out, "faces.out")) { BMO_slot_copy(&op_sub, slots_out, "faces.out", op, slots_out, "faces.out"); BMO_op_finish(bm, &op_sub); return; @@ -280,7 +280,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) * last resort when all else fails. */ if (totv > 2) { - /* TODO, some of these vertices may be connected by edges, + /* TODO: some of these vertices may be connected by edges, * this connectivity could be used rather than treating * them as a bunch of isolated verts. */ diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 30c80d43b9c..efba0ec99ec 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -128,7 +128,11 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) { BMOIter oiter; BMFace *f; - BMFace ***regions = NULL; + /* List of face arrays, the first element in each array in the length. */ + struct { + BMFace **faces; + int faces_len; + } *regions = NULL, *region; BMFace **faces = NULL; BLI_array_declare(regions); BLI_array_declare(faces); @@ -158,9 +162,6 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) continue; } - BLI_array_clear(faces); - faces = NULL; /* Forces different allocation. */ - BMW_init(®walker, bm, BMW_ISLAND_MANIFOLD, @@ -171,56 +172,71 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BMW_FLAG_NOP, BMW_NIL_LAY); - for (f_iter = BMW_begin(®walker, f); f_iter; f_iter = BMW_step(®walker)) { - BLI_array_append(faces, f_iter); - } - BMW_end(®walker); + /* Check there are at least two faces before creating the array. */ + BMFace *faces_init[2]; + if ((faces_init[0] = BMW_begin(®walker, f)) && (faces_init[1] = BMW_step(®walker))) { + + BLI_assert(BLI_array_len(faces) == 0); + + BLI_array_append(faces, faces_init[0]); + BLI_array_append(faces, faces_init[1]); + + while ((f_iter = BMW_step(®walker))) { + BLI_array_append(faces, f_iter); + } + + for (i = 0; i < BLI_array_len(faces); i++) { + f_iter = faces[i]; + BMO_face_flag_disable(bm, f_iter, FACE_TAG); + BMO_face_flag_enable(bm, f_iter, FACE_ORIG); + } + + region = BLI_array_append_ret(regions); + region->faces = faces; + region->faces_len = BLI_array_len(faces); - for (i = 0; i < BLI_array_len(faces); i++) { - f_iter = faces[i]; - BMO_face_flag_disable(bm, f_iter, FACE_TAG); - BMO_face_flag_enable(bm, f_iter, FACE_ORIG); + BLI_array_clear(faces); + /* Forces a new allocation. */ + faces = NULL; } - BLI_array_append(faces, NULL); - BLI_array_append(regions, faces); + BMW_end(®walker); } /* track how many faces we should end up with */ int totface_target = bm->totface; for (i = 0; i < BLI_array_len(regions); i++) { - BMFace *f_new; - int tot = 0; - - faces = regions[i]; - if (!faces[0]) { - BMO_error_raise(bm, op, "Could not find boundary of dissolve region"); - goto cleanup; - } - - while (faces[tot]) { - tot++; - } + region = ®ions[i]; - f_new = BM_faces_join(bm, faces, tot, true); + const int faces_len = region->faces_len; + faces = region->faces; - if (f_new) { - /* maintain active face */ + BMFace *f_new = BM_faces_join(bm, faces, faces_len, true); + if (f_new != NULL) { + /* Maintain the active face. */ if (act_face && bm->act_face == NULL) { bm->act_face = f_new; } - totface_target -= tot - 1; + totface_target -= faces_len - 1; + + /* If making the new face failed (e.g. overlapping test) + * un-mark the original faces for deletion. */ + BMO_face_flag_disable(bm, f_new, FACE_ORIG); + BMO_face_flag_enable(bm, f_new, FACE_NEW); } else { - BMO_error_raise(bm, op, "Could not create merged face"); - goto cleanup; + /* NOTE: prior to 3.0 this raised an error: "Could not create merged face". + * Change behavior since it's not useful to fail entirely when a single face-group + * can't be merged into one face. Continue with other face groups instead. + * + * This could optionally do a partial merge, where some faces are joined. */ + + /* Prevent these faces from being removed. */ + for (i = 0; i < faces_len; i++) { + BMO_face_flag_disable(bm, faces[i], FACE_ORIG); + } } - - /* if making the new face failed (e.g. overlapping test) - * unmark the original faces for deletion */ - BMO_face_flag_disable(bm, f_new, FACE_ORIG); - BMO_face_flag_enable(bm, f_new, FACE_NEW); } /* Typically no faces need to be deleted */ @@ -241,18 +257,13 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } } - if (BMO_error_occurred(bm)) { - goto cleanup; - } + BLI_assert(!BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL)); BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW); -cleanup: /* free/cleanup */ for (i = 0; i < BLI_array_len(regions); i++) { - if (regions[i]) { - MEM_freeN(regions[i]); - } + MEM_freeN(regions[i].faces); } BLI_array_free(regions); diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index 53a2a3b2bba..7f70c452af3 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -52,7 +52,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false); BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); - BM_mesh_edgenet(bm, true, true); /* TODO, sides */ + BM_mesh_edgenet(bm, true, true); /* TODO: sides. */ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); @@ -79,7 +79,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op_attr); /* check if some faces couldn't be touched */ - if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) { + if (BMO_slot_buffer_len(op_attr.slots_out, "faces_fail.out")) { BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out"); } BMO_op_finish(bm, &op_attr); @@ -93,7 +93,7 @@ static BMEdge *edge_next(BMesh *bm, BMEdge *e) for (i = 0; i < 2; i++) { BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) { - if ((BMO_edge_flag_test(bm, e2, EDGE_MARK)) && + if (BMO_edge_flag_test(bm, e2, EDGE_MARK) && (BMO_edge_flag_test(bm, e2, EDGE_VIS) == false) && (e2 != e)) { return e2; } diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index ffdce943d9f..0cedc2324f2 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -459,7 +459,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } /* Allocate array to store possible vertices that will be dissolved. */ - int boundary_edges_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out"); + int boundary_edges_len = BMO_slot_map_len(dupeop.slots_out, "boundary_map.out"); /* We do not know the real number of boundary vertices. */ int boundary_verts_len_maybe = 2 * boundary_edges_len; dissolve_verts = MEM_mallocN(boundary_verts_len_maybe * sizeof(*dissolve_verts), __func__); diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c index e377fa6079b..5e8924c4a3b 100644 --- a/source/blender/bmesh/operators/bmo_fill_attribute.c +++ b/source/blender/bmesh/operators/bmo_fill_attribute.c @@ -161,7 +161,7 @@ void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op) /* now we can copy adjacent data */ face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data); - if (face_tot != BMO_slot_buffer_count(op->slots_in, "faces")) { + if (face_tot != BMO_slot_buffer_len(op->slots_in, "faces")) { /* any remaining tags will be skipped */ BMO_slot_buffer_from_enabled_hflag( bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG); diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c index 16f9922b21d..da4567d947b 100644 --- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c +++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c @@ -35,7 +35,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op) { /* first collect an array of unique from the edges */ - const int tote = BMO_slot_buffer_count(op->slots_in, "edges"); + const int tote = BMO_slot_buffer_len(op->slots_in, "edges"); const int totv = tote; /* these should be the same */ BMVert **verts = MEM_mallocN(sizeof(*verts) * totv, __func__); @@ -85,7 +85,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op) } if (ok) { - /* note: in the case of multiple loops, this over-allocs (which is fine) */ + /* NOTE: in the case of multiple loops, this over-allocs (which is fine). */ BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__); BMIter eiter; diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index 4ba7dbad736..6734cc60cad 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -619,6 +619,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) * extract two 'rail' loops from a single edge loop, see T72075. */ BMO_error_raise(bm, op, + BMO_ERROR_CANCEL, "Select two edge loops " "or a single closed edge loop from which two edge loops can be calculated"); goto cleanup; @@ -633,7 +634,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) v_b_last = ((LinkData *)BM_edgeloop_verts_get(estore_b)->last)->data; if (BM_edgeloop_is_closed(estore_a) || BM_edgeloop_is_closed(estore_b)) { - BMO_error_raise(bm, op, "Closed loops unsupported"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Closed loops unsupported"); goto cleanup; } @@ -644,20 +645,20 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, true); bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, true); - if ((BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first)) && - (BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last))) { + if (BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first) && + BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last)) { estore_rail_a = eloops_rail.first; estore_rail_b = eloops_rail.last; } else { BM_mesh_edgeloops_free(&eloops_rail); - if ((BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last)) && - (BM_mesh_edgeloops_find_path( - bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first))) { + if (BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last) && + BM_mesh_edgeloops_find_path( + bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first)) { estore_rail_a = eloops_rail.first; estore_rail_b = eloops_rail.last; BM_edgeloop_flip(bm, estore_b); @@ -671,7 +672,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, false); if (BLI_listbase_is_empty(&eloops_rail)) { - BMO_error_raise(bm, op, "Loops are not connected by wire/boundary edges"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Loops are not connected by wire/boundary edges"); goto cleanup; } @@ -679,7 +680,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) BLI_assert(v_a_last != v_b_last); if (BM_edgeloop_overlap_check(estore_rail_a, estore_rail_b)) { - BMO_error_raise(bm, op, "Connecting edge loops overlap"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Connecting edge loops overlap"); goto cleanup; } diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c index 5801db582e1..a24d81c5bdb 100644 --- a/source/blender/bmesh/operators/bmo_fill_holes.c +++ b/source/blender/bmesh/operators/bmo_fill_holes.c @@ -35,7 +35,7 @@ void bmo_holes_fill_exec(BMesh *bm, BMOperator *op) BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false); BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false); - BM_mesh_edgenet(bm, true, true); // TODO, sides + BM_mesh_edgenet(bm, true, true); // TODO: sides /* bad - remove faces after as a workaround */ if (sides != 0) { @@ -66,7 +66,7 @@ void bmo_holes_fill_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op_attr); /* check if some faces couldn't be touched */ - if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) { + if (BMO_slot_buffer_len(op_attr.slots_out, "faces_fail.out")) { BMOIter siter; BMFace *f; diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 956d55695d6..740815691cc 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -278,7 +278,7 @@ static void hull_remove_overlapping(BMesh *bm, } } - /* Note: can't change ghash while iterating, so mark + /* NOTE: can't change ghash while iterating, so mark * with 'skip' flag rather than deleting triangles */ if (BM_vert_in_face(t->v[1], f) && BM_vert_in_face(t->v[2], f) && f_on_hull) { t->skip = true; @@ -465,7 +465,7 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull, hull_verts[i] = input_verts[original_index]; } else { - BLI_assert(!"Unexpected new vertex in hull output"); + BLI_assert_msg(0, "Unexpected new vertex in hull output"); } } @@ -505,7 +505,7 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, BLI_mempool *hull_triang BLI_array_grow_items(fvi, len); plConvexHullGetFaceVertices(hull, i, fvi); - /* Note: here we throw away any NGons from Bullet and turn + /* NOTE: here we throw away any NGons from Bullet and turn * them into triangle fans. Would be nice to use these * directly, but will have to wait until HullTriangle goes * away (TODO) */ @@ -554,7 +554,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) /* Verify that at least three verts in the input */ if (!hull_num_input_verts_is_ok(op)) { - BMO_error_raise(bm, op, "Requires at least three vertices"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Requires at least three vertices"); return; } diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 39f8f41432a..4833290aa0b 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -822,7 +822,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) /* this could go in its own loop, * only use the 'es->l->f' so we don't store loops for faces which have no mixed selection * - * note: faces on the other side of the inset will be interpolated too since this is hard to + * NOTE: faces on the other side of the inset will be interpolated too since this is hard to * detect, just allow it even though it will cause some redundant interpolation */ if (use_interpolate) { BMIter viter; @@ -1016,8 +1016,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) if (use_even_boundary) { /** - * This case where only one edge attached to #v_split - * is used - ei - the face to inset is on a boundary. + * This case where only one edge attached to #v_split is used. + * i.e. the face to inset is on a boundary. * * <pre> * We want the inset to align flush with the diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index c3e96a9b08e..8b456bb0925 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -44,7 +44,7 @@ static float quad_calc_error(const float v1[3], { /* Gives a 'weight' to a pair of triangles that join an edge * to decide how good a join they would make. */ - /* Note: this is more complicated than it needs to be and should be cleaned up. */ + /* NOTE: this is more complicated than it needs to be and should be cleaned up. */ float error = 0.0f; /* Normal difference */ diff --git a/source/blender/bmesh/operators/bmo_offset_edgeloops.c b/source/blender/bmesh/operators/bmo_offset_edgeloops.c index 2c7e478b549..28f2c9a47aa 100644 --- a/source/blender/bmesh/operators/bmo_offset_edgeloops.c +++ b/source/blender/bmesh/operators/bmo_offset_edgeloops.c @@ -74,7 +74,7 @@ static BMFace *bm_face_split_walk_back(BMesh *bm, BMLoop *l_src, BMLoop **r_l) void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op) { - const int edges_num = BMO_slot_buffer_count(op->slots_in, "edges"); + const int edges_num = BMO_slot_buffer_len(op->slots_in, "edges"); BMVert **verts; STACK_DECLARE(verts); int i; @@ -221,7 +221,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op) } } - /* Note: instead of duplicate code in alternate direction, + /* NOTE: instead of duplicate code in alternate direction, * we can be sure to hit the other vertex, so the code above runs. */ #if 0 else if (BM_elem_index_get(l->prev->v) == -1) { diff --git a/source/blender/bmesh/operators/bmo_planar_faces.c b/source/blender/bmesh/operators/bmo_planar_faces.c index c8f9d9a38dd..53cfc379269 100644 --- a/source/blender/bmesh/operators/bmo_planar_faces.c +++ b/source/blender/bmesh/operators/bmo_planar_faces.c @@ -41,7 +41,7 @@ void bmo_planar_faces_exec(BMesh *bm, BMOperator *op) { const float fac = BMO_slot_float_get(op->slots_in, "factor"); const int iterations = BMO_slot_int_get(op->slots_in, "iterations"); - const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces"); + const int faces_num = BMO_slot_buffer_len(op->slots_in, "faces"); const float eps = 0.00001f; const float eps_sq = square_f(eps); diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index f47c8dfb405..8d5963cfb1c 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -788,7 +788,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) } /** - * Fills first available UVmap with grid-like UVs for all faces OpFlag-ged by given flag. + * Fills first available UV-map with grid-like UV's for all faces with `oflag` set. * * \param bm: The BMesh to operate on * \param x_segments: The x-resolution of the grid @@ -1131,7 +1131,7 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset) } /** - * Fills first available UVmap with spherical projected UVs for all faces OpFlag-ged by given flag. + * Fills first available UV-map with spherical projected UVs for all faces with `oflag` set. * * \param bm: The BMesh to operate on * \param oflag: The flag to check faces with. @@ -1344,7 +1344,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) } /** - * Fills first available UVmap with 2D projected UVs for all faces OpFlag-ged by given flag. + * Fills first available UV-map with 2D projected UVs for all faces with `oflag` set. * * \param bm: The BMesh to operate on. * \param mat: The transform matrix applied to the created circle. @@ -1536,7 +1536,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) } /** - * Fills first available UVmap with cylinder/cone-like UVs for all faces OpFlag-ged by given flag. + * Fills first available UV-map with cylinder/cone-like UVs for all faces with `oflag` set. * * \param bm: The BMesh to operate on. * \param mat: The transform matrix applied to the created cone/cylinder. @@ -1712,7 +1712,7 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) } /** - * Fills first available UVmap with cube-like UVs for all faces OpFlag-ged by given flag. + * Fills first available UV-map with cube-like UVs for all faces with `oflag` set. * * \note Expects tagged faces to be six quads. * \note Caller must order faces for correct alignment. diff --git a/source/blender/bmesh/operators/bmo_rotate_edges.c b/source/blender/bmesh/operators/bmo_rotate_edges.c index b684aa390cf..10dd9dcc9b7 100644 --- a/source/blender/bmesh/operators/bmo_rotate_edges.c +++ b/source/blender/bmesh/operators/bmo_rotate_edges.c @@ -191,7 +191,7 @@ static void bm_rotate_edges_shared( edges_len_rotate += 1; - /* Note: we could validate all edges which have not been rotated + /* NOTE: we could validate all edges which have not been rotated * (not just previously degenerate edges). * However there is no real need - * they can be left until they're popped off the queue. */ @@ -234,7 +234,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e; - const int edges_len = BMO_slot_buffer_count(op->slots_in, "edges"); + const int edges_len = BMO_slot_buffer_len(op->slots_in, "edges"); const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); const bool is_single = (edges_len == 1); short check_flag = is_single ? BM_EDGEROT_CHECK_EXISTS : diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index ae4fa65b55c..7311c94a0d8 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -79,7 +79,7 @@ typedef void (*subd_pattern_fill_fp)(BMesh *bm, const SubDParams *params); /* - * note: this is a pattern-based edge subdivider. + * NOTE: this is a pattern-based edge subdivider. * it tries to match a pattern to edge selections on faces, * then executes functions to cut them. */ @@ -138,7 +138,7 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace * multiple faces yet. that might require a convexity test to figure out which * face is "best" and who knows what for non-manifold conditions. * - * note: we allow adjacent here, since there's no chance this happens. + * NOTE: we allow adjacent here, since there's no chance this happens. */ f = BM_vert_pair_share_face_by_len(v_a, v_b, &l_a, &l_b, true); @@ -469,7 +469,7 @@ static void bm_subdivide_multicut( alter_co(v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp); } -/* note: the patterns are rotated as necessary to +/* NOTE: the patterns are rotated as necessary to * match the input geometry. they're based on the * pre-split state of the face */ diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index d9bfe96ddc4..6a80f360f59 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -83,8 +83,8 @@ static float bezier_handle_calc_length_v3(const float co_a[3], float fac = 1.333333f; float len; if (dot < 0.0f) { - /* scale down to 0.666 if we point directly at each other rough but ok */ - /* TODO, current blend from dot may not be optimal but its also a detail */ + /* Scale down to 0.666 if we point directly at each other rough but ok. */ + /* TODO: current blend from dot may not be optimal but its also a detail. */ const float t = 1.0f + dot; fac = (fac * t) + (0.75f * (1.0f - t)); } @@ -821,7 +821,7 @@ static void bm_edgering_pair_interpolate(BMesh *bm, */ static void bm_face_slice(BMesh *bm, BMLoop *l, const int cuts) { - /* TODO, interpolate edge data */ + /* TODO: interpolate edge data. */ BMLoop *l_new = l; int i; @@ -860,12 +860,12 @@ static bool bm_edgering_pair_order_is_flipped(BMesh *UNUSED(bm), /* step around any fan-faces on both sides */ do { v_iter_a_step = v_iter_a_step->next; - } while (v_iter_a_step && ((BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data)) || - (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data)))); + } while (v_iter_a_step && (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data) || + BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data))); do { v_iter_b_step = v_iter_b_step->next; - } while (v_iter_b_step && ((BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data)) || - (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data)))); + } while (v_iter_b_step && (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data) || + BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data))); v_iter_a_step = v_iter_a_step ? v_iter_a_step->prev : lb_a->last; v_iter_b_step = v_iter_b_step ? v_iter_b_step->prev : lb_b->last; @@ -1143,7 +1143,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) count = BM_mesh_edgeloops_find(bm, &eloops_rim, bm_edge_rim_test_cb, (void *)bm); if (count < 2) { - BMO_error_raise(bm, op, "No edge rings found"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "No edge rings found"); goto cleanup; } else if (count == 2) { @@ -1167,7 +1167,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) changed = true; } else { - BMO_error_raise(bm, op, "Edge-ring pair isn't connected"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Edge-ring pair isn't connected"); goto cleanup; } } @@ -1179,7 +1179,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) LoopPairStore **lpair_arr; if (eloop_pairs_gs == NULL) { - BMO_error_raise(bm, op, "Edge-rings are not connected"); + BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Edge-rings are not connected"); goto cleanup; } diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index f6d612f31eb..9fa74bb64c3 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -74,7 +74,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) uint nors_tot; bool calc_winding = false; - sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges")); + sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_len(op->slots_in, "edges")); BMO_slot_vec_get(op->slots_in, "normal", normal); diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index c056302ca0f..7d2b6b73455 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -393,7 +393,7 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op) BMIter iter; BMVert *v; BMEdge *e; - float(*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_count(op->slots_in, "verts"), + float(*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_len(op->slots_in, "verts"), __func__); float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist"); const float fac = BMO_slot_float_get(op->slots_in, "factor"); diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index 4ef165fe6c1..d5c5063f2cb 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -429,7 +429,7 @@ void BM_mesh_beautify_fill(BMesh *bm, GSet *e_state_set = edge_state_arr[i]; /* add the new state into the set so we don't move into this state again - * note: we could add the previous state too but this isn't essential) + * NOTE: we could add the previous state too but this isn't essential) * for avoiding eternal loops */ EdRotState *e_state = BLI_mempool_alloc(edge_state_pool); erot_state_current(e, e_state); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 65cceb8dcfd..1e8ef9737d3 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -321,7 +321,7 @@ typedef struct BevelParams { GHash *vert_hash; /** Records new faces: key BMFace*, value one of {VERT/EDGE/RECON}_POLY. */ GHash *face_hash; - /** Use for all allocs while bevel runs. Note: If we need to free we can switch to mempool. */ + /** Use for all allocs while bevel runs. NOTE: If we need to free we can switch to mempool. */ MemArena *mem_arena; /** Profile vertex location and spacings. */ ProfileSpacing pro_spacing; @@ -1225,7 +1225,7 @@ static void offset_meet_lines_percent_or_absolute(BevelParams *bp, float r_l2b[3]) { /* Get points the specified distance along each leg. - * Note: not all BevVerts and EdgeHalfs have been made yet, so we have + * NOTE: not all BevVerts and EdgeHalfs have been made yet, so we have * to find required edges by moving around faces and use fake EdgeHalfs for * some of the edges. If there aren't faces to move around, we have to give up. * The legs we need are: @@ -1676,7 +1676,7 @@ static void project_to_edge(const BMEdge *e, float otherco[3]; if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) { #ifdef BEVEL_ASSERT_PROJECT - BLI_assert(!"project meet failure"); + BLI_assert_msg(0, "project meet failure"); #endif copy_v3_v3(projco, e->v1->co); } @@ -3621,7 +3621,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle) } while (v && v != vstart); EIG_linear_solver_solve(solver); #ifdef DEBUG_ADJUST - /* Note: this print only works after solve, but by that time b has been cleared. */ + /* NOTE: this print only works after solve, but by that time b has been cleared. */ EIG_linear_solver_print_matrix(solver); printf("\nSolution:\n"); for (i = 0; i < np; i++) { @@ -3682,7 +3682,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle) static void adjust_offsets(BevelParams *bp, BMesh *bm) { /* Find and process chains and cycles of unvisited BoundVerts that have eon set. */ - /* Note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts. */ + /* NOTE: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts. */ BMIter iter; BMVert *bmv; BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) { @@ -6194,7 +6194,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT); bv->offset *= weight; } - /* Find center axis. Note: Don't use vert normal, can give unwanted results. */ + /* Find center axis. NOTE: Don't use vert normal, can give unwanted results. */ if (ELEM(bp->offset_type, BEVEL_AMT_WIDTH, BEVEL_AMT_DEPTH)) { float edge_dir[3]; EdgeHalf *e = bv->edges; @@ -6262,7 +6262,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) break; } default: { - BLI_assert(!"bad bevel offset kind"); + BLI_assert_msg(0, "bad bevel offset kind"); e->offset_l_spec = bp->offset; break; } @@ -6872,7 +6872,7 @@ static double find_superellipse_chord_endpoint(double x0, double dtarget, float double ymin = superellipse_co(xmin, r, rbig); double ymax = superellipse_co(xmax, r, rbig); - /* Note: using distance**2 (no sqrt needed) does not converge that well. */ + /* NOTE: using distance**2 (no sqrt needed) does not converge that well. */ double dmaxerr = sqrt(pow((xmax - x0), 2) + pow((ymax - y0), 2)) - dtarget; double dminerr = sqrt(pow((xmin - x0), 2) + pow((ymin - y0), 2)) - dtarget; @@ -7253,7 +7253,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb) return no_collide_offset; } float kb = eb->offset_l_spec; - EdgeHalf *ea = eb->next; /* Note: this is in direction b --> a. */ + EdgeHalf *ea = eb->next; /* NOTE: this is in direction b --> a. */ float ka = ea->offset_r_spec; BMVert *vb, *vc; if (eb->is_rev) { @@ -7282,7 +7282,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb) return no_collide_offset; } if (ebother != NULL) { - ec = ebother->prev; /* Note: this is in direction c --> d. */ + ec = ebother->prev; /* NOTE: this is in direction c --> d. */ vc = bvc->v; kc = ec->offset_l_spec; vd = ec->is_rev ? ec->e->v1 : ec->e->v2; diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index a1630d9d2ff..20b6903b239 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -285,7 +285,7 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, cost = (BLI_quadric_evaluate(q1, optimize_co) + BLI_quadric_evaluate(q2, optimize_co)); } - /* note, 'cost' shouldn't be negative but happens sometimes with small values. + /* NOTE: 'cost' shouldn't be negative but happens sometimes with small values. * this can cause faces that make up a flat surface to over-collapse, see T37121. */ cost = fabsf(cost); @@ -303,7 +303,7 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, const float e_weight = (vweights[BM_elem_index_get(e->v1)] + vweights[BM_elem_index_get(e->v2)]); cost = bm_decim_build_edge_cost_single__topology(e) - cost; - /* note, this is rather arbitrary max weight is 2 here, + /* NOTE: this is rather arbitrary max weight is 2 here, * allow for skipping edges 4x the length, based on weights */ if (e_weight) { cost *= 1.0f + (e_weight * vweight_factor); diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 036dae1b9bd..d8a586acee5 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -55,7 +55,7 @@ static float bm_vert_edge_face_angle(BMVert *v, #define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE) const float angle = BM_vert_calc_edge_angle(v); - /* note: could be either edge, it doesn't matter */ + /* NOTE: could be either edge, it doesn't matter. */ if (v->e && BM_edge_is_manifold(v->e)) { /* Checking delimited is important here, * otherwise the boundary between two materials for e.g. diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c index 51af4d24e52..242b269ed47 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.c +++ b/source/blender/bmesh/tools/bmesh_edgenet.c @@ -17,7 +17,7 @@ /** \file * \ingroup bmesh * - * Edgenet Fill. + * Edge-net Fill. */ #include <limits.h> diff --git a/source/blender/bmesh/tools/bmesh_intersect_edges.c b/source/blender/bmesh/tools/bmesh_intersect_edges.c index 1e9adea2615..eb56075e136 100644 --- a/source/blender/bmesh/tools/bmesh_intersect_edges.c +++ b/source/blender/bmesh/tools/bmesh_intersect_edges.c @@ -938,7 +938,7 @@ bool BM_mesh_intersect_edges( } if (va_dest == v_other_dest) { - /* Edge/Edgenet to vertex - we can't split the face. */ + /* Edge/Edge-net to vertex - we can't split the face. */ break; } if (edgenet_len == 0 && BM_edge_exists(va_dest, v_other_dest)) { diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c index cb75f47acf3..ea1e7eb1e43 100644 --- a/source/blender/bmesh/tools/bmesh_path.c +++ b/source/blender/bmesh/tools/bmesh_path.c @@ -142,7 +142,7 @@ LinkNode *BM_mesh_calc_path_vert(BMesh *bm, BMVert **verts_prev; int i, totvert; - /* Note, would pass #BM_EDGE except we are looping over all faces anyway. */ + /* NOTE: would pass #BM_EDGE except we are looping over all faces anyway. */ // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { @@ -322,7 +322,7 @@ LinkNode *BM_mesh_calc_path_edge(BMesh *bm, BMEdge **edges_prev; int i, totedge; - /* Note, would pass #BM_EDGE except we are looping over all edges anyway. */ + /* NOTE: would pass #BM_EDGE except we are looping over all edges anyway. */ BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) { @@ -523,7 +523,7 @@ LinkNode *BM_mesh_calc_path_face(BMesh *bm, /* Start measuring face path at the face edges, ignoring their centers. */ const void *const f_endpoints[2] = {f_src, f_dst}; - /* Note, would pass #BM_EDGE except we are looping over all faces anyway. */ + /* NOTE: would pass #BM_EDGE except we are looping over all faces anyway. */ // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { diff --git a/source/blender/bmesh/tools/bmesh_path_uv.c b/source/blender/bmesh/tools/bmesh_path_uv.c index 57a70645187..30b109d4731 100644 --- a/source/blender/bmesh/tools/bmesh_path_uv.c +++ b/source/blender/bmesh/tools/bmesh_path_uv.c @@ -139,7 +139,7 @@ struct LinkNode *BM_mesh_calc_path_uv_vert(BMesh *bm, int i = 0, totloop; BMFace *f; - /* Note, would pass BM_EDGE except we are looping over all faces anyway. */ + /* NOTE: would pass BM_EDGE except we are looping over all faces anyway. */ // BM_mesh_elem_index_ensure(bm, BM_LOOP); // NOT NEEDED FOR FACETAG BM_ITER_MESH (f, &viter, bm, BM_FACES_OF_MESH) { @@ -377,7 +377,7 @@ struct LinkNode *BM_mesh_calc_path_uv_face(BMesh *bm, /* Start measuring face path at the face edges, ignoring their centers. */ const void *const f_endpoints[2] = {f_src, f_dst}; - /* Note, would pass BM_EDGE except we are looping over all faces anyway. */ + /* NOTE: would pass BM_EDGE except we are looping over all faces anyway. */ // BM_mesh_elem_index_ensure(bm, BM_LOOP); // NOT NEEDED FOR FACETAG { diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index c538d5b17cd..4ae5bfb7fb2 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -1053,7 +1053,7 @@ static BMEdge *bm_face_region_pivot_edge_find(BMFace **faces_region, uint verts_region_len, uint *r_depth) { - /* note, keep deterministic where possible (geometry order independent) + /* NOTE: keep deterministic where possible (geometry order independent) * this function assumed all visit faces & edges are tagged */ BLI_LINKSTACK_DECLARE(vert_queue_prev, BMVert *); diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c index de2deee2929..af4a4424103 100644 --- a/source/blender/bmesh/tools/bmesh_wireframe.c +++ b/source/blender/bmesh/tools/bmesh_wireframe.c @@ -77,7 +77,7 @@ static void bm_vert_boundary_tangent( } if (e_a && e_b) { - /* note, with an incorrectly flushed selection this can crash */ + /* NOTE: with an incorrectly flushed selection this can crash. */ l_a = bm_edge_tag_faceloop(e_a); l_b = bm_edge_tag_faceloop(e_b); diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index ac59d832013..20b56ceb55f 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -59,6 +59,8 @@ set(SRC intern/COM_ChunkOrderHotspot.h intern/COM_CompositorContext.cc intern/COM_CompositorContext.h + intern/COM_ConstantFolder.cc + intern/COM_ConstantFolder.h intern/COM_Converter.cc intern/COM_Converter.h intern/COM_Debug.cc @@ -66,6 +68,7 @@ set(SRC intern/COM_Device.cc intern/COM_Device.h intern/COM_Enums.cc + intern/COM_Enums.h intern/COM_ExecutionGroup.cc intern/COM_ExecutionGroup.h intern/COM_ExecutionModel.cc @@ -82,6 +85,8 @@ set(SRC intern/COM_MetaData.h intern/COM_MultiThreadedOperation.cc intern/COM_MultiThreadedOperation.h + intern/COM_MultiThreadedRowOperation.cc + intern/COM_MultiThreadedRowOperation.h intern/COM_Node.cc intern/COM_Node.h intern/COM_NodeConverter.cc @@ -442,6 +447,8 @@ set(SRC operations/COM_BrightnessOperation.h operations/COM_ColorCorrectionOperation.cc operations/COM_ColorCorrectionOperation.h + operations/COM_ConstantOperation.cc + operations/COM_ConstantOperation.h operations/COM_GammaOperation.cc operations/COM_GammaOperation.h operations/COM_MixOperation.cc diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h index 857cbf0beee..9f8e6f10215 100644 --- a/source/blender/compositor/COM_defines.h +++ b/source/blender/compositor/COM_defines.h @@ -60,9 +60,12 @@ constexpr int COM_data_type_num_channels(const DataType datatype) } constexpr int COM_DATA_TYPE_VALUE_CHANNELS = COM_data_type_num_channels(DataType::Value); +constexpr int COM_DATA_TYPE_VECTOR_CHANNELS = COM_data_type_num_channels(DataType::Vector); constexpr int COM_DATA_TYPE_COLOR_CHANNELS = COM_data_type_num_channels(DataType::Color); +constexpr float COM_VECTOR_ZERO[3] = {0.0f, 0.0f, 0.0f}; constexpr float COM_VALUE_ZERO[1] = {0.0f}; +constexpr float COM_VALUE_ONE[1] = {1.0f}; /** * Utility to get data type for given number of channels. diff --git a/source/blender/compositor/intern/COM_BufferOperation.cc b/source/blender/compositor/intern/COM_BufferOperation.cc index 8464d01801f..90c97f2a9c7 100644 --- a/source/blender/compositor/intern/COM_BufferOperation.cc +++ b/source/blender/compositor/intern/COM_BufferOperation.cc @@ -23,6 +23,7 @@ namespace blender::compositor { BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type) { buffer_ = buffer; + inflated_buffer_ = nullptr; /* TODO: Implement a MemoryBuffer get_size() method returning a Size2d type. Shorten following * code to: set_resolution(buffer.get_size()) */ unsigned int resolution[2]; @@ -30,11 +31,30 @@ BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type) resolution[1] = buffer->getHeight(); setResolution(resolution); addOutputSocket(data_type); + flags.is_constant_operation = buffer_->is_a_single_elem(); +} + +const float *BufferOperation::get_constant_elem() +{ + BLI_assert(buffer_->is_a_single_elem()); + return buffer_->getBuffer(); } void *BufferOperation::initializeTileData(rcti * /*rect*/) { - return buffer_; + if (buffer_->is_a_single_elem() == false) { + return buffer_; + } + + if (!inflated_buffer_) { + inflated_buffer_ = buffer_->inflate(); + } + return inflated_buffer_; +} + +void BufferOperation::deinitExecution() +{ + delete inflated_buffer_; } void BufferOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) diff --git a/source/blender/compositor/intern/COM_BufferOperation.h b/source/blender/compositor/intern/COM_BufferOperation.h index f87cd4db94e..705264c37b7 100644 --- a/source/blender/compositor/intern/COM_BufferOperation.h +++ b/source/blender/compositor/intern/COM_BufferOperation.h @@ -18,18 +18,21 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_ConstantOperation.h" namespace blender::compositor { -class BufferOperation : public NodeOperation { +class BufferOperation : public ConstantOperation { private: MemoryBuffer *buffer_; + MemoryBuffer *inflated_buffer_; public: BufferOperation(MemoryBuffer *buffer, DataType data_type); + const float *get_constant_elem() override; void *initializeTileData(rcti *rect) override; + void deinitExecution() override; void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]) override; }; diff --git a/source/blender/compositor/intern/COM_CompositorContext.cc b/source/blender/compositor/intern/COM_CompositorContext.cc index 61e299c045e..a93820b66dc 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.cc +++ b/source/blender/compositor/intern/COM_CompositorContext.cc @@ -53,7 +53,7 @@ eExecutionModel CompositorContext::get_execution_model() const case 0: return eExecutionModel::Tiled; default: - BLI_assert(!"Invalid execution mode"); + BLI_assert_msg(0, "Invalid execution mode"); } } return eExecutionModel::Tiled; diff --git a/source/blender/compositor/intern/COM_ConstantFolder.cc b/source/blender/compositor/intern/COM_ConstantFolder.cc new file mode 100644 index 00000000000..f20324de342 --- /dev/null +++ b/source/blender/compositor/intern/COM_ConstantFolder.cc @@ -0,0 +1,191 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#include "BLI_rect.h" + +#include "COM_ConstantFolder.h" +#include "COM_ConstantOperation.h" +#include "COM_SetColorOperation.h" +#include "COM_SetValueOperation.h" +#include "COM_SetVectorOperation.h" +#include "COM_WorkScheduler.h" + +namespace blender::compositor { + +using Link = NodeOperationBuilder::Link; + +/** + * \param operations_builder: Contains all operations to fold. + * \param exec_system: Execution system. + */ +ConstantFolder::ConstantFolder(NodeOperationBuilder &operations_builder) + : operations_builder_(operations_builder) +{ + BLI_rcti_init(&max_area_, INT_MIN, INT_MAX, INT_MIN, INT_MAX); + BLI_rcti_init(&first_elem_area_, 0, 1, 0, 1); +} + +static bool is_constant_foldable(NodeOperation *operation) +{ + if (operation->get_flags().can_be_constant && !operation->get_flags().is_constant_operation) { + for (int i = 0; i < operation->getNumberOfInputSockets(); i++) { + if (!operation->get_input_operation(i)->get_flags().is_constant_operation) { + return false; + } + } + return true; + } + return false; +} + +static Vector<NodeOperation *> find_constant_foldable_operations(Span<NodeOperation *> operations) +{ + Vector<NodeOperation *> foldable_ops; + for (NodeOperation *op : operations) { + if (is_constant_foldable(op)) { + foldable_ops.append(op); + } + } + return foldable_ops; +} + +static ConstantOperation *create_constant_operation(DataType data_type, const float *constant_elem) +{ + switch (data_type) { + case DataType::Color: { + SetColorOperation *color_op = new SetColorOperation(); + color_op->setChannels(constant_elem); + return color_op; + } + case DataType::Vector: { + SetVectorOperation *vector_op = new SetVectorOperation(); + vector_op->setVector(constant_elem); + return vector_op; + } + case DataType::Value: { + SetValueOperation *value_op = new SetValueOperation(); + value_op->setValue(*constant_elem); + return value_op; + } + default: { + BLI_assert_msg(0, "Non implemented data type"); + return nullptr; + } + } +} + +ConstantOperation *ConstantFolder::fold_operation(NodeOperation *operation) +{ + const DataType data_type = operation->getOutputSocket()->getDataType(); + MemoryBuffer fold_buf(data_type, first_elem_area_); + Vector<MemoryBuffer *> input_bufs = get_constant_input_buffers(operation); + operation->render(&fold_buf, {first_elem_area_}, input_bufs); + + MemoryBuffer *constant_buf = create_constant_buffer(data_type); + constant_buf->copy_from(&fold_buf, first_elem_area_); + ConstantOperation *constant_op = create_constant_operation(data_type, constant_buf->getBuffer()); + operations_builder_.replace_operation_with_constant(operation, constant_op); + constant_buffers_.add_new(constant_op, constant_buf); + return constant_op; +} + +MemoryBuffer *ConstantFolder::create_constant_buffer(const DataType data_type) +{ + /* Create a single elem buffer with maximum area possible so readers can read any coordinate + * returning always same element. */ + return new MemoryBuffer(data_type, max_area_, true); +} + +Vector<MemoryBuffer *> ConstantFolder::get_constant_input_buffers(NodeOperation *operation) +{ + const int num_inputs = operation->getNumberOfInputSockets(); + Vector<MemoryBuffer *> inputs_bufs(num_inputs); + for (int i = 0; i < num_inputs; i++) { + BLI_assert(operation->get_input_operation(i)->get_flags().is_constant_operation); + ConstantOperation *constant_op = static_cast<ConstantOperation *>( + operation->get_input_operation(i)); + MemoryBuffer *constant_buf = constant_buffers_.lookup_or_add_cb(constant_op, [=] { + MemoryBuffer *buf = create_constant_buffer(constant_op->getOutputSocket()->getDataType()); + constant_op->render(buf, {first_elem_area_}, {}); + return buf; + }); + inputs_bufs[i] = constant_buf; + } + return inputs_bufs; +} + +/** Returns constant operations resulted from folded operations. */ +Vector<ConstantOperation *> ConstantFolder::try_fold_operations(Span<NodeOperation *> operations) +{ + Vector<NodeOperation *> foldable_ops = find_constant_foldable_operations(operations); + if (foldable_ops.size() == 0) { + return Vector<ConstantOperation *>(); + } + + Vector<ConstantOperation *> new_folds; + for (NodeOperation *op : foldable_ops) { + ConstantOperation *constant_op = fold_operation(op); + new_folds.append(constant_op); + } + return new_folds; +} + +/** + * Evaluate operations with constant elements into primitive constant operations. + */ +int ConstantFolder::fold_operations() +{ + WorkScheduler::start(operations_builder_.context()); + Vector<ConstantOperation *> last_folds = try_fold_operations( + operations_builder_.get_operations()); + int folds_count = last_folds.size(); + while (last_folds.size() > 0) { + Vector<NodeOperation *> ops_to_fold; + for (ConstantOperation *fold : last_folds) { + get_operation_output_operations(fold, ops_to_fold); + } + last_folds = try_fold_operations(ops_to_fold); + folds_count += last_folds.size(); + } + WorkScheduler::stop(); + + delete_constant_buffers(); + + return folds_count; +} + +void ConstantFolder::delete_constant_buffers() +{ + for (MemoryBuffer *buf : constant_buffers_.values()) { + delete buf; + } + constant_buffers_.clear(); +} + +void ConstantFolder::get_operation_output_operations(NodeOperation *operation, + Vector<NodeOperation *> &r_outputs) +{ + const Vector<Link> &links = operations_builder_.get_links(); + for (const Link &link : links) { + if (&link.from()->getOperation() == operation) { + r_outputs.append(&link.to()->getOperation()); + } + } +} + +} // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_ConstantFolder.h b/source/blender/compositor/intern/COM_ConstantFolder.h new file mode 100644 index 00000000000..2432e859a5a --- /dev/null +++ b/source/blender/compositor/intern/COM_ConstantFolder.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#pragma once + +#include "BLI_map.hh" +#include "BLI_set.hh" +#include "BLI_vector.hh" + +#include "COM_NodeOperationBuilder.h" +#include "COM_defines.h" + +namespace blender::compositor { + +class NodeOperation; +class ConstantOperation; +class MemoryBuffer; + +/** + * Evaluates all operations with constant elements into primitive constant operations + * (Value/Vector/Color). + */ +class ConstantFolder { + private: + NodeOperationBuilder &operations_builder_; + + /** Constant operations buffers. */ + Map<ConstantOperation *, MemoryBuffer *> constant_buffers_; + + rcti max_area_; + rcti first_elem_area_; + + public: + ConstantFolder(NodeOperationBuilder &operations_builder); + int fold_operations(); + + private: + Vector<ConstantOperation *> try_fold_operations(Span<NodeOperation *> operations); + ConstantOperation *fold_operation(NodeOperation *operation); + + MemoryBuffer *create_constant_buffer(DataType data_type); + Vector<MemoryBuffer *> get_constant_input_buffers(NodeOperation *operation); + void delete_constant_buffers(); + + void get_operation_output_operations(NodeOperation *operation, + Vector<NodeOperation *> &r_outputs); +}; + +} // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_Converter.cc b/source/blender/compositor/intern/COM_Converter.cc index af593b2e1b5..18973bb5a00 100644 --- a/source/blender/compositor/intern/COM_Converter.cc +++ b/source/blender/compositor/intern/COM_Converter.cc @@ -460,6 +460,9 @@ void COM_convert_resolution(NodeOperationBuilder &builder, NodeOperationOutput *fromSocket, NodeOperationInput *toSocket) { + /* Data type conversions are executed before resolutions to ensure convert operations have + * resolution. This method have to ensure same datatypes are linked for new operations. */ + BLI_assert(fromSocket->getDataType() == toSocket->getDataType()); ResizeMode mode = toSocket->getResizeMode(); NodeOperation *toOperation = &toSocket->getOperation(); @@ -515,7 +518,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder, NodeOperation *first = nullptr; ScaleOperation *scaleOperation = nullptr; if (doScale) { - scaleOperation = new ScaleOperation(); + scaleOperation = new ScaleOperation(fromSocket->getDataType()); scaleOperation->getInputSocket(1)->setResizeMode(ResizeMode::None); scaleOperation->getInputSocket(2)->setResizeMode(ResizeMode::None); first = scaleOperation; @@ -535,7 +538,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder, builder.addOperation(scaleOperation); } - TranslateOperation *translateOperation = new TranslateOperation(); + TranslateOperation *translateOperation = new TranslateOperation(toSocket->getDataType()); translateOperation->getInputSocket(1)->setResizeMode(ResizeMode::None); translateOperation->getInputSocket(2)->setResizeMode(ResizeMode::None); if (!first) { diff --git a/source/blender/compositor/intern/COM_Debug.cc b/source/blender/compositor/intern/COM_Debug.cc index 4cf7e09a7d8..abef4517b3e 100644 --- a/source/blender/compositor/intern/COM_Debug.cc +++ b/source/blender/compositor/intern/COM_Debug.cc @@ -37,6 +37,7 @@ extern "C" { #include "COM_Node.h" #include "COM_ReadBufferOperation.h" +#include "COM_SetValueOperation.h" #include "COM_ViewerOperation.h" #include "COM_WriteBufferOperation.h" @@ -49,6 +50,15 @@ std::string DebugInfo::m_current_node_name; std::string DebugInfo::m_current_op_name; DebugInfo::GroupStateMap DebugInfo::m_group_states; +static std::string operation_class_name(NodeOperation *op) +{ + std::string full_name = typeid(*op).name(); + /* Remove name-spaces. */ + size_t pos = full_name.find_last_of(':'); + BLI_assert(pos != std::string::npos); + return full_name.substr(pos + 1); +} + std::string DebugInfo::node_name(const Node *node) { NodeNameMap::const_iterator it = m_node_names.find(node); @@ -135,15 +145,23 @@ int DebugInfo::graphviz_operation(const ExecutionSystem *system, len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|"); } + if (COM_GRAPHVIZ_SHOW_NODE_NAME) { + std::string op_node_name = operation->get_name(); + if (!op_node_name.empty()) { + len += snprintf( + str + len, maxlen > len ? maxlen - len : 0, "%s\\n", (op_node_name + " Node").c_str()); + } + } + len += snprintf(str + len, maxlen > len ? maxlen - len : 0, - "%s\\n(%s)", - m_op_names[operation].c_str(), - typeid(*operation).name()); + "%s\\n", + operation_class_name(operation).c_str()); len += snprintf(str + len, maxlen > len ? maxlen - len : 0, - " (%u,%u)", + "#%d (%u,%u)", + operation->get_id(), operation->getWidth(), operation->getHeight()); @@ -159,7 +177,13 @@ int DebugInfo::graphviz_operation(const ExecutionSystem *system, len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<OUT_%p>", socket); switch (socket->getDataType()) { case DataType::Value: - len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value"); + if (typeid(*operation) == typeid(SetValueOperation)) { + const float value = ((SetValueOperation *)operation)->getValue(); + len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value\\n%12.4g", value); + } + else { + len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value"); + } break; case DataType::Vector: len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector"); @@ -401,7 +425,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma return (len < maxlen); } -void DebugInfo::graphviz(const ExecutionSystem *system) +void DebugInfo::graphviz(const ExecutionSystem *system, StringRefNull name) { if (!COM_EXPORT_GRAPHVIZ) { return; @@ -411,7 +435,12 @@ void DebugInfo::graphviz(const ExecutionSystem *system) char basename[FILE_MAX]; char filename[FILE_MAX]; - BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index); + if (name.is_empty()) { + BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index); + } + else { + BLI_strncpy(basename, (name + ".dot").c_str(), sizeof(basename)); + } BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), basename); m_file_index++; diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h index 0de3a5e39dc..53461e13f48 100644 --- a/source/blender/compositor/intern/COM_Debug.h +++ b/source/blender/compositor/intern/COM_Debug.h @@ -28,6 +28,8 @@ namespace blender::compositor { static constexpr bool COM_EXPORT_GRAPHVIZ = false; +static constexpr bool COM_GRAPHVIZ_SHOW_NODE_NAME = false; + class Node; class ExecutionSystem; class ExecutionGroup; @@ -116,7 +118,7 @@ class DebugInfo { } }; - static void graphviz(const ExecutionSystem *system); + static void graphviz(const ExecutionSystem *system, StringRefNull name = ""); protected: static int graphviz_operation(const ExecutionSystem *system, diff --git a/source/blender/compositor/intern/COM_ExecutionModel.cc b/source/blender/compositor/intern/COM_ExecutionModel.cc index 4d7f62e091b..b75b277e92c 100644 --- a/source/blender/compositor/intern/COM_ExecutionModel.cc +++ b/source/blender/compositor/intern/COM_ExecutionModel.cc @@ -39,10 +39,4 @@ ExecutionModel::ExecutionModel(CompositorContext &context, Span<NodeOperation *> border_.render_border = &rd->border; } -bool ExecutionModel::is_breaked() const -{ - const bNodeTree *btree = context_.getbNodeTree(); - return btree->test_break(btree->tbh); -} - } // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_ExecutionModel.h b/source/blender/compositor/intern/COM_ExecutionModel.h index 9e8466b9282..452861ae4be 100644 --- a/source/blender/compositor/intern/COM_ExecutionModel.h +++ b/source/blender/compositor/intern/COM_ExecutionModel.h @@ -67,15 +67,6 @@ class ExecutionModel { virtual void execute(ExecutionSystem &exec_system) = 0; - virtual void execute_work(const rcti &UNUSED(work_rect), - std::function<void(const rcti &split_rect)> UNUSED(work_func)) - { - BLI_assert(!"Method not supported by current execution model"); - } - - protected: - bool is_breaked() const; - #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:BaseExecutionModel") #endif diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cc b/source/blender/compositor/intern/COM_ExecutionSystem.cc index a12ec774032..60caf22be1b 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cc +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cc @@ -63,8 +63,11 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, this->m_context.setViewSettings(viewSettings); this->m_context.setDisplaySettings(displaySettings); + BLI_mutex_init(&work_mutex_); + BLI_condition_init(&work_finished_cond_); + { - NodeOperationBuilder builder(&m_context, editingtree); + NodeOperationBuilder builder(&m_context, editingtree, this); builder.convertToOperations(this); } @@ -76,13 +79,16 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, execution_model_ = new FullFrameExecutionModel(m_context, active_buffers_, m_operations); break; default: - BLI_assert(!"Non implemented execution model"); + BLI_assert_msg(0, "Non implemented execution model"); break; } } ExecutionSystem::~ExecutionSystem() { + BLI_condition_end(&work_finished_cond_); + BLI_mutex_end(&work_mutex_); + delete execution_model_; for (NodeOperation *operation : m_operations) { @@ -109,10 +115,74 @@ void ExecutionSystem::execute() execution_model_->execute(*this); } +/** + * Multi-threadedly execute given work function passing work_rect splits as argument. + */ void ExecutionSystem::execute_work(const rcti &work_rect, std::function<void(const rcti &split_rect)> work_func) { - execution_model_->execute_work(work_rect, work_func); + if (is_breaked()) { + return; + } + + /* Split work vertically to maximize continuous memory. */ + const int work_height = BLI_rcti_size_y(&work_rect); + const int num_sub_works = MIN2(WorkScheduler::get_num_cpu_threads(), work_height); + const int split_height = num_sub_works == 0 ? 0 : work_height / num_sub_works; + int remaining_height = work_height - split_height * num_sub_works; + + Vector<WorkPackage> sub_works(num_sub_works); + int sub_work_y = work_rect.ymin; + int num_sub_works_finished = 0; + for (int i = 0; i < num_sub_works; i++) { + int sub_work_height = split_height; + + /* Distribute remaining height between sub-works. */ + if (remaining_height > 0) { + sub_work_height++; + remaining_height--; + } + + WorkPackage &sub_work = sub_works[i]; + sub_work.type = eWorkPackageType::CustomFunction; + sub_work.execute_fn = [=, &work_func, &work_rect]() { + if (is_breaked()) { + return; + } + rcti split_rect; + BLI_rcti_init( + &split_rect, work_rect.xmin, work_rect.xmax, sub_work_y, sub_work_y + sub_work_height); + work_func(split_rect); + }; + sub_work.executed_fn = [&]() { + BLI_mutex_lock(&work_mutex_); + num_sub_works_finished++; + if (num_sub_works_finished == num_sub_works) { + BLI_condition_notify_one(&work_finished_cond_); + } + BLI_mutex_unlock(&work_mutex_); + }; + WorkScheduler::schedule(&sub_work); + sub_work_y += sub_work_height; + } + BLI_assert(sub_work_y == work_rect.ymax); + + WorkScheduler::finish(); + + /* Ensure all sub-works finished. + * TODO: This a workaround for WorkScheduler::finish() not waiting all works on queue threading + * model. Sync code should be removed once it's fixed. */ + BLI_mutex_lock(&work_mutex_); + if (num_sub_works_finished < num_sub_works) { + BLI_condition_wait(&work_finished_cond_, &work_mutex_); + } + BLI_mutex_unlock(&work_mutex_); +} + +bool ExecutionSystem::is_breaked() const +{ + const bNodeTree *btree = m_context.getbNodeTree(); + return btree->test_break(btree->tbh); } } // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h index e106209651c..38c3432a8ec 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.h +++ b/source/blender/compositor/intern/COM_ExecutionSystem.h @@ -150,7 +150,9 @@ class ExecutionSystem { */ ExecutionModel *execution_model_; - private: // methods + ThreadMutex work_mutex_; + ThreadCondition work_finished_cond_; + public: /** * \brief Create a new ExecutionSystem and initialize it with the @@ -199,6 +201,8 @@ class ExecutionSystem { void execute_work(const rcti &work_rect, std::function<void(const rcti &split_rect)> work_func); + bool is_breaked() const; + private: /* allow the DebugInfo class to look at internals */ friend class DebugInfo; diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc index 21075bb7255..3b0a9172871 100644 --- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc +++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc @@ -35,24 +35,13 @@ FullFrameExecutionModel::FullFrameExecutionModel(CompositorContext &context, Span<NodeOperation *> operations) : ExecutionModel(context, operations), active_buffers_(shared_buffers), - num_operations_finished_(0), - work_mutex_(), - work_finished_cond_() + num_operations_finished_(0) { priorities_.append(eCompositorPriority::High); if (!context.isFastCalculation()) { priorities_.append(eCompositorPriority::Medium); priorities_.append(eCompositorPriority::Low); } - - BLI_mutex_init(&work_mutex_); - BLI_condition_init(&work_finished_cond_); -} - -FullFrameExecutionModel::~FullFrameExecutionModel() -{ - BLI_condition_end(&work_finished_cond_); - BLI_mutex_end(&work_mutex_); } void FullFrameExecutionModel::execute(ExecutionSystem &exec_system) @@ -60,10 +49,10 @@ void FullFrameExecutionModel::execute(ExecutionSystem &exec_system) const bNodeTree *node_tree = this->context_.getbNodeTree(); node_tree->stats_draw(node_tree->sdh, TIP_("Compositing | Initializing execution")); - DebugInfo::graphviz(&exec_system); + DebugInfo::graphviz(&exec_system, "compositor_prior_rendering"); determine_areas_to_render_and_reads(); - render_operations(exec_system); + render_operations(); } void FullFrameExecutionModel::determine_areas_to_render_and_reads() @@ -101,20 +90,18 @@ MemoryBuffer *FullFrameExecutionModel::create_operation_buffer(NodeOperation *op BLI_rcti_init(&op_rect, 0, op->getWidth(), 0, op->getHeight()); const DataType data_type = op->getOutputSocket(0)->getDataType(); - /* TODO: We should check if the operation is constant instead of is_set_operation. Finding a way - * to know if an operation is constant has to be implemented yet. */ - const bool is_a_single_elem = op->get_flags().is_set_operation; + const bool is_a_single_elem = op->get_flags().is_constant_operation; return new MemoryBuffer(data_type, op_rect, is_a_single_elem); } -void FullFrameExecutionModel::render_operation(NodeOperation *op, ExecutionSystem &exec_system) +void FullFrameExecutionModel::render_operation(NodeOperation *op) { Vector<MemoryBuffer *> input_bufs = get_input_buffers(op); const bool has_outputs = op->getNumberOfOutputSockets() > 0; MemoryBuffer *op_buf = has_outputs ? create_operation_buffer(op) : nullptr; Span<rcti> areas = active_buffers_.get_areas_to_render(op); - op->render(op_buf, areas, input_bufs, exec_system); + op->render(op_buf, areas, input_bufs); active_buffers_.set_rendered_buffer(op, std::unique_ptr<MemoryBuffer>(op_buf)); operation_finished(op); @@ -123,7 +110,7 @@ void FullFrameExecutionModel::render_operation(NodeOperation *op, ExecutionSyste /** * Render output operations in order of priority. */ -void FullFrameExecutionModel::render_operations(ExecutionSystem &exec_system) +void FullFrameExecutionModel::render_operations() { const bool is_rendering = context_.isRendering(); @@ -131,8 +118,8 @@ void FullFrameExecutionModel::render_operations(ExecutionSystem &exec_system) for (eCompositorPriority priority : priorities_) { for (NodeOperation *op : operations_) { if (op->isOutputOperation(is_rendering) && op->getRenderPriority() == priority) { - render_output_dependencies(op, exec_system); - render_operation(op, exec_system); + render_output_dependencies(op); + render_operation(op); } } } @@ -166,14 +153,13 @@ static Vector<NodeOperation *> get_operation_dependencies(NodeOperation *operati return dependencies; } -void FullFrameExecutionModel::render_output_dependencies(NodeOperation *output_op, - ExecutionSystem &exec_system) +void FullFrameExecutionModel::render_output_dependencies(NodeOperation *output_op) { BLI_assert(output_op->isOutputOperation(context_.isRendering())); Vector<NodeOperation *> dependencies = get_operation_dependencies(output_op); for (NodeOperation *op : dependencies) { if (!active_buffers_.is_operation_rendered(op)) { - render_operation(op, exec_system); + render_operation(op); } } } @@ -266,70 +252,6 @@ void FullFrameExecutionModel::get_output_render_area(NodeOperation *output_op, r } } -/** - * Multi-threadedly execute given work function passing work_rect splits as argument. - */ -void FullFrameExecutionModel::execute_work(const rcti &work_rect, - std::function<void(const rcti &split_rect)> work_func) -{ - if (is_breaked()) { - return; - } - - /* Split work vertically to maximize continuous memory. */ - const int work_height = BLI_rcti_size_y(&work_rect); - const int num_sub_works = MIN2(WorkScheduler::get_num_cpu_threads(), work_height); - const int split_height = num_sub_works == 0 ? 0 : work_height / num_sub_works; - int remaining_height = work_height - split_height * num_sub_works; - - Vector<WorkPackage> sub_works(num_sub_works); - int sub_work_y = work_rect.ymin; - int num_sub_works_finished = 0; - for (int i = 0; i < num_sub_works; i++) { - int sub_work_height = split_height; - - /* Distribute remaining height between sub-works. */ - if (remaining_height > 0) { - sub_work_height++; - remaining_height--; - } - - WorkPackage &sub_work = sub_works[i]; - sub_work.type = eWorkPackageType::CustomFunction; - sub_work.execute_fn = [=, &work_func, &work_rect]() { - if (is_breaked()) { - return; - } - rcti split_rect; - BLI_rcti_init( - &split_rect, work_rect.xmin, work_rect.xmax, sub_work_y, sub_work_y + sub_work_height); - work_func(split_rect); - }; - sub_work.executed_fn = [&]() { - BLI_mutex_lock(&work_mutex_); - num_sub_works_finished++; - if (num_sub_works_finished == num_sub_works) { - BLI_condition_notify_one(&work_finished_cond_); - } - BLI_mutex_unlock(&work_mutex_); - }; - WorkScheduler::schedule(&sub_work); - sub_work_y += sub_work_height; - } - BLI_assert(sub_work_y == work_rect.ymax); - - WorkScheduler::finish(); - - /* Ensure all sub-works finished. - * TODO: This a workaround for WorkScheduler::finish() not waiting all works on queue threading - * model. Sync code should be removed once it's fixed. */ - BLI_mutex_lock(&work_mutex_); - if (num_sub_works_finished < num_sub_works) { - BLI_condition_wait(&work_finished_cond_, &work_mutex_); - } - BLI_mutex_unlock(&work_mutex_); -} - void FullFrameExecutionModel::operation_finished(NodeOperation *operation) { /* Report inputs reads so that buffers may be freed/reused. */ diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.h b/source/blender/compositor/intern/COM_FullFrameExecutionModel.h index e68ad93b407..f75d4f1afdc 100644 --- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.h +++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.h @@ -50,27 +50,20 @@ class FullFrameExecutionModel : public ExecutionModel { */ Vector<eCompositorPriority> priorities_; - ThreadMutex work_mutex_; - ThreadCondition work_finished_cond_; - public: FullFrameExecutionModel(CompositorContext &context, SharedOperationBuffers &shared_buffers, Span<NodeOperation *> operations); - ~FullFrameExecutionModel(); void execute(ExecutionSystem &exec_system) override; - void execute_work(const rcti &work_rect, - std::function<void(const rcti &split_rect)> work_func) override; - private: void determine_areas_to_render_and_reads(); - void render_operations(ExecutionSystem &exec_system); - void render_output_dependencies(NodeOperation *output_op, ExecutionSystem &exec_system); + void render_operations(); + void render_output_dependencies(NodeOperation *output_op); Vector<MemoryBuffer *> get_input_buffers(NodeOperation *op); MemoryBuffer *create_operation_buffer(NodeOperation *op); - void render_operation(NodeOperation *op, ExecutionSystem &exec_system); + void render_operation(NodeOperation *op); void operation_finished(NodeOperation *operation); diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc index 44d3f059374..c7bddddd0e6 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cc +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc @@ -129,6 +129,18 @@ void MemoryBuffer::clear() memset(m_buffer, 0, buffer_len() * m_num_channels * sizeof(float)); } +/** + * Converts a single elem buffer to a full size buffer (allocates memory for all + * elements in resolution). + */ +MemoryBuffer *MemoryBuffer::inflate() const +{ + BLI_assert(is_a_single_elem()); + MemoryBuffer *inflated = new MemoryBuffer(this->m_datatype, this->m_rect, false); + inflated->copy_from(this, this->m_rect); + return inflated; +} + float MemoryBuffer::get_max_value() const { float result = this->m_buffer[0]; diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index fdfd1c1c37b..4ad0872b0b7 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -247,6 +247,8 @@ class MemoryBuffer { return this->m_buffer; } + MemoryBuffer *inflate() const; + inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) { const int w = getWidth(); @@ -262,11 +264,14 @@ class MemoryBuffer { x = 0; } if (x >= w) { - x = w; + x = w - 1; } break; case MemoryBufferExtend::Repeat: - x = (x >= 0.0f ? (x % w) : (x % w) + w); + x %= w; + if (x < 0) { + x += w; + } break; } @@ -278,13 +283,19 @@ class MemoryBuffer { y = 0; } if (y >= h) { - y = h; + y = h - 1; } break; case MemoryBufferExtend::Repeat: - y = (y >= 0.0f ? (y % h) : (y % h) + h); + y %= h; + if (y < 0) { + y += h; + } break; } + + x = x + m_rect.xmin; + y = y + m_rect.ymin; } inline void wrap_pixel(float &x, @@ -305,11 +316,14 @@ class MemoryBuffer { x = 0.0f; } if (x >= w) { - x = w; + x = w - 1; } break; case MemoryBufferExtend::Repeat: x = fmodf(x, w); + if (x < 0.0f) { + x += w; + } break; } @@ -321,13 +335,19 @@ class MemoryBuffer { y = 0.0f; } if (y >= h) { - y = h; + y = h - 1; } break; case MemoryBufferExtend::Repeat: y = fmodf(y, h); + if (y < 0.0f) { + y += h; + } break; } + + x = x + m_rect.xmin; + y = y + m_rect.ymin; } inline void read(float *result, diff --git a/source/blender/compositor/intern/COM_MultiThreadedOperation.cc b/source/blender/compositor/intern/COM_MultiThreadedOperation.cc index e6e98d69b36..7ccf6f76d9f 100644 --- a/source/blender/compositor/intern/COM_MultiThreadedOperation.cc +++ b/source/blender/compositor/intern/COM_MultiThreadedOperation.cc @@ -12,12 +12,11 @@ MultiThreadedOperation::MultiThreadedOperation() void MultiThreadedOperation::update_memory_buffer(MemoryBuffer *output, const rcti &area, - Span<MemoryBuffer *> inputs, - ExecutionSystem &exec_system) + Span<MemoryBuffer *> inputs) { for (current_pass_ = 0; current_pass_ < num_passes_; current_pass_++) { update_memory_buffer_started(output, area, inputs); - exec_system.execute_work(area, [=](const rcti &split_rect) { + exec_system_->execute_work(area, [=](const rcti &split_rect) { update_memory_buffer_partial(output, split_rect, inputs); }); update_memory_buffer_finished(output, area, inputs); diff --git a/source/blender/compositor/intern/COM_MultiThreadedOperation.h b/source/blender/compositor/intern/COM_MultiThreadedOperation.h index ad09c4df089..a7e574ca745 100644 --- a/source/blender/compositor/intern/COM_MultiThreadedOperation.h +++ b/source/blender/compositor/intern/COM_MultiThreadedOperation.h @@ -64,8 +64,7 @@ class MultiThreadedOperation : public NodeOperation { private: void update_memory_buffer(MemoryBuffer *output, const rcti &area, - Span<MemoryBuffer *> inputs, - ExecutionSystem &exec_system) override; + Span<MemoryBuffer *> inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_MultiThreadedRowOperation.cc b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.cc new file mode 100644 index 00000000000..6bf318bb96b --- /dev/null +++ b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.cc @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#include "COM_MultiThreadedRowOperation.h" + +namespace blender::compositor { + +MultiThreadedRowOperation::PixelCursor::PixelCursor(const int num_inputs) + : out(nullptr), out_stride(0), row_end(nullptr), ins(num_inputs), in_strides(num_inputs) +{ +} + +void MultiThreadedRowOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + BLI_assert(output != nullptr); + const int width = BLI_rcti_size_x(&area); + PixelCursor p(inputs.size()); + p.out_stride = output->elem_stride; + for (int i = 0; i < p.in_strides.size(); i++) { + p.in_strides[i] = inputs[i]->elem_stride; + } + + for (int y = area.ymin; y < area.ymax; y++) { + p.out = output->get_elem(area.xmin, y); + for (int i = 0; i < p.ins.size(); i++) { + p.ins[i] = inputs[i]->get_elem(area.xmin, y); + } + p.row_end = p.out + width * p.out_stride; + update_memory_buffer_row(p); + } +} + +} // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_MultiThreadedRowOperation.h b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.h new file mode 100644 index 00000000000..3daa9eec474 --- /dev/null +++ b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.h @@ -0,0 +1,60 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#pragma once + +#include "COM_MultiThreadedOperation.h" + +namespace blender::compositor { + +/** + * Executes buffer updates per row. To be inherited only by operations with correlated coordinates + * between inputs and output. + */ +class MultiThreadedRowOperation : public MultiThreadedOperation { + protected: + struct PixelCursor { + float *out; + int out_stride; + const float *row_end; + Array<const float *> ins; + Array<int> in_strides; + + public: + PixelCursor(int num_inputs); + + void next() + { + BLI_assert(out < row_end); + out += out_stride; + for (int i = 0; i < ins.size(); i++) { + ins[i] += in_strides[i]; + } + } + }; + + protected: + virtual void update_memory_buffer_row(PixelCursor &p) = 0; + + private: + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) final; +}; + +} // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_NodeGraph.cc b/source/blender/compositor/intern/COM_NodeGraph.cc index fbe56dd4b5a..205fbcc0440 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.cc +++ b/source/blender/compositor/intern/COM_NodeGraph.cc @@ -174,7 +174,7 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink return; } - /* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies) + /* NOTE: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies) * The output then gets linked to each one of them. */ diff --git a/source/blender/compositor/intern/COM_NodeOperation.cc b/source/blender/compositor/intern/COM_NodeOperation.cc index b943ab6af7f..4e115cb3f2f 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.cc +++ b/source/blender/compositor/intern/COM_NodeOperation.cc @@ -218,7 +218,7 @@ void NodeOperation::get_area_of_interest(NodeOperation *input_op, return; } } - BLI_assert(!"input_op is not an input operation."); + BLI_assert_msg(0, "input_op is not an input operation."); } /** @@ -226,18 +226,16 @@ void NodeOperation::get_area_of_interest(NodeOperation *input_op, * \param output_buf: Buffer to write result to. * \param areas: Areas within this operation bounds to render. * \param inputs_bufs: Inputs operations buffers. - * \param exec_system: Execution system. */ void NodeOperation::render(MemoryBuffer *output_buf, Span<rcti> areas, - Span<MemoryBuffer *> inputs_bufs, - ExecutionSystem &exec_system) + Span<MemoryBuffer *> inputs_bufs) { if (get_flags().is_fullframe_operation) { - render_full_frame(output_buf, areas, inputs_bufs, exec_system); + render_full_frame(output_buf, areas, inputs_bufs); } else { - render_full_frame_fallback(output_buf, areas, inputs_bufs, exec_system); + render_full_frame_fallback(output_buf, areas, inputs_bufs); } } @@ -246,12 +244,11 @@ void NodeOperation::render(MemoryBuffer *output_buf, */ void NodeOperation::render_full_frame(MemoryBuffer *output_buf, Span<rcti> areas, - Span<MemoryBuffer *> inputs_bufs, - ExecutionSystem &exec_system) + Span<MemoryBuffer *> inputs_bufs) { initExecution(); for (const rcti &area : areas) { - update_memory_buffer(output_buf, area, inputs_bufs, exec_system); + update_memory_buffer(output_buf, area, inputs_bufs); } deinitExecution(); } @@ -261,8 +258,7 @@ void NodeOperation::render_full_frame(MemoryBuffer *output_buf, */ void NodeOperation::render_full_frame_fallback(MemoryBuffer *output_buf, Span<rcti> areas, - Span<MemoryBuffer *> inputs_bufs, - ExecutionSystem &exec_system) + Span<MemoryBuffer *> inputs_bufs) { Vector<NodeOperationOutput *> orig_input_links = replace_inputs_with_buffers(inputs_bufs); @@ -274,7 +270,7 @@ void NodeOperation::render_full_frame_fallback(MemoryBuffer *output_buf, } else { for (const rcti &rect : areas) { - exec_system.execute_work(rect, [=](const rcti &split_rect) { + exec_system_->execute_work(rect, [=](const rcti &split_rect) { rcti tile_rect = split_rect; if (is_output_operation) { executeRegion(&tile_rect, 0); @@ -328,6 +324,7 @@ Vector<NodeOperationOutput *> NodeOperation::replace_inputs_with_buffers( BufferOperation *buffer_op = new BufferOperation(inputs_bufs[i], input_socket->getDataType()); orig_links[i] = input_socket->getLink(); input_socket->setLink(buffer_op->getOutputSocket()); + buffer_op->initExecution(); } return orig_links; } @@ -340,6 +337,7 @@ void NodeOperation::remove_buffers_and_restore_original_inputs( NodeOperation *buffer_op = get_input_operation(i); BLI_assert(buffer_op != nullptr); BLI_assert(typeid(*buffer_op) == typeid(BufferOperation)); + buffer_op->deinitExecution(); NodeOperationInput *input_socket = getInputSocket(i); input_socket->setLink(original_inputs_links[i]); delete buffer_op; @@ -443,6 +441,12 @@ std::ostream &operator<<(std::ostream &os, const NodeOperationFlags &node_operat if (node_operation_flags.is_fullframe_operation) { os << "full_frame,"; } + if (node_operation_flags.is_constant_operation) { + os << "contant_operation,"; + } + if (node_operation_flags.can_be_constant) { + os << "can_be_constant,"; + } return os; } diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 5ae0aae67d5..fb9ec1e7a83 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -221,6 +221,7 @@ struct NodeOperationFlags { /** * Is this a set operation (value, color, vector). + * TODO: To be replaced by is_constant_operation flag once tiled implementation is removed. */ bool is_set_operation : 1; bool is_write_buffer_operation : 1; @@ -242,6 +243,17 @@ struct NodeOperationFlags { */ bool is_fullframe_operation : 1; + /** + * Whether operation is a primitive constant operation (Color/Vector/Value). + */ + bool is_constant_operation : 1; + + /** + * Whether operation have constant elements/pixels values when all its inputs are constant + * operations. + */ + bool can_be_constant : 1; + NodeOperationFlags() { complex = false; @@ -258,6 +270,8 @@ struct NodeOperationFlags { is_preview_operation = false; use_datatype_conversion = true; is_fullframe_operation = false; + is_constant_operation = false; + can_be_constant = false; } }; @@ -316,6 +330,8 @@ class NodeOperation { */ NodeOperationFlags flags; + ExecutionSystem *exec_system_; + public: virtual ~NodeOperation() { @@ -402,6 +418,12 @@ class NodeOperation { { this->m_btree = tree; } + + void set_execution_system(ExecutionSystem *system) + { + exec_system_ = system; + } + virtual void initExecution(); /** @@ -569,18 +591,14 @@ class NodeOperation { /** \name Full Frame Methods * \{ */ - void render(MemoryBuffer *output_buf, - Span<rcti> areas, - Span<MemoryBuffer *> inputs_bufs, - ExecutionSystem &exec_system); + void render(MemoryBuffer *output_buf, Span<rcti> areas, Span<MemoryBuffer *> inputs_bufs); /** * Executes operation updating output memory buffer. Single-threaded calls. */ virtual void update_memory_buffer(MemoryBuffer *UNUSED(output), const rcti &UNUSED(area), - Span<MemoryBuffer *> UNUSED(inputs), - ExecutionSystem &UNUSED(exec_system)) + Span<MemoryBuffer *> UNUSED(inputs)) { } @@ -678,13 +696,11 @@ class NodeOperation { void render_full_frame(MemoryBuffer *output_buf, Span<rcti> areas, - Span<MemoryBuffer *> inputs_bufs, - ExecutionSystem &exec_system); + Span<MemoryBuffer *> inputs_bufs); void render_full_frame_fallback(MemoryBuffer *output_buf, Span<rcti> areas, - Span<MemoryBuffer *> inputs, - ExecutionSystem &exec_system); + Span<MemoryBuffer *> inputs); void render_tile(MemoryBuffer *output_buf, rcti *tile_rect); Vector<NodeOperationOutput *> replace_inputs_with_buffers(Span<MemoryBuffer *> inputs_bufs); void remove_buffers_and_restore_original_inputs( diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cc b/source/blender/compositor/intern/COM_NodeOperationBuilder.cc index 1beb83bb477..10a91bbcd3e 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cc +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cc @@ -36,12 +36,15 @@ #include "COM_ViewerOperation.h" #include "COM_WriteBufferOperation.h" +#include "COM_ConstantFolder.h" #include "COM_NodeOperationBuilder.h" /* own include */ namespace blender::compositor { -NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree) - : m_context(context), m_current_node(nullptr), m_active_viewer(nullptr) +NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, + bNodeTree *b_nodetree, + ExecutionSystem *system) + : m_context(context), exec_system_(system), m_current_node(nullptr), m_active_viewer(nullptr) { m_graph.from_bNodeTree(*context, b_nodetree); } @@ -79,7 +82,7 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system) if (!op_from || op_to_list.is_empty()) { /* XXX allow this? error/debug message? */ // BLI_assert(false); - /* XXX note: this can happen with certain nodes (e.g. OutputFile) + /* XXX NOTE: this can happen with certain nodes (e.g. OutputFile) * which only generate operations in certain circumstances (rendering) * just let this pass silently for now ... */ @@ -97,6 +100,15 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system) add_datatype_conversions(); + if (m_context->get_execution_model() == eExecutionModel::FullFrame) { + /* Copy operations to system. Needed for graphviz. */ + system->set_operations(m_operations, {}); + + DebugInfo::graphviz(system, "compositor_prior_folding"); + ConstantFolder folder(*this); + folder.fold_operations(); + } + determineResolutions(); if (m_context->get_execution_model() == eExecutionModel::Tiled) { @@ -130,6 +142,29 @@ void NodeOperationBuilder::addOperation(NodeOperation *operation) operation->set_name(m_current_node->getbNode()->name); } operation->set_execution_model(m_context->get_execution_model()); + operation->set_execution_system(exec_system_); +} + +void NodeOperationBuilder::replace_operation_with_constant(NodeOperation *operation, + ConstantOperation *constant_operation) +{ + BLI_assert(constant_operation->getNumberOfInputSockets() == 0); + int i = 0; + while (i < m_links.size()) { + Link &link = m_links[i]; + if (&link.to()->getOperation() == operation) { + link.to()->setLink(nullptr); + m_links.remove(i); + continue; + } + + if (&link.from()->getOperation() == operation) { + link.to()->setLink(constant_operation->getOutputSocket()); + m_links[i] = Link(constant_operation->getOutputSocket(), link.to()); + } + i++; + } + addOperation(constant_operation); } void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket, @@ -138,7 +173,7 @@ void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket, BLI_assert(m_current_node); BLI_assert(node_socket->getNode() == m_current_node); - /* note: this maps operation sockets to node sockets. + /* NOTE: this maps operation sockets to node sockets. * for resolving links the map will be inverted first in convertToOperations, * to get a list of links for each node input socket. */ @@ -284,7 +319,7 @@ void NodeOperationBuilder::add_datatype_conversions() void NodeOperationBuilder::add_operation_input_constants() { - /* Note: unconnected inputs cached first to avoid modifying + /* NOTE: unconnected inputs cached first to avoid modifying * m_operations while iterating over it */ Vector<NodeOperationInput *> pending_inputs; @@ -537,7 +572,7 @@ void NodeOperationBuilder::add_output_buffers(NodeOperation *operation, void NodeOperationBuilder::add_complex_operation_buffers() { - /* note: complex ops and get cached here first, since adding operations + /* NOTE: complex ops and get cached here first, since adding operations * will invalidate iterators over the main m_operations */ Vector<NodeOperation *> complex_ops; diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.h b/source/blender/compositor/intern/COM_NodeOperationBuilder.h index b2fb822af25..1f76765c846 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.h +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.h @@ -41,6 +41,7 @@ class NodeOperationOutput; class PreviewOperation; class WriteBufferOperation; class ViewerOperation; +class ConstantOperation; class NodeOperationBuilder { public: @@ -67,6 +68,7 @@ class NodeOperationBuilder { private: const CompositorContext *m_context; NodeGraph m_graph; + ExecutionSystem *exec_system_; Vector<NodeOperation *> m_operations; Vector<Link> m_links; @@ -86,7 +88,9 @@ class NodeOperationBuilder { ViewerOperation *m_active_viewer; public: - NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree); + NodeOperationBuilder(const CompositorContext *context, + bNodeTree *b_nodetree, + ExecutionSystem *system); const CompositorContext &context() const { @@ -96,6 +100,8 @@ class NodeOperationBuilder { void convertToOperations(ExecutionSystem *system); void addOperation(NodeOperation *operation); + void replace_operation_with_constant(NodeOperation *operation, + ConstantOperation *constant_operation); /** Map input socket of the current node to an operation socket */ void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket); diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cc b/source/blender/compositor/intern/COM_OpenCLDevice.cc index 0f6ed0dbd2b..3409c8fa3bc 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cc +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cc @@ -110,7 +110,7 @@ const cl_image_format *OpenCLDevice::determineImageFormat(MemoryBuffer *memoryBu return &IMAGE_FORMAT_COLOR; break; default: - BLI_assert(!"Unsupported num_channels."); + BLI_assert_msg(0, "Unsupported num_channels."); } return &IMAGE_FORMAT_COLOR; diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cc b/source/blender/compositor/intern/COM_WorkScheduler.cc index 157ded943d6..8e49bf34b51 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cc +++ b/source/blender/compositor/intern/COM_WorkScheduler.cc @@ -126,7 +126,7 @@ static void *thread_execute_gpu(void *data) return nullptr; } -static void opencl_start(CompositorContext &context) +static void opencl_start(const CompositorContext &context) { if (context.getHasActiveOpenCLDevices()) { g_work_scheduler.opencl.queue = BLI_thread_queue_init(); @@ -458,7 +458,7 @@ void WorkScheduler::schedule(WorkPackage *package) } } -void WorkScheduler::start(CompositorContext &context) +void WorkScheduler::start(const CompositorContext &context) { if (COM_is_opencl_enabled()) { opencl_start(context); diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h index be88859be7c..297943aa63b 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.h +++ b/source/blender/compositor/intern/COM_WorkScheduler.h @@ -65,7 +65,7 @@ struct WorkScheduler { * for every device a thread is created. * \see initialize Initialization and query of the number of devices */ - static void start(CompositorContext &context); + static void start(const CompositorContext &context); /** * \brief stop the execution diff --git a/source/blender/compositor/intern/COM_compositor.cc b/source/blender/compositor/intern/COM_compositor.cc index 5839f53976b..c05234f3bd0 100644 --- a/source/blender/compositor/intern/COM_compositor.cc +++ b/source/blender/compositor/intern/COM_compositor.cc @@ -70,7 +70,7 @@ void COM_execute(RenderData *render_data, const ColorManagedDisplaySettings *displaySettings, const char *viewName) { - /* Initialize mutex, TODO this mutex init is actually not thread safe and + /* Initialize mutex, TODO: this mutex init is actually not thread safe and * should be done somewhere as part of blender startup, all the other * initializations can be done lazily. */ if (!g_compositor.is_initialized) { diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.cc b/source/blender/compositor/nodes/COM_CornerPinNode.cc index 6a120cffe0a..3cfa20f4e05 100644 --- a/source/blender/compositor/nodes/COM_CornerPinNode.cc +++ b/source/blender/compositor/nodes/COM_CornerPinNode.cc @@ -30,7 +30,7 @@ void CornerPinNode::convertToOperations(NodeConverter &converter, const CompositorContext & /*context*/) const { NodeInput *input_image = this->getInputSocket(0); - /* note: socket order differs between UI node and operations: + /* NOTE: socket order differs between UI node and operations: * bNode uses intuitive order following top-down layout: * upper-left, upper-right, lower-left, lower-right * Operations use same order as the tracking blenkernel functions expect: diff --git a/source/blender/compositor/nodes/COM_IDMaskNode.cc b/source/blender/compositor/nodes/COM_IDMaskNode.cc index 9798dabd035..b51e79f2dea 100644 --- a/source/blender/compositor/nodes/COM_IDMaskNode.cc +++ b/source/blender/compositor/nodes/COM_IDMaskNode.cc @@ -17,9 +17,9 @@ */ #include "COM_IDMaskNode.h" -#include "COM_AntiAliasOperation.h" #include "COM_ExecutionSystem.h" #include "COM_IDMaskOperation.h" +#include "COM_SMAAOperation.h" namespace blender::compositor { @@ -42,11 +42,27 @@ void IDMaskNode::convertToOperations(NodeConverter &converter, converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0)); } else { - AntiAliasOperation *antiAliasOperation = new AntiAliasOperation(); - converter.addOperation(antiAliasOperation); + SMAAEdgeDetectionOperation *operation1 = nullptr; - converter.addLink(operation->getOutputSocket(), antiAliasOperation->getInputSocket(0)); - converter.mapOutputSocket(getOutputSocket(0), antiAliasOperation->getOutputSocket(0)); + operation1 = new SMAAEdgeDetectionOperation(); + converter.addOperation(operation1); + + converter.addLink(operation->getOutputSocket(0), operation1->getInputSocket(0)); + + /* Blending Weight Calculation Pixel Shader (Second Pass). */ + SMAABlendingWeightCalculationOperation *operation2 = + new SMAABlendingWeightCalculationOperation(); + converter.addOperation(operation2); + + converter.addLink(operation1->getOutputSocket(), operation2->getInputSocket(0)); + + /* Neighborhood Blending Pixel Shader (Third Pass). */ + SMAANeighborhoodBlendingOperation *operation3 = new SMAANeighborhoodBlendingOperation(); + converter.addOperation(operation3); + + converter.addLink(operation->getOutputSocket(0), operation3->getInputSocket(0)); + converter.addLink(operation2->getOutputSocket(), operation3->getInputSocket(1)); + converter.mapOutputSocket(getOutputSocket(0), operation3->getOutputSocket()); } } diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cc b/source/blender/compositor/nodes/COM_OutputFileNode.cc index 8b5140636c1..25ec7331849 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cc +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cc @@ -36,7 +36,7 @@ void OutputFileNode::add_input_sockets(OutputOpenExrMultiLayerOperation &operati for (NodeInput *input : inputs) { NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)input->getbNodeSocket()->storage; - /* note: layer becomes an empty placeholder if the input is not linked */ + /* NOTE: layer becomes an empty placeholder if the input is not linked. */ operation.add_layer(sockdata->layer, input->getDataType(), input->isLinked()); } } diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cc b/source/blender/compositor/nodes/COM_RenderLayersNode.cc index 851d0366546..253ca542c04 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.cc +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cc @@ -107,7 +107,7 @@ void RenderLayersNode::testRenderLink(NodeConverter &converter, type = DataType::Value; break; default: - BLI_assert(!"Unexpected number of channels for pass"); + BLI_assert_msg(0, "Unexpected number of channels for pass"); type = DataType::Value; break; } diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cc b/source/blender/compositor/nodes/COM_TranslateNode.cc index 1b2ce341a66..3a3e98c3472 100644 --- a/source/blender/compositor/nodes/COM_TranslateNode.cc +++ b/source/blender/compositor/nodes/COM_TranslateNode.cc @@ -42,6 +42,7 @@ void TranslateNode::convertToOperations(NodeConverter &converter, NodeOutput *outputSocket = this->getOutputSocket(0); TranslateOperation *operation = new TranslateOperation(); + operation->set_wrapping(data->wrap_axis); if (data->relative) { const RenderData *rd = context.getRenderData(); const float render_size_factor = context.getRenderPercentageAsFactor(); @@ -55,11 +56,8 @@ void TranslateNode::convertToOperations(NodeConverter &converter, converter.mapInputSocket(inputXSocket, operation->getInputSocket(1)); converter.mapInputSocket(inputYSocket, operation->getInputSocket(2)); converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0)); - - /* FullFrame does not support using WriteBufferOperation. - * TODO: Implement TranslateOperation with wrap support in FullFrame. - */ if (data->wrap_axis && context.get_execution_model() != eExecutionModel::FullFrame) { + /* TODO: To be removed with tiled implementation. */ WriteBufferOperation *writeOperation = new WriteBufferOperation(DataType::Color); WrapOperation *wrapOperation = new WrapOperation(DataType::Color); wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy()); diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc index d1d3752e402..aee8c0d52e8 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc +++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc @@ -41,6 +41,7 @@ ColorBalanceASCCDLOperation::ColorBalanceASCCDLOperation() this->m_inputValueOperation = nullptr; this->m_inputColorOperation = nullptr; this->setResolutionInputSocketIndex(1); + flags.can_be_constant = true; } void ColorBalanceASCCDLOperation::initExecution() @@ -76,6 +77,23 @@ void ColorBalanceASCCDLOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ColorBalanceASCCDLOperation::update_memory_buffer_row(PixelCursor &p) +{ + for (; p.out < p.row_end; p.next()) { + const float *in_factor = p.ins[0]; + const float *in_color = p.ins[1]; + const float fac = MIN2(1.0f, in_factor[0]); + const float fac_m = 1.0f - fac; + p.out[0] = fac_m * in_color[0] + + fac * colorbalance_cdl(in_color[0], m_offset[0], m_power[0], m_slope[0]); + p.out[1] = fac_m * in_color[1] + + fac * colorbalance_cdl(in_color[1], m_offset[1], m_power[1], m_slope[1]); + p.out[2] = fac_m * in_color[2] + + fac * colorbalance_cdl(in_color[2], m_offset[2], m_power[2], m_slope[2]); + p.out[3] = in_color[3]; + } +} + void ColorBalanceASCCDLOperation::deinitExecution() { this->m_inputValueOperation = nullptr; diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h index 5851600190f..d161ea66af2 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h +++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedRowOperation.h" namespace blender::compositor { @@ -26,7 +26,7 @@ namespace blender::compositor { * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ -class ColorBalanceASCCDLOperation : public NodeOperation { +class ColorBalanceASCCDLOperation : public MultiThreadedRowOperation { protected: /** * Prefetched reference to the inputProgram @@ -71,6 +71,8 @@ class ColorBalanceASCCDLOperation : public NodeOperation { { copy_v3_v3(this->m_slope, slope); } + + void update_memory_buffer_row(PixelCursor &p) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc index cac16a3f7b0..674cb79a238 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc +++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc @@ -46,6 +46,7 @@ ColorBalanceLGGOperation::ColorBalanceLGGOperation() this->m_inputValueOperation = nullptr; this->m_inputColorOperation = nullptr; this->setResolutionInputSocketIndex(1); + flags.can_be_constant = true; } void ColorBalanceLGGOperation::initExecution() @@ -81,6 +82,23 @@ void ColorBalanceLGGOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ColorBalanceLGGOperation::update_memory_buffer_row(PixelCursor &p) +{ + for (; p.out < p.row_end; p.next()) { + const float *in_factor = p.ins[0]; + const float *in_color = p.ins[1]; + const float fac = MIN2(1.0f, in_factor[0]); + const float fac_m = 1.0f - fac; + p.out[0] = fac_m * in_color[0] + + fac * colorbalance_lgg(in_color[0], m_lift[0], m_gamma_inv[0], m_gain[0]); + p.out[1] = fac_m * in_color[1] + + fac * colorbalance_lgg(in_color[1], m_lift[1], m_gamma_inv[1], m_gain[1]); + p.out[2] = fac_m * in_color[2] + + fac * colorbalance_lgg(in_color[2], m_lift[2], m_gamma_inv[2], m_gain[2]); + p.out[3] = in_color[3]; + } +} + void ColorBalanceLGGOperation::deinitExecution() { this->m_inputValueOperation = nullptr; diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h index 23f70247b66..4bc929ed76c 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h +++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedRowOperation.h" namespace blender::compositor { @@ -26,7 +26,7 @@ namespace blender::compositor { * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ -class ColorBalanceLGGOperation : public NodeOperation { +class ColorBalanceLGGOperation : public MultiThreadedRowOperation { protected: /** * Prefetched reference to the inputProgram @@ -71,6 +71,8 @@ class ColorBalanceLGGOperation : public NodeOperation { { copy_v3_v3(this->m_gamma_inv, gamma_inv); } + + void update_memory_buffer_row(PixelCursor &p) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc index 168e9b57eb2..b50145b106d 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc @@ -33,6 +33,7 @@ ColorCorrectionOperation::ColorCorrectionOperation() this->m_redChannelEnabled = true; this->m_greenChannelEnabled = true; this->m_blueChannelEnabled = true; + flags.can_be_constant = true; } void ColorCorrectionOperation::initExecution() { @@ -157,6 +158,86 @@ void ColorCorrectionOperation::executePixelSampled(float output[4], output[3] = inputImageColor[3]; } +void ColorCorrectionOperation::update_memory_buffer_row(PixelCursor &p) +{ + for (; p.out < p.row_end; p.next()) { + const float *in_color = p.ins[0]; + const float *in_mask = p.ins[1]; + + const float level = (in_color[0] + in_color[1] + in_color[2]) / 3.0f; + float level_shadows = 0.0f; + float level_midtones = 0.0f; + float level_highlights = 0.0f; + constexpr float MARGIN = 0.10f; + constexpr float MARGIN_DIV = 0.5f / MARGIN; + if (level < this->m_data->startmidtones - MARGIN) { + level_shadows = 1.0f; + } + else if (level < this->m_data->startmidtones + MARGIN) { + level_midtones = ((level - this->m_data->startmidtones) * MARGIN_DIV) + 0.5f; + level_shadows = 1.0f - level_midtones; + } + else if (level < this->m_data->endmidtones - MARGIN) { + level_midtones = 1.0f; + } + else if (level < this->m_data->endmidtones + MARGIN) { + level_highlights = ((level - this->m_data->endmidtones) * MARGIN_DIV) + 0.5f; + level_midtones = 1.0f - level_highlights; + } + else { + level_highlights = 1.0f; + } + float contrast = this->m_data->master.contrast; + float saturation = this->m_data->master.saturation; + float gamma = this->m_data->master.gamma; + float gain = this->m_data->master.gain; + float lift = this->m_data->master.lift; + contrast *= level_shadows * this->m_data->shadows.contrast + + level_midtones * this->m_data->midtones.contrast + + level_highlights * this->m_data->highlights.contrast; + saturation *= level_shadows * this->m_data->shadows.saturation + + level_midtones * this->m_data->midtones.saturation + + level_highlights * this->m_data->highlights.saturation; + gamma *= level_shadows * this->m_data->shadows.gamma + + level_midtones * this->m_data->midtones.gamma + + level_highlights * this->m_data->highlights.gamma; + gain *= level_shadows * this->m_data->shadows.gain + + level_midtones * this->m_data->midtones.gain + + level_highlights * this->m_data->highlights.gain; + lift += level_shadows * this->m_data->shadows.lift + + level_midtones * this->m_data->midtones.lift + + level_highlights * this->m_data->highlights.lift; + + const float inv_gamma = 1.0f / gamma; + const float luma = IMB_colormanagement_get_luminance(in_color); + + float r = luma + saturation * (in_color[0] - luma); + float g = luma + saturation * (in_color[1] - luma); + float b = luma + saturation * (in_color[2] - luma); + + r = 0.5f + (r - 0.5f) * contrast; + g = 0.5f + (g - 0.5f) * contrast; + b = 0.5f + (b - 0.5f) * contrast; + + /* Check for negative values to avoid nan. */ + r = color_correct_powf_safe(r * gain + lift, inv_gamma, r); + g = color_correct_powf_safe(g * gain + lift, inv_gamma, g); + b = color_correct_powf_safe(b * gain + lift, inv_gamma, b); + + /* Mix with mask. */ + const float value = MIN2(1.0f, in_mask[0]); + const float m_value = 1.0f - value; + r = m_value * in_color[0] + value * r; + g = m_value * in_color[1] + value * g; + b = m_value * in_color[2] + value * b; + + p.out[0] = m_redChannelEnabled ? r : in_color[0]; + p.out[1] = m_greenChannelEnabled ? g : in_color[1]; + p.out[2] = m_blueChannelEnabled ? b : in_color[2]; + p.out[3] = in_color[3]; + } +} + void ColorCorrectionOperation::deinitExecution() { this->m_inputImage = nullptr; diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h index c5826ed0152..32b5e02e77a 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h @@ -18,11 +18,11 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedRowOperation.h" namespace blender::compositor { -class ColorCorrectionOperation : public NodeOperation { +class ColorCorrectionOperation : public MultiThreadedRowOperation { private: /** * Cached reference to the inputProgram @@ -69,6 +69,8 @@ class ColorCorrectionOperation : public NodeOperation { { this->m_blueChannelEnabled = enabled; } + + void update_memory_buffer_row(PixelCursor &p) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.cc b/source/blender/compositor/operations/COM_ColorExposureOperation.cc index 1512ff87658..228550a31c5 100644 --- a/source/blender/compositor/operations/COM_ColorExposureOperation.cc +++ b/source/blender/compositor/operations/COM_ColorExposureOperation.cc @@ -26,6 +26,7 @@ ExposureOperation::ExposureOperation() this->addInputSocket(DataType::Value); this->addOutputSocket(DataType::Color); this->m_inputProgram = nullptr; + flags.can_be_constant = true; } void ExposureOperation::initExecution() @@ -52,6 +53,19 @@ void ExposureOperation::executePixelSampled(float output[4], output[3] = inputValue[3]; } +void ExposureOperation::update_memory_buffer_row(PixelCursor &p) +{ + for (; p.out < p.row_end; p.next()) { + const float *in_value = p.ins[0]; + const float *in_exposure = p.ins[1]; + const float exposure = pow(2, in_exposure[0]); + p.out[0] = in_value[0] * exposure; + p.out[1] = in_value[1] * exposure; + p.out[2] = in_value[2] * exposure; + p.out[3] = in_value[3]; + } +} + void ExposureOperation::deinitExecution() { this->m_inputProgram = nullptr; diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.h b/source/blender/compositor/operations/COM_ColorExposureOperation.h index 0cfaa059e41..1eb790e8d52 100644 --- a/source/blender/compositor/operations/COM_ColorExposureOperation.h +++ b/source/blender/compositor/operations/COM_ColorExposureOperation.h @@ -18,11 +18,11 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedRowOperation.h" namespace blender::compositor { -class ExposureOperation : public NodeOperation { +class ExposureOperation : public MultiThreadedRowOperation { private: /** * Cached reference to the inputProgram @@ -47,6 +47,8 @@ class ExposureOperation : public NodeOperation { * Deinitialize the execution */ void deinitExecution() override; + + void update_memory_buffer_row(PixelCursor &p) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ConstantOperation.cc b/source/blender/compositor/operations/COM_ConstantOperation.cc new file mode 100644 index 00000000000..f905edbde76 --- /dev/null +++ b/source/blender/compositor/operations/COM_ConstantOperation.cc @@ -0,0 +1,28 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#include "COM_ConstantOperation.h" + +namespace blender::compositor { + +ConstantOperation::ConstantOperation() +{ + flags.is_constant_operation = true; +} + +} // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ConstantOperation.h b/source/blender/compositor/operations/COM_ConstantOperation.h new file mode 100644 index 00000000000..2709efeebd8 --- /dev/null +++ b/source/blender/compositor/operations/COM_ConstantOperation.h @@ -0,0 +1,36 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#pragma once + +#include "COM_NodeOperation.h" + +namespace blender::compositor { + +/** + * Base class for primitive constant operations (Color/Vector/Value). The rest of operations that + * can be constant are evaluated into primitives during constant folding. + */ +class ConstantOperation : public NodeOperation { + public: + ConstantOperation(); + + virtual const float *get_constant_elem() = 0; +}; + +} // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc index 9e18a8e2f2c..2454f507664 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc @@ -370,7 +370,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect) int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; - // Note: Cache buffer has original tilesize width, but new height. + // NOTE: Cache buffer has original tilesize width, but new height. // We have to calculate the additional rows in the first pass, // to have valid data available for the second pass. tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); @@ -500,7 +500,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect) int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; - // Note: Cache buffer has original tilesize width, but new height. + // NOTE: Cache buffer has original tilesize width, but new height. // We have to calculate the additional rows in the first pass, // to have valid data available for the second pass. tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); diff --git a/source/blender/compositor/operations/COM_GammaOperation.cc b/source/blender/compositor/operations/COM_GammaOperation.cc index 343e335070a..396d3942b06 100644 --- a/source/blender/compositor/operations/COM_GammaOperation.cc +++ b/source/blender/compositor/operations/COM_GammaOperation.cc @@ -28,6 +28,7 @@ GammaOperation::GammaOperation() this->addOutputSocket(DataType::Color); this->m_inputProgram = nullptr; this->m_inputGammaProgram = nullptr; + flags.can_be_constant = true; } void GammaOperation::initExecution() { @@ -51,6 +52,20 @@ void GammaOperation::executePixelSampled(float output[4], float x, float y, Pixe output[3] = inputValue[3]; } +void GammaOperation::update_memory_buffer_row(PixelCursor &p) +{ + for (; p.out < p.row_end; p.next()) { + const float *in_value = p.ins[0]; + const float *in_gamma = p.ins[1]; + const float gamma = in_gamma[0]; + /* Check for negative to avoid nan's. */ + p.out[0] = in_value[0] > 0.0f ? powf(in_value[0], gamma) : in_value[0]; + p.out[1] = in_value[1] > 0.0f ? powf(in_value[1], gamma) : in_value[1]; + p.out[2] = in_value[2] > 0.0f ? powf(in_value[2], gamma) : in_value[2]; + p.out[3] = in_value[3]; + } +} + void GammaOperation::deinitExecution() { this->m_inputProgram = nullptr; diff --git a/source/blender/compositor/operations/COM_GammaOperation.h b/source/blender/compositor/operations/COM_GammaOperation.h index 034046106d6..713d3d8484f 100644 --- a/source/blender/compositor/operations/COM_GammaOperation.h +++ b/source/blender/compositor/operations/COM_GammaOperation.h @@ -18,11 +18,11 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedRowOperation.h" namespace blender::compositor { -class GammaOperation : public NodeOperation { +class GammaOperation : public MultiThreadedRowOperation { private: /** * Cached reference to the inputProgram @@ -47,6 +47,8 @@ class GammaOperation : public NodeOperation { * Deinitialize the execution */ void deinitExecution() override; + + void update_memory_buffer_row(PixelCursor &p) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.h b/source/blender/compositor/operations/COM_GlareBaseOperation.h index 7ae15595e3b..50db4e02940 100644 --- a/source/blender/compositor/operations/COM_GlareBaseOperation.h +++ b/source/blender/compositor/operations/COM_GlareBaseOperation.h @@ -27,7 +27,7 @@ namespace blender::compositor { /* soms macros for color handling */ typedef float fRGB[4]; -/* TODO - replace with BLI_math_vector */ +/* TODO: replace with BLI_math_vector. */ /* multiply c2 by color rgb, rgb as separate arguments */ #define fRGB_rgbmult(c, r, g, b) \ { \ diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.cc b/source/blender/compositor/operations/COM_IDMaskOperation.cc index 38f8b7e075f..bb11ac8b1be 100644 --- a/source/blender/compositor/operations/COM_IDMaskOperation.cc +++ b/source/blender/compositor/operations/COM_IDMaskOperation.cc @@ -25,6 +25,7 @@ IDMaskOperation::IDMaskOperation() this->addInputSocket(DataType::Value); this->addOutputSocket(DataType::Value); this->flags.complex = true; + flags.can_be_constant = true; } void *IDMaskOperation::initializeTileData(rcti *rect) diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h index 92a2c291a72..e8cd9c722df 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.h +++ b/source/blender/compositor/operations/COM_MaskOperation.h @@ -35,7 +35,7 @@ class MaskOperation : public NodeOperation { protected: Mask *m_mask; - /* note, these are used more like aspect, + /* NOTE: these are used more like aspect, * but they _do_ impact on mask detail */ int m_maskWidth; int m_maskHeight; diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cc b/source/blender/compositor/operations/COM_NormalizeOperation.cc index faacb429f71..f93afcaab95 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.cc +++ b/source/blender/compositor/operations/COM_NormalizeOperation.cc @@ -36,7 +36,7 @@ void NormalizeOperation::initExecution() void NormalizeOperation::executePixel(float output[4], int x, int y, void *data) { - /* using generic two floats struct to store x: min y: mult */ + /* using generic two floats struct to store `x: min`, `y: multiply` */ NodeTwoFloats *minmult = (NodeTwoFloats *)data; this->m_imageReader->read(output, x, y, nullptr); @@ -89,7 +89,7 @@ void *NormalizeOperation::initializeTileData(rcti *rect) lockMutex(); if (this->m_cachedInstance == nullptr) { MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); - /* using generic two floats struct to store x: min y: mult */ + /* using generic two floats struct to store `x: min`, `y: multiply`. */ NodeTwoFloats *minmult = new NodeTwoFloats(); float *buffer = tile->getBuffer(); diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.h b/source/blender/compositor/operations/COM_NormalizeOperation.h index 93d4a0fc67d..c89ba372189 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.h +++ b/source/blender/compositor/operations/COM_NormalizeOperation.h @@ -36,7 +36,7 @@ class NormalizeOperation : public NodeOperation { /** * \brief temporarily cache of the execution storage - * it stores x->min and y->mult + * it stores `x->min` and `y->multiply`. */ NodeTwoFloats *m_cachedInstance; diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc index 1ee749b1a49..7e896046f01 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cc +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc @@ -426,8 +426,8 @@ void OutputOpenExrMultiLayerOperation::deinitExecution() IMB_exr_write_channels(exrhandle); } else { - /* TODO, get the error from openexr's exception */ - /* XXX nice way to do report? */ + /* TODO: get the error from openexr's exception. */ + /* XXX: nice way to do report? */ printf("Error Writing Render Result, see console\n"); } diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h index d240c8b06e9..3bae230aa06 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackOperation.h +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h @@ -37,7 +37,7 @@ class PlaneTrackCommon { char m_trackingObjectName[64]; char m_planeTrackName[64]; - /* note: this class is not an operation itself (to prevent virtual inheritance issues) + /* NOTE: this class is not an operation itself (to prevent virtual inheritance issues) * implementation classes must make wrappers to use these methods, see below. */ void read_and_calculate_corners(PlaneDistortBaseOperation *distort_op); diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cc b/source/blender/compositor/operations/COM_ReadBufferOperation.cc index cc58f29e8d9..d35d2516f16 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.cc +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cc @@ -44,7 +44,7 @@ void ReadBufferOperation::determineResolution(unsigned int resolution[2], operation->determineResolution(resolution, preferredResolution); operation->setResolution(resolution); - /** \todo: may not occur!, but does with blur node */ + /** \todo may not occur! But does with blur node. */ if (this->m_memoryProxy->getExecutor()) { this->m_memoryProxy->getExecutor()->setResolution(resolution); } diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cc b/source/blender/compositor/operations/COM_RenderLayersProg.cc index 1ac451b95c2..72e2c92c9cf 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cc +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cc @@ -43,6 +43,7 @@ RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elem this->m_inputBuffer = nullptr; this->m_elementsize = elementsize; this->m_rd = nullptr; + layer_buffer_ = nullptr; this->addOutputSocket(type); } @@ -65,6 +66,9 @@ void RenderLayersProg::initExecution() if (rl) { this->m_inputBuffer = RE_RenderLayerGetPass( rl, this->m_passName.c_str(), this->m_viewName); + if (m_inputBuffer) { + layer_buffer_ = new MemoryBuffer(m_inputBuffer, m_elementsize, getWidth(), getHeight()); + } } } } @@ -159,7 +163,7 @@ void RenderLayersProg::executePixelSampled(float output[4], float x, float y, Pi } else { expected_element_size = 0; - BLI_assert(!"Something horribly wrong just happened"); + BLI_assert_msg(0, "Something horribly wrong just happened"); } BLI_assert(expected_element_size == actual_element_size); } @@ -186,6 +190,10 @@ void RenderLayersProg::executePixelSampled(float output[4], float x, float y, Pi void RenderLayersProg::deinitExecution() { this->m_inputBuffer = nullptr; + if (layer_buffer_) { + delete layer_buffer_; + layer_buffer_ = nullptr; + } } void RenderLayersProg::determineResolution(unsigned int resolution[2], @@ -255,6 +263,20 @@ std::unique_ptr<MetaData> RenderLayersProg::getMetaData() return std::move(callback_data.meta_data); } +void RenderLayersProg::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> UNUSED(inputs)) +{ + BLI_assert(output->get_num_channels() >= m_elementsize); + if (layer_buffer_) { + output->copy_from(layer_buffer_, area, 0, m_elementsize, 0); + } + else { + std::unique_ptr<float[]> zero_elem = std::make_unique<float[]>(m_elementsize); + output->fill(area, 0, zero_elem.get(), m_elementsize); + } +} + /* ******** Render Layers AO Operation ******** */ void RenderLayersAOOperation::executePixelSampled(float output[4], float x, @@ -271,6 +293,21 @@ void RenderLayersAOOperation::executePixelSampled(float output[4], output[3] = 1.0f; } +void RenderLayersAOOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> UNUSED(inputs)) +{ + BLI_assert(output->get_num_channels() == COM_DATA_TYPE_COLOR_CHANNELS); + BLI_assert(m_elementsize == COM_DATA_TYPE_COLOR_CHANNELS); + if (layer_buffer_) { + output->copy_from(layer_buffer_, area, 0, COM_DATA_TYPE_VECTOR_CHANNELS, 0); + } + else { + output->fill(area, 0, COM_VECTOR_ZERO, COM_DATA_TYPE_VECTOR_CHANNELS); + } + output->fill(area, 3, COM_VALUE_ONE, COM_DATA_TYPE_VALUE_CHANNELS); +} + /* ******** Render Layers Alpha Operation ******** */ void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, @@ -289,6 +326,20 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4], } } +void RenderLayersAlphaProg::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> UNUSED(inputs)) +{ + BLI_assert(output->get_num_channels() == COM_DATA_TYPE_VALUE_CHANNELS); + BLI_assert(m_elementsize == COM_DATA_TYPE_COLOR_CHANNELS); + if (layer_buffer_) { + output->copy_from(layer_buffer_, area, 3, COM_DATA_TYPE_VALUE_CHANNELS, 0); + } + else { + output->fill(area, COM_VALUE_ZERO); + } +} + /* ******** Render Layers Depth Operation ******** */ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, @@ -309,4 +360,19 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], } } +void RenderLayersDepthProg::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> UNUSED(inputs)) +{ + BLI_assert(output->get_num_channels() == COM_DATA_TYPE_VALUE_CHANNELS); + BLI_assert(m_elementsize == COM_DATA_TYPE_VALUE_CHANNELS); + if (layer_buffer_) { + output->copy_from(layer_buffer_, area); + } + else { + const float default_depth = 10e10f; + output->fill(area, &default_depth); + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index 33e4fb163c5..dd76a56d645 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -20,7 +20,7 @@ #include "BLI_listbase.h" #include "BLI_utildefines.h" -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" #include "DNA_scene_types.h" #include "MEM_guardedalloc.h" @@ -31,9 +31,9 @@ namespace blender::compositor { /** * Base class for all renderlayeroperations * - * \todo: rename to operation. + * \todo Rename to operation. */ -class RenderLayersProg : public NodeOperation { +class RenderLayersProg : public MultiThreadedOperation { protected: /** * Reference to the scene object. @@ -50,8 +50,11 @@ class RenderLayersProg : public NodeOperation { */ const char *m_viewName; + const MemoryBuffer *layer_buffer_; + /** - * cached instance to the float buffer inside the layer + * Cached instance to the float buffer inside the layer. + * TODO: To be removed with tiled implementation. */ float *m_inputBuffer; @@ -126,6 +129,10 @@ class RenderLayersProg : public NodeOperation { void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; std::unique_ptr<MetaData> getMetaData() override; + + virtual void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; }; class RenderLayersAOOperation : public RenderLayersProg { @@ -135,6 +142,10 @@ class RenderLayersAOOperation : public RenderLayersProg { { } void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; }; class RenderLayersAlphaProg : public RenderLayersProg { @@ -144,6 +155,10 @@ class RenderLayersAlphaProg : public RenderLayersProg { { } void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; }; class RenderLayersDepthProg : public RenderLayersProg { @@ -153,6 +168,10 @@ class RenderLayersDepthProg : public RenderLayersProg { { } void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SMAAOperation.cc b/source/blender/compositor/operations/COM_SMAAOperation.cc index 7a272fa8795..3c753591ced 100644 --- a/source/blender/compositor/operations/COM_SMAAOperation.cc +++ b/source/blender/compositor/operations/COM_SMAAOperation.cc @@ -21,6 +21,7 @@ #include "COM_SMAAOperation.h" #include "BLI_math.h" #include "COM_SMAAAreaTexture.h" +#include "BKE_node.h" extern "C" { #include "IMB_colormanagement.h" @@ -36,14 +37,14 @@ namespace blender::compositor { * * http://www.iryoku.com/smaa/ * - * This file is based on smaa-cpp: + * This file is based on SMAA-CPP: * * https://github.com/iRi-E/smaa-cpp * * Currently only SMAA 1x mode is provided, so the operation will be done - * with no spatial multisampling nor temporal supersampling. + * with no spatial multi-sampling nor temporal super-sampling. * - * Note: This program assumes the screen coordinates are DirectX style, so + * NOTE: This program assumes the screen coordinates are DirectX style, so * the vertical direction is upside-down. "top" and "bottom" actually mean * bottom and top, respectively. */ @@ -166,8 +167,8 @@ SMAAEdgeDetectionOperation::SMAAEdgeDetectionOperation() this->flags.complex = true; this->m_imageReader = nullptr; this->m_valueReader = nullptr; - this->m_threshold = 0.1f; - this->m_contrast_limit = 2.0f; + this->setThreshold(CMP_DEFAULT_SMAA_THRESHOLD); + this->setLocalContrastAdaptationFactor(CMP_DEFAULT_SMAA_CONTRAST_LIMIT); } void SMAAEdgeDetectionOperation::initExecution() @@ -297,7 +298,7 @@ SMAABlendingWeightCalculationOperation::SMAABlendingWeightCalculationOperation() this->addOutputSocket(DataType::Color); this->flags.complex = true; this->m_imageReader = nullptr; - this->m_corner_rounding = 25; + this->setCornerRounding(CMP_DEFAULT_SMAA_CORNER_ROUNDING); } void *SMAABlendingWeightCalculationOperation::initializeTileData(rcti *rect) diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cc b/source/blender/compositor/operations/COM_ScaleOperation.cc index 03525d4ea01..f03b9fcf34d 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cc +++ b/source/blender/compositor/operations/COM_ScaleOperation.cc @@ -21,10 +21,10 @@ namespace blender::compositor { #define USE_FORCE_BILINEAR -/* XXX - ignore input and use default from old compositor, - * could become an option like the transform node - campbell +/* XXX(campbell): ignore input and use default from old compositor, + * could become an option like the transform node. * - * note: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1) + * NOTE: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1) */ BaseScaleOperation::BaseScaleOperation() @@ -37,12 +37,16 @@ BaseScaleOperation::BaseScaleOperation() m_variable_size = false; } -ScaleOperation::ScaleOperation() : BaseScaleOperation() +ScaleOperation::ScaleOperation() : ScaleOperation(DataType::Color) { - this->addInputSocket(DataType::Color); +} + +ScaleOperation::ScaleOperation(DataType data_type) : BaseScaleOperation() +{ + this->addInputSocket(data_type); this->addInputSocket(DataType::Value); this->addInputSocket(DataType::Value); - this->addOutputSocket(DataType::Color); + this->addOutputSocket(data_type); this->setResolutionInputSocketIndex(0); this->m_inputOperation = nullptr; this->m_inputXOperation = nullptr; diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h index dc3de3602bf..2f9a7be92e6 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.h +++ b/source/blender/compositor/operations/COM_ScaleOperation.h @@ -55,6 +55,7 @@ class ScaleOperation : public BaseScaleOperation { public: ScaleOperation(); + ScaleOperation(DataType data_type); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) override; diff --git a/source/blender/compositor/operations/COM_SetColorOperation.cc b/source/blender/compositor/operations/COM_SetColorOperation.cc index 79dee33e266..bfe735aab15 100644 --- a/source/blender/compositor/operations/COM_SetColorOperation.cc +++ b/source/blender/compositor/operations/COM_SetColorOperation.cc @@ -44,8 +44,7 @@ void SetColorOperation::determineResolution(unsigned int resolution[2], void SetColorOperation::update_memory_buffer(MemoryBuffer *output, const rcti &area, - Span<MemoryBuffer *> UNUSED(inputs), - ExecutionSystem &UNUSED(exec_system)) + Span<MemoryBuffer *> UNUSED(inputs)) { BLI_assert(output->is_a_single_elem()); float *out_elem = output->get_elem(area.xmin, area.ymin); diff --git a/source/blender/compositor/operations/COM_SetColorOperation.h b/source/blender/compositor/operations/COM_SetColorOperation.h index 2e22ef60ba4..f4c0948ee1b 100644 --- a/source/blender/compositor/operations/COM_SetColorOperation.h +++ b/source/blender/compositor/operations/COM_SetColorOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_ConstantOperation.h" namespace blender::compositor { @@ -26,7 +26,7 @@ namespace blender::compositor { * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ -class SetColorOperation : public NodeOperation { +class SetColorOperation : public ConstantOperation { private: float m_color[4]; @@ -36,6 +36,11 @@ class SetColorOperation : public NodeOperation { */ SetColorOperation(); + const float *get_constant_elem() override + { + return m_color; + } + float getChannel1() { return this->m_color[0]; @@ -83,8 +88,7 @@ class SetColorOperation : public NodeOperation { void update_memory_buffer(MemoryBuffer *output, const rcti &area, - Span<MemoryBuffer *> inputs, - ExecutionSystem &exec_system) override; + Span<MemoryBuffer *> inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SetValueOperation.cc b/source/blender/compositor/operations/COM_SetValueOperation.cc index 359647c8fe3..c12fb106afd 100644 --- a/source/blender/compositor/operations/COM_SetValueOperation.cc +++ b/source/blender/compositor/operations/COM_SetValueOperation.cc @@ -44,8 +44,7 @@ void SetValueOperation::determineResolution(unsigned int resolution[2], void SetValueOperation::update_memory_buffer(MemoryBuffer *output, const rcti &area, - Span<MemoryBuffer *> UNUSED(inputs), - ExecutionSystem &UNUSED(exec_system)) + Span<MemoryBuffer *> UNUSED(inputs)) { BLI_assert(output->is_a_single_elem()); float *out_elem = output->get_elem(area.xmin, area.ymin); diff --git a/source/blender/compositor/operations/COM_SetValueOperation.h b/source/blender/compositor/operations/COM_SetValueOperation.h index acde5aa03b7..f18d44d9554 100644 --- a/source/blender/compositor/operations/COM_SetValueOperation.h +++ b/source/blender/compositor/operations/COM_SetValueOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_ConstantOperation.h" namespace blender::compositor { @@ -26,7 +26,7 @@ namespace blender::compositor { * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ -class SetValueOperation : public NodeOperation { +class SetValueOperation : public ConstantOperation { private: float m_value; @@ -36,6 +36,11 @@ class SetValueOperation : public NodeOperation { */ SetValueOperation(); + const float *get_constant_elem() override + { + return &m_value; + } + float getValue() { return this->m_value; @@ -53,8 +58,7 @@ class SetValueOperation : public NodeOperation { unsigned int preferredResolution[2]) override; void update_memory_buffer(MemoryBuffer *output, const rcti &area, - Span<MemoryBuffer *> inputs, - ExecutionSystem &exec_system) override; + Span<MemoryBuffer *> inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.cc b/source/blender/compositor/operations/COM_SetVectorOperation.cc index 7152d5e61d4..7b8cf44048c 100644 --- a/source/blender/compositor/operations/COM_SetVectorOperation.cc +++ b/source/blender/compositor/operations/COM_SetVectorOperation.cc @@ -32,9 +32,9 @@ void SetVectorOperation::executePixelSampled(float output[4], float /*y*/, PixelSampler /*sampler*/) { - output[0] = this->m_x; - output[1] = this->m_y; - output[2] = this->m_z; + output[0] = vector_.x; + output[1] = vector_.y; + output[2] = vector_.z; } void SetVectorOperation::determineResolution(unsigned int resolution[2], diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.h b/source/blender/compositor/operations/COM_SetVectorOperation.h index b444339fcb2..41fd06659d6 100644 --- a/source/blender/compositor/operations/COM_SetVectorOperation.h +++ b/source/blender/compositor/operations/COM_SetVectorOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_ConstantOperation.h" namespace blender::compositor { @@ -26,12 +26,14 @@ namespace blender::compositor { * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ -class SetVectorOperation : public NodeOperation { +class SetVectorOperation : public ConstantOperation { private: - float m_x; - float m_y; - float m_z; - float m_w; + struct { + float x; + float y; + float z; + float w; + } vector_; public: /** @@ -39,37 +41,42 @@ class SetVectorOperation : public NodeOperation { */ SetVectorOperation(); + const float *get_constant_elem() override + { + return reinterpret_cast<float *>(&vector_); + } + float getX() { - return this->m_x; + return vector_.x; } void setX(float value) { - this->m_x = value; + vector_.x = value; } float getY() { - return this->m_y; + return vector_.y; } void setY(float value) { - this->m_y = value; + vector_.y = value; } float getZ() { - return this->m_z; + return vector_.z; } void setZ(float value) { - this->m_z = value; + vector_.z = value; } float getW() { - return this->m_w; + return vector_.w; } void setW(float value) { - this->m_w = value; + vector_.w = value; } /** diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cc b/source/blender/compositor/operations/COM_SunBeamsOperation.cc index 839eeb9ff8f..ff117841e8e 100644 --- a/source/blender/compositor/operations/COM_SunBeamsOperation.cc +++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cc @@ -197,7 +197,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator { madd_v4_v4fl(output, border, border[3] * weight); } - /* TODO implement proper filtering here, see + /* TODO: implement proper filtering here, see * https://en.wikipedia.org/wiki/Lanczos_resampling * https://en.wikipedia.org/wiki/Sinc_function * diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index e5f56673694..6fec9ab8f33 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -31,7 +31,7 @@ namespace blender::compositor { /** * Base class for all renderlayeroperations * - * \todo: rename to operation. + * \todo Rename to operation. */ class TextureBaseOperation : public NodeOperation { private: diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cc b/source/blender/compositor/operations/COM_TranslateOperation.cc index 49135f25320..a3db086e974 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.cc +++ b/source/blender/compositor/operations/COM_TranslateOperation.cc @@ -20,12 +20,15 @@ namespace blender::compositor { -TranslateOperation::TranslateOperation() +TranslateOperation::TranslateOperation() : TranslateOperation(DataType::Color) { - this->addInputSocket(DataType::Color); +} +TranslateOperation::TranslateOperation(DataType data_type) +{ + this->addInputSocket(data_type); this->addInputSocket(DataType::Value); this->addInputSocket(DataType::Value); - this->addOutputSocket(DataType::Color); + this->addOutputSocket(data_type); this->setResolutionInputSocketIndex(0); this->m_inputOperation = nullptr; this->m_inputXOperation = nullptr; @@ -33,6 +36,8 @@ TranslateOperation::TranslateOperation() this->m_isDeltaSet = false; this->m_factorX = 1.0f; this->m_factorY = 1.0f; + this->x_extend_mode_ = MemoryBufferExtend::Clip; + this->y_extend_mode_ = MemoryBufferExtend::Clip; } void TranslateOperation::initExecution() { @@ -83,4 +88,58 @@ void TranslateOperation::setFactorXY(float factorX, float factorY) m_factorY = factorY; } +void TranslateOperation::set_wrapping(int wrapping_type) +{ + switch (wrapping_type) { + case CMP_NODE_WRAP_X: + x_extend_mode_ = MemoryBufferExtend::Repeat; + break; + case CMP_NODE_WRAP_Y: + y_extend_mode_ = MemoryBufferExtend::Repeat; + break; + case CMP_NODE_WRAP_XY: + x_extend_mode_ = MemoryBufferExtend::Repeat; + y_extend_mode_ = MemoryBufferExtend::Repeat; + break; + default: + break; + } +} + +void TranslateOperation::get_area_of_interest(const int input_idx, + const rcti &output_area, + rcti &r_input_area) +{ + if (input_idx == 0) { + ensureDelta(); + r_input_area = output_area; + if (x_extend_mode_ == MemoryBufferExtend::Clip) { + const int delta_x = this->getDeltaX(); + BLI_rcti_translate(&r_input_area, -delta_x, 0); + } + if (y_extend_mode_ == MemoryBufferExtend::Clip) { + const int delta_y = this->getDeltaY(); + BLI_rcti_translate(&r_input_area, 0, -delta_y); + } + } +} + +void TranslateOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + MemoryBuffer *input = inputs[0]; + const int delta_x = this->getDeltaX(); + const int delta_y = this->getDeltaY(); + for (int y = area.ymin; y < area.ymax; y++) { + float *out = output->get_elem(area.xmin, y); + for (int x = area.xmin; x < area.xmax; x++) { + const int input_x = x - delta_x; + const int input_y = y - delta_y; + input->read(out, input_x, input_y, x_extend_mode_, y_extend_mode_); + out += output->elem_stride; + } + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h index eb3a664159f..ce1965cecef 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.h +++ b/source/blender/compositor/operations/COM_TranslateOperation.h @@ -18,11 +18,12 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_ConstantOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { -class TranslateOperation : public NodeOperation { +class TranslateOperation : public MultiThreadedOperation { private: SocketReader *m_inputOperation; SocketReader *m_inputXOperation; @@ -32,9 +33,12 @@ class TranslateOperation : public NodeOperation { bool m_isDeltaSet; float m_factorX; float m_factorY; + MemoryBufferExtend x_extend_mode_; + MemoryBufferExtend y_extend_mode_; public: TranslateOperation(); + TranslateOperation(DataType data_type); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) override; @@ -55,16 +59,38 @@ class TranslateOperation : public NodeOperation { inline void ensureDelta() { if (!this->m_isDeltaSet) { - float tempDelta[4]; - this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest); - this->m_deltaX = tempDelta[0]; - this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest); - this->m_deltaY = tempDelta[0]; + if (execution_model_ == eExecutionModel::Tiled) { + float tempDelta[4]; + this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest); + this->m_deltaX = tempDelta[0]; + this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest); + this->m_deltaY = tempDelta[0]; + } + else { + this->m_deltaX = 0; + NodeOperation *x_op = getInputOperation(1); + if (x_op->get_flags().is_constant_operation) { + this->m_deltaX = ((ConstantOperation *)x_op)->get_constant_elem()[0]; + } + this->m_deltaY = 0; + NodeOperation *y_op = getInputOperation(2); + if (y_op->get_flags().is_constant_operation) { + this->m_deltaY = ((ConstantOperation *)y_op)->get_constant_elem()[0]; + } + } + this->m_isDeltaSet = true; } } void setFactorXY(float factorX, float factorY); + void set_wrapping(int wrapping_type); + + void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cc b/source/blender/compositor/operations/COM_VectorBlurOperation.cc index fd64bda156b..b5b5d426338 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cc +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cc @@ -432,7 +432,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove) } } - /* 2: evaluate horizontal scanlines and calculate alphas */ + /* 2: evaluate horizontal scan-lines and calculate alphas. */ row1 = rectmove; for (y = 0; y < ysize; y++) { row1++; @@ -449,7 +449,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove) /* now we can blend values */ next = row1[step]; - /* note, prev value can be next value, but we do this loop to clear 128 then */ + /* NOTE: prev value can be next value, but we do this loop to clear 128 then. */ for (a = 0; a < step; a++) { int fac, mfac; @@ -463,7 +463,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove) } } - /* 3: evaluate vertical scanlines and calculate alphas */ + /* 3: evaluate vertical scan-lines and calculate alphas */ /* use for reading a copy of the original tagged buffer */ for (x = 0; x < xsize; x++) { row1 = rectmove + x + xsize; @@ -480,7 +480,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove) if (y + step != ysize) { /* now we can blend values */ next = row1[step * xsize]; - /* note, prev value can be next value, but we do this loop to clear 128 then */ + /* NOTE: prev value can be next value, but we do this loop to clear 128 then. */ for (a = 0; a < step; a++) { int fac, mfac; diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cc b/source/blender/compositor/operations/COM_WriteBufferOperation.cc index 1aa19f26e2b..e2dc6287baf 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cc +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cc @@ -124,7 +124,7 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, * 3. schedule read back from opencl to main device (outputbuffer) * 4. schedule native callback * - * note: list of cl_mem will be filled by 2, and needs to be cleaned up by 4 + * NOTE: list of cl_mem will be filled by 2, and needs to be cleaned up by 4 */ // STEP 1 const unsigned int outputBufferWidth = outputBuffer->getWidth(); diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index 27441c9a7ae..749b1bba871 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -159,7 +159,7 @@ void DEG_ids_restore_recalc(Depsgraph *depsgraph); /* Graph Evaluation ----------------------------- */ /* Frame changed recalculation entry point. */ -void DEG_evaluate_on_framechange(Depsgraph *graph, float ctime); +void DEG_evaluate_on_framechange(Depsgraph *graph, float frame); /* Data changed recalculation entry point. */ void DEG_evaluate_on_refresh(Depsgraph *graph); diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 42c9cccceed..c029d203574 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -33,6 +33,7 @@ struct Depsgraph; /* ------------------------------------------------ */ struct CacheFile; +struct Collection; struct CustomData_MeshMasks; struct ID; struct Main; @@ -40,7 +41,6 @@ struct Object; struct Scene; struct Simulation; struct bNodeTree; -struct Collection; #include "BLI_sys_types.h" diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index f877e99b16b..17f5ca0db79 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -95,7 +95,7 @@ struct ViewLayer *DEG_get_evaluated_view_layer(const struct Depsgraph *graph); /* Get evaluated version of object for given original one. */ struct Object *DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object); -/* Get evaluated version of given ID datablock. */ +/* Get evaluated version of given ID data-block. */ struct ID *DEG_get_evaluated_id(const struct Depsgraph *depsgraph, struct ID *id); /* Get evaluated version of data pointed to by RNA pointer */ @@ -106,7 +106,7 @@ void DEG_get_evaluated_rna_pointer(const struct Depsgraph *depsgraph, /* Get original version of object for given evaluated one. */ struct Object *DEG_get_original_object(struct Object *object); -/* Get original version of given evaluated ID datablock. */ +/* Get original version of given evaluated ID data-block. */ struct ID *DEG_get_original_id(struct ID *id); /* Check whether given ID is an original, @@ -122,7 +122,7 @@ bool DEG_is_original_object(const struct Object *object); bool DEG_is_evaluated_id(const struct ID *id); bool DEG_is_evaluated_object(const struct Object *object); -/* Check whether depsgraph os fully evaluated. This includes the following checks: +/* Check whether depsgraph is fully evaluated. This includes the following checks: * - Relations are up-to-date. * - Nothing is tagged for update. */ bool DEG_is_fully_evaluated(const struct Depsgraph *depsgraph); @@ -180,7 +180,7 @@ void DEG_iterator_objects_next(struct BLI_Iterator *iter); void DEG_iterator_objects_end(struct BLI_Iterator *iter); /** - * Note: Be careful with DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY objects. + * NOTE: Be careful with DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY objects. * Although they are available they have no overrides (collection_properties) * and will crash if you try to access it. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index f4d65698bee..41512168f57 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -97,7 +97,7 @@ bool DepsgraphBuilder::need_pull_base_into_graph(Base *base) property_id = AnimatedPropertyID(&object->id, &RNA_Object, "hide_render"); } else { - BLI_assert(!"Unknown evaluation mode."); + BLI_assert_msg(0, "Unknown evaluation mode."); return false; } return cache_->isPropertyAnimated(&object->id, property_id); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 56168739fae..e561d0b653c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -114,6 +114,7 @@ #include "SEQ_iterator.h" #include "intern/builder/deg_builder.h" +#include "intern/builder/deg_builder_rna.h" #include "intern/depsgraph.h" #include "intern/depsgraph_tag.h" #include "intern/depsgraph_type.h" @@ -226,7 +227,7 @@ OperationNode *DepsgraphNodeBuilder::add_operation_node(ComponentNode *comp_node comp_node->identifier().c_str(), op_node->identifier().c_str(), op_node); - BLI_assert(!"Should not happen!"); + BLI_assert_msg(0, "Should not happen!"); } return op_node; } @@ -1199,7 +1200,7 @@ void DepsgraphNodeBuilder::build_driver_id_property(ID *id, const char *rna_path if (prop == nullptr) { return; } - if (!RNA_property_is_idprop(prop)) { + if (!rna_prop_affects_parameters_node(&ptr, prop)) { return; } const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); @@ -1495,7 +1496,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob add_operation_node( &object->id, NodeType::BATCH_CACHE, - OperationCode::GEOMETRY_SELECT_UPDATE, + OperationCode::BATCH_UPDATE_SELECT, [object_cow](::Depsgraph *depsgraph) { BKE_object_select_update(depsgraph, object_cow); }); } @@ -1516,33 +1517,37 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool if (key) { build_shapekeys(key); } - /* Nodes for result of obdata's evaluation, and geometry - * evaluation on object. */ + + /* Geometry evaluation. */ + /* Entry operation, takes care of initialization, and some other + * relations which needs to be run prior to actual geometry evaluation. */ + op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); + op_node->set_as_entry(); + + add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM); + const ID_Type id_type = GS(obdata->name); switch (id_type) { case ID_ME: { - op_node = add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_mesh_eval_geometry(depsgraph, (Mesh *)obdata_cow); - }); - op_node->set_as_entry(); + add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_mesh_eval_geometry(depsgraph, (Mesh *)obdata_cow); + }); break; } case ID_MB: { - op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); - op_node->set_as_entry(); + add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); break; } case ID_CU: { - op_node = add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_curve_eval_geometry(depsgraph, (Curve *)obdata_cow); - }); - op_node->set_as_entry(); + add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_curve_eval_geometry(depsgraph, (Curve *)obdata_cow); + }); /* Make sure objects used for bevel.taper are in the graph. * NOTE: This objects might be not linked to the scene. */ Curve *cu = (Curve *)obdata; @@ -1558,51 +1563,45 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool break; } case ID_LT: { - op_node = add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_lattice_eval_geometry(depsgraph, (Lattice *)obdata_cow); - }); - op_node->set_as_entry(); + add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_lattice_eval_geometry(depsgraph, (Lattice *)obdata_cow); + }); break; } case ID_GD: { /* GPencil evaluation operations. */ - op_node = add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_gpencil_frame_active_set(depsgraph, - (bGPdata *)obdata_cow); - }); - op_node->set_as_entry(); + add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_gpencil_frame_active_set(depsgraph, (bGPdata *)obdata_cow); + }); break; } case ID_HA: { - op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); - op_node->set_as_entry(); + add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); break; } case ID_PT: { - op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); - op_node->set_as_entry(); + add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); break; } case ID_VO: { /* Volume frame update. */ - op_node = add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_volume_eval_geometry(depsgraph, (Volume *)obdata_cow); - }); - op_node->set_as_entry(); + add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_volume_eval_geometry(depsgraph, (Volume *)obdata_cow); + }); break; } default: - BLI_assert(!"Should not happen"); + BLI_assert_msg(0, "Should not happen"); break; } op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE); @@ -1612,10 +1611,22 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool /* Batch cache. */ add_operation_node(obdata, NodeType::BATCH_CACHE, - OperationCode::GEOMETRY_SELECT_UPDATE, + OperationCode::BATCH_UPDATE_SELECT, [obdata_cow](::Depsgraph *depsgraph) { BKE_object_data_select_update(depsgraph, obdata_cow); }); + add_operation_node(obdata, + NodeType::BATCH_CACHE, + OperationCode::BATCH_UPDATE_DEFORM, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_object_data_eval_batch_cache_deform_tag(depsgraph, obdata_cow); + }); + add_operation_node(obdata, + NodeType::BATCH_CACHE, + OperationCode::BATCH_UPDATE_ALL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_object_data_eval_batch_cache_dirty_tag(depsgraph, obdata_cow); + }); } void DepsgraphNodeBuilder::build_armature(bArmature *armature) @@ -1769,7 +1780,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) build_nodetree(group_ntree); } else { - BLI_assert(!"Unknown ID type used for node"); + BLI_assert_msg(0, "Unknown ID type used for node"); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 151e0d844b6..3b2dd44af0d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -289,7 +289,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { * setting the current state. */ Collection *collection_; /* Accumulated flag over the hierarchy of currently building collections. - * Denotes whether all the hierarchy from parent of collection_ to the + * Denotes whether all the hierarchy from parent of `collection_` to the * very root is visible (aka not restricted.). */ bool is_parent_collection_visible_; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index c269ad16824..c63b3d825a0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -326,7 +326,7 @@ void DepsgraphRelationBuilder::add_customdata_mask(Object *object, IDNode *id_node = graph_->find_id_node(&object->id); if (id_node == nullptr) { - BLI_assert(!"ID should always be valid"); + BLI_assert_msg(0, "ID should always be valid"); } else { id_node->customdata_masks |= customdata_masks; @@ -338,7 +338,7 @@ void DepsgraphRelationBuilder::add_special_eval_flag(ID *id, uint32_t flag) { IDNode *id_node = graph_->find_id_node(id); if (id_node == nullptr) { - BLI_assert(!"ID should always be valid"); + BLI_assert_msg(0, "ID should always be valid"); } else { id_node->eval_flags |= flag; @@ -647,7 +647,7 @@ void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_coll /* Only create geometry relations to child objects, if they have a geometry component. */ OperationKey object_geometry_key{ - &cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL}; + &cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT}; if (find_node(object_geometry_key) != nullptr) { add_relation(object_geometry_key, collection_geometry_key, "Collection Geometry"); } @@ -1099,7 +1099,14 @@ void DepsgraphRelationBuilder::build_object_pointcache(Object *object) else { flag = FLAG_GEOMETRY; OperationKey geometry_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); - add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry"); + add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry Eval"); + if (object->data) { + /* Geometry may change, so rebuild the Drawing Cache. */ + OperationKey object_data_batch_all_key( + (ID *)object->data, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_ALL); + add_relation( + point_cache_key, object_data_batch_all_key, "Point Cache -> Batch Update All"); + } } BLI_assert(flag != -1); /* Tag that we did handle that component. */ @@ -1610,7 +1617,7 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) } } } - if (property_entry_key.prop != nullptr && RNA_property_is_idprop(property_entry_key.prop)) { + if (rna_prop_affects_parameters_node(&property_entry_key.ptr, property_entry_key.prop)) { RNAPathKey property_exit_key(property_entry_key.id, property_entry_key.ptr, property_entry_key.prop, @@ -1713,7 +1720,7 @@ void DepsgraphRelationBuilder::build_driver_id_property(ID *id, const char *rna_ if (prop == nullptr) { return; } - if (!RNA_property_is_idprop(prop)) { + if (!rna_prop_affects_parameters_node(&ptr, prop)) { return; } const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); @@ -1868,7 +1875,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) void DepsgraphRelationBuilder::build_particle_systems(Object *object) { TimeSourceKey time_src_key; - OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + OperationKey obdata_ubereval_key( + &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); OperationKey eval_init_key( &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_INIT); OperationKey eval_done_key( @@ -2016,7 +2024,8 @@ void DepsgraphRelationBuilder::build_particle_system_visualization_object(Object { OperationKey psys_key( &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_EVAL, psys->name); - OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + OperationKey obdata_ubereval_key( + &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM); add_relation(dup_ob_key, psys_key, "Particle Object Visualization"); if (draw_object->type == OB_MBALL) { @@ -2073,15 +2082,15 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) /* Get nodes for result of obdata's evaluation, and geometry evaluation * on object. */ ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY); - ComponentKey geom_key(&object->id, NodeType::GEOMETRY); - /* Link components to each other. */ - add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data"); OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + /* Link components to each other. */ + add_relation(obdata_geom_key, obdata_ubereval_key, "Object Geometry Base Data"); + /* Special case: modifiers evaluation queries scene for various things like * data mask to be used. We add relation here to ensure object is never * evaluated prior to Scene's CoW is ready. */ OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); - Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation"); + Relation *rel = add_relation(scene_key, geom_init_key, "CoW Relation"); rel->flag |= RELATION_FLAG_NO_FLUSH; /* Modifiers */ if (object->modifiers.first != nullptr) { @@ -2091,13 +2100,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); if (mti->updateDepsgraph) { - DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); + DepsNodeHandle handle = create_node_handle(geom_init_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); mti->updateDepsgraph(md, &ctx); } if (BKE_object_modifier_use_time(object, md)) { TimeSourceKey time_src_key; - add_relation(time_src_key, obdata_ubereval_key, "Time Source"); + add_relation(time_src_key, geom_init_key, "Time Source"); } } } @@ -2110,13 +2119,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info( (GpencilModifierType)md->type); if (mti->updateDepsgraph) { - DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); + DepsNodeHandle handle = create_node_handle(geom_init_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); mti->updateDepsgraph(md, &ctx, graph_->mode); } if (BKE_object_modifier_gpencil_use_time(object, md)) { TimeSourceKey time_src_key; - add_relation(time_src_key, obdata_ubereval_key, "Time Source"); + add_relation(time_src_key, geom_init_key, "Time Source"); } } } @@ -2128,13 +2137,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) { const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info((ShaderFxType)fx->type); if (fxi->updateDepsgraph) { - DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); + DepsNodeHandle handle = create_node_handle(geom_init_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); fxi->updateDepsgraph(fx, &ctx); } if (BKE_object_shaderfx_use_time(object, fx)) { TimeSourceKey time_src_key; - add_relation(time_src_key, obdata_ubereval_key, "Time Source"); + add_relation(time_src_key, geom_init_key, "Time Source"); } } } @@ -2160,6 +2169,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) add_relation(mom_transform_key, mom_geom_key, "Metaball Motherball Transform -> Geometry"); } else { + ComponentKey geom_key(&object->id, NodeType::GEOMETRY); ComponentKey transform_key(&object->id, NodeType::TRANSFORM); add_relation(geom_key, mom_geom_key, "Metaball Motherball"); add_relation(transform_key, mom_geom_key, "Metaball Motherball"); @@ -2174,9 +2184,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) * Ideally we need to get rid of this relation. */ if (object_particles_depends_on_time(object)) { TimeSourceKey time_key; - OperationKey obdata_ubereval_key( - &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); - add_relation(time_key, obdata_ubereval_key, "Legacy particle time"); + add_relation(time_key, geom_init_key, "Legacy particle time"); } /* Object data data-block. */ build_object_data_geometry_datablock((ID *)object->data); @@ -2198,12 +2206,33 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) add_relation(final_geometry_key, synchronize_key, "Synchronize to Original"); /* Batch cache. */ OperationKey object_data_select_key( - obdata, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE); + obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_SELECT); OperationKey object_select_key( - &object->id, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE); + &object->id, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_SELECT); + add_relation(object_data_select_key, object_select_key, "Data Selection -> Object Selection"); + add_relation(final_geometry_key, + object_select_key, + "Object Geometry -> Select Update", + RELATION_FLAG_NO_FLUSH); + + OperationKey object_data_geom_deform_key( + obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM); + OperationKey object_data_geom_init_key( + obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); + + OperationKey object_data_batch_deform_key( + obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_DEFORM); + OperationKey object_data_batch_all_key( + obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_ALL); + + add_relation(geom_init_key, object_data_batch_all_key, "Object Geometry -> Batch Update All"); + add_relation( - geom_key, object_select_key, "Object Geometry -> Select Update", RELATION_FLAG_NO_FLUSH); + object_data_geom_init_key, object_data_batch_all_key, "Data Init -> Batch Update All"); + add_relation(object_data_geom_deform_key, + object_data_batch_deform_key, + "Data Deform -> Batch Update Deform"); } void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata) @@ -2221,8 +2250,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata) build_shapekeys(key); } /* Link object data evaluation node to exit operation. */ + OperationKey obdata_geom_deform_key( + obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM); + OperationKey obdata_geom_init_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); OperationKey obdata_geom_eval_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); OperationKey obdata_geom_done_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE); + add_relation(obdata_geom_init_key, obdata_geom_eval_key, "ObData Init -> Geom Eval"); + add_relation(obdata_geom_deform_key, obdata_geom_eval_key, "ObData Deform -> Geom Eval"); add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done"); /* Type-specific links. */ const ID_Type id_type = GS(obdata->name); @@ -2314,7 +2348,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata) break; } default: - BLI_assert(!"Should not happen"); + BLI_assert_msg(0, "Should not happen"); break; } } @@ -2497,7 +2531,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) add_relation(group_shading_key, shading_key, "Group Node"); } else { - BLI_assert(!"Unknown ID type used for node"); + BLI_assert_msg(0, "Unknown ID type used for node"); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h index 035d636b977..14ed153832d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h @@ -54,7 +54,7 @@ Relation *DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, } else { if (!op_from) { - /* XXX TODO handle as error or report if needed */ + /* XXX TODO: handle as error or report if needed. */ fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n", description, @@ -67,7 +67,7 @@ Relation *DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, key_from.identifier().c_str()); } if (!op_to) { - /* XXX TODO handle as error or report if needed */ + /* XXX TODO: handle as error or report if needed. */ fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n", description, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 54c51adec66..8e3960e1a15 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -180,7 +180,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, node_identifier.operation_name = ""; node_identifier.operation_name_tag = -1; /* Handling of commonly known scenarios. */ - if (prop != nullptr && RNA_property_is_idprop(prop)) { + if (rna_prop_affects_parameters_node(ptr, prop)) { node_identifier.type = NodeType::PARAMETERS; node_identifier.operation_code = OperationCode::ID_PROPERTY; node_identifier.operation_name = RNA_property_identifier( @@ -397,4 +397,12 @@ RNANodeQueryIDData *RNANodeQuery::ensure_id_data(const ID *id) return id_data.get(); } +bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop) +{ + return prop != nullptr && RNA_property_is_idprop(prop) && + /* ID properties in the geometry nodes modifier don't affect that parameters node. Instead + they affect the modifier and therefore the geometry node directly. */ + !RNA_struct_is_a(ptr->type, &RNA_NodesModifier); +} + } // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h index d03903d508c..24d7f5f3a30 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h @@ -108,5 +108,7 @@ class RNANodeQuery { static bool contains(const char *prop_identifier, const char *rna_path_component); }; +bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop); + } // namespace deg } // namespace blender diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc index 9afae0f2c22..57c6f062611 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -461,7 +461,7 @@ static void deg_debug_graphviz_node_relations(DotExportContext &ctx, const Node dot::DirectedEdge &edge = ctx.digraph.new_edge(dot_tail, dot_head); - /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */ + /* NOTE: without label an id seem necessary to avoid bugs in graphviz/dot. */ edge.attributes.set("id", rel->name); deg_debug_graphviz_relation_color(rel, edge); deg_debug_graphviz_relation_style(rel, edge); diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 6fe7d5f5d8b..4c036417ba0 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -68,7 +68,8 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati scene(scene), view_layer(view_layer), mode(mode), - ctime(BKE_scene_frame_get(scene)), + frame(BKE_scene_frame_get(scene)), + ctime(BKE_scene_ctime_get(scene)), scene_cow(nullptr), is_active(false), is_evaluating(false), @@ -267,7 +268,7 @@ ID *Depsgraph::get_cow_id(const ID *id_orig) const * - Object or mesh has material at a slot which is not used (for * example, object has material slot by materials are set to * object data). */ - // BLI_assert(!"Request for non-existing copy-on-write ID"); + // BLI_assert_msg(0, "Request for non-existing copy-on-write ID"); } return (ID *)id_orig; } diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index ff536c19c05..913b61ca563 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -140,7 +140,9 @@ struct Depsgraph { ViewLayer *view_layer; eEvaluationMode mode; - /* Time at which dependency graph is being or was last evaluated. */ + /* Time at which dependency graph is being or was last evaluated. + * frame is the value before, and ctime the value after time remapping. */ + float frame; float ctime; /* Evaluated version of datablocks we access a lot. diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc index c5e306f3148..3677f80469c 100644 --- a/source/blender/depsgraph/intern/depsgraph_debug.cc +++ b/source/blender/depsgraph/intern/depsgraph_debug.cc @@ -96,7 +96,7 @@ bool DEG_debug_graph_relations_validate(Depsgraph *graph, DEG_graph_build_from_view_layer(temp_depsgraph); if (!DEG_debug_compare(temp_depsgraph, graph)) { fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n"); - BLI_assert(!"This should not happen!"); + BLI_assert_msg(0, "This should not happen!"); valid = false; } DEG_graph_free(temp_depsgraph); diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc index 1ad3fdbc9da..cc7ce871419 100644 --- a/source/blender/depsgraph/intern/depsgraph_eval.cc +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -51,7 +51,7 @@ static void deg_flush_updates_and_refresh(deg::Depsgraph *deg_graph) { /* Update the time on the cow scene. */ if (deg_graph->scene_cow) { - BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime); + BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->frame); } deg::deg_graph_flush_updates(deg_graph); @@ -63,10 +63,12 @@ void DEG_evaluate_on_refresh(Depsgraph *graph) { deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); const Scene *scene = DEG_get_input_scene(graph); - const float ctime = BKE_scene_frame_get(scene); + const float frame = BKE_scene_frame_get(scene); + const float ctime = BKE_scene_ctime_get(scene); - if (ctime != deg_graph->ctime) { + if (deg_graph->frame != frame || ctime != deg_graph->ctime) { deg_graph->tag_time_source(); + deg_graph->frame = frame; deg_graph->ctime = ctime; } @@ -74,10 +76,13 @@ void DEG_evaluate_on_refresh(Depsgraph *graph) } /* Frame-change happened for root scene that graph belongs to. */ -void DEG_evaluate_on_framechange(Depsgraph *graph, float ctime) +void DEG_evaluate_on_framechange(Depsgraph *graph, float frame) { deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); + const Scene *scene = DEG_get_input_scene(graph); + deg_graph->tag_time_source(); - deg_graph->ctime = ctime; + deg_graph->frame = frame; + deg_graph->ctime = BKE_scene_frame_to_ctime(scene, frame); deg_flush_updates_and_refresh(deg_graph); } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc index 8f3aab19e37..a70c0c10de0 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.cc +++ b/source/blender/depsgraph/intern/depsgraph_physics.cc @@ -59,7 +59,7 @@ static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type return DEG_PHYSICS_DYNAMIC_BRUSH; } - BLI_assert(!"Unknown collision modifier type"); + BLI_assert_msg(0, "Unknown collision modifier type"); return DEG_PHYSICS_RELATIONS_NUM; } /* Get ID from an ID type object, in a safe manner. This means that object can be nullptr, @@ -80,7 +80,7 @@ ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collect if (hash == nullptr) { return nullptr; } - /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a + /* NOTE: nullptr is a valid lookup key here as it means that the relation is not bound to a * specific collection. */ ID *collection_orig = DEG_get_original_id(object_id_safe(collection)); return hash->lookup_default(collection_orig, nullptr); @@ -96,7 +96,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph, if (hash == nullptr) { return nullptr; } - /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a + /* NOTE: nullptr is a valid lookup key here as it means that the relation is not bound to a * specific collection. */ ID *collection_orig = DEG_get_original_id(object_id_safe(collection)); return hash->lookup_default(collection_orig, nullptr); diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index b00cae87311..34b33e9a6c0 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -117,7 +117,7 @@ void depsgraph_select_tag_to_component_opcode(const ID *id, } else if (is_selectable_data_id_type(id_type)) { *component_type = NodeType::BATCH_CACHE; - *operation_code = OperationCode::GEOMETRY_SELECT_UPDATE; + *operation_code = OperationCode::BATCH_UPDATE_SELECT; } else { *component_type = NodeType::COPY_ON_WRITE; @@ -168,6 +168,11 @@ void depsgraph_tag_to_component_opcode(const ID *id, break; case ID_RECALC_GEOMETRY: depsgraph_geometry_tag_to_component(id, component_type); + *operation_code = OperationCode::GEOMETRY_EVAL_INIT; + break; + case ID_RECALC_GEOMETRY_DEFORM: + depsgraph_geometry_tag_to_component(id, component_type); + *operation_code = OperationCode::GEOMETRY_EVAL_DEFORM; break; case ID_RECALC_ANIMATION: *component_type = NodeType::ANIMATION; @@ -233,7 +238,7 @@ void depsgraph_tag_to_component_opcode(const ID *id, case ID_RECALC_GEOMETRY_ALL_MODES: case ID_RECALC_ALL: case ID_RECALC_PSYS_ALL: - BLI_assert(!"Should not happen"); + BLI_assert_msg(0, "Should not happen"); break; case ID_RECALC_TAG_FOR_UNDO: break; /* Must be ignored by depsgraph. */ @@ -452,7 +457,7 @@ const char *update_source_as_string(eUpdateSource source) case DEG_UPDATE_SOURCE_VISIBILITY: return "VISIBILITY"; } - BLI_assert(!"Should never happen."); + BLI_assert_msg(0, "Should never happen."); return "UNKNOWN"; } @@ -708,6 +713,8 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) return "GEOMETRY"; case ID_RECALC_GEOMETRY_ALL_MODES: return "GEOMETRY_ALL_MODES"; + case ID_RECALC_GEOMETRY_DEFORM: + return "GEOMETRY_DEFORM"; case ID_RECALC_ANIMATION: return "ANIMATION"; case ID_RECALC_PSYS_REDO: diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 6f35143e28f..915b9fedcec 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -223,7 +223,7 @@ bool need_evaluate_operation_at_stage(DepsgraphEvalState *state, case EvaluationStage::SINGLE_THREADED_WORKAROUND: return true; } - BLI_assert(!"Unhandled evaluation stage, should never happen."); + BLI_assert_msg(0, "Unhandled evaluation stage, should never happen."); return false; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 0d367762b00..346eba5bbc2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -899,7 +899,7 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, done = id_copy_inplace_no_main(id_orig, id_cow); } if (!done) { - BLI_assert(!"No idea how to perform CoW on datablock"); + BLI_assert_msg(0, "No idea how to perform CoW on datablock"); } /* Update pointers to nested ID datablocks. */ DEG_COW_PRINT( diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 1b24e2b7ad2..2cbb0b52e34 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -144,7 +144,10 @@ inline void flush_handle_component_node(IDNode *id_node, * special component where we don't want all operations to be tagged. * * TODO(sergey): Make this a more generic solution. */ - if (!ELEM(comp_node->type, NodeType::PARTICLE_SETTINGS, NodeType::PARTICLE_SYSTEM)) { + if (!ELEM(comp_node->type, + NodeType::PARTICLE_SETTINGS, + NodeType::PARTICLE_SYSTEM, + NodeType::BATCH_CACHE)) { for (OperationNode *op : comp_node->operations) { op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; } diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc index 0d3563ee3de..fee5342df59 100644 --- a/source/blender/depsgraph/intern/node/deg_node.cc +++ b/source/blender/depsgraph/intern/node/deg_node.cc @@ -48,7 +48,7 @@ const char *nodeClassAsString(NodeClass node_class) case NodeClass::OPERATION: return "OPERATION"; } - BLI_assert(!"Unhandled node class, should never happen."); + BLI_assert_msg(0, "Unhandled node class, should never happen."); return "UNKNOWN"; } @@ -121,7 +121,7 @@ const char *nodeTypeAsString(NodeType type) case NodeType::NUM_TYPES: return "SpecialCase"; } - BLI_assert(!"Unhandled node type, should never happen."); + BLI_assert_msg(0, "Unhandled node type, should never happen."); return "UNKNOWN"; } @@ -177,7 +177,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type) case NodeType::SIMULATION: return DEG_SCENE_COMP_PARAMETERS; } - BLI_assert(!"Unhandled node type, not suppsed to happen."); + BLI_assert_msg(0, "Unhandled node type, not suppsed to happen."); return DEG_SCENE_COMP_PARAMETERS; } @@ -253,7 +253,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type) case NodeType::NUM_TYPES: return DEG_OB_COMP_PARAMETERS; } - BLI_assert(!"Unhandled node type, not suppsed to happen."); + BLI_assert_msg(0, "Unhandled node type, not suppsed to happen."); return DEG_OB_COMP_PARAMETERS; } diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index d824fb14718..431bf536b65 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -142,7 +142,7 @@ OperationNode *ComponentNode::get_operation(OperationIDKey key) const "%s: find_operation(%s) failed\n", this->identifier().c_str(), key.identifier().c_str()); - BLI_assert(!"Request for non-existing operation, should not happen"); + BLI_assert_msg(0, "Request for non-existing operation, should not happen"); return nullptr; } return node; @@ -181,7 +181,7 @@ OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op, OperationIDKey key(opcode, name, name_tag); operations_map->add(key, op_node); - /* set backlink */ + /* Set back-link. */ op_node->owner = this; } else { @@ -190,7 +190,7 @@ OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op, this->identifier().c_str(), op_node->identifier().c_str(), op_node); - BLI_assert(!"Should not happen!"); + BLI_assert_msg(0, "Should not happen!"); } /* attach extra data */ diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 688afe141e9..2b1ebc663fe 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -53,7 +53,7 @@ const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state) case DEG_ID_LINKED_DIRECTLY: return "DIRECTLY"; } - BLI_assert(!"Unhandled linked state, should never happen."); + BLI_assert_msg(0, "Unhandled linked state, should never happen."); return "UNKNOWN"; } diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 7e57467f905..d98486b83a8 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -98,6 +98,8 @@ const char *operationCodeAsString(OperationCode opcode) /* Geometry. */ case OperationCode::GEOMETRY_EVAL_INIT: return "GEOMETRY_EVAL_INIT"; + case OperationCode::GEOMETRY_EVAL_DEFORM: + return "GEOMETRY_EVAL_DEFORM"; case OperationCode::GEOMETRY_EVAL: return "GEOMETRY_EVAL"; case OperationCode::GEOMETRY_EVAL_DONE: @@ -160,8 +162,12 @@ const char *operationCodeAsString(OperationCode opcode) case OperationCode::FILE_CACHE_UPDATE: return "FILE_CACHE_UPDATE"; /* Batch cache. */ - case OperationCode::GEOMETRY_SELECT_UPDATE: - return "GEOMETRY_SELECT_UPDATE"; + case OperationCode::BATCH_UPDATE_SELECT: + return "BATCH_UPDATE_SELECT"; + case OperationCode::BATCH_UPDATE_DEFORM: + return "BATCH_UPDATE_DEFORM"; + case OperationCode::BATCH_UPDATE_ALL: + return "BATCH_UPDATE_ALL"; /* Masks. */ case OperationCode::MASK_ANIMATION: return "MASK_ANIMATION"; @@ -205,7 +211,7 @@ const char *operationCodeAsString(OperationCode opcode) case OperationCode::SIMULATION_EVAL: return "SIMULATION_EVAL"; } - BLI_assert(!"Unhandled operation code, should never happen."); + BLI_assert_msg(0, "Unhandled operation code, should never happen."); return "UNKNOWN"; } diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index a17186da941..b0130d03c69 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -100,7 +100,11 @@ enum class OperationCode { /* Initialize evaluation of the geometry. Is an entry operation of geometry * component. */ GEOMETRY_EVAL_INIT, - /* Evaluate the whole geometry, including modifiers. */ + /* Evaluate the geometry, including modifiers, and update only batches that + * are affected by deform operations. */ + GEOMETRY_EVAL_DEFORM, + /* Evaluate the geometry, including modifiers, but don't update the batch + * cache. */ GEOMETRY_EVAL, /* Evaluation of geometry is completely done. */ GEOMETRY_EVAL_DONE, @@ -178,7 +182,9 @@ enum class OperationCode { WORLD_UPDATE, /* Batch caches. -------------------------------------------------------- */ - GEOMETRY_SELECT_UPDATE, + BATCH_UPDATE_SELECT, + BATCH_UPDATE_DEFORM, + BATCH_UPDATE_ALL, /* Masks. --------------------------------------------------------------- */ MASK_ANIMATION, diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 4f68c3fdc7e..ad154704d2c 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -51,16 +51,36 @@ set(INC set(SRC intern/draw_cache.c + intern/draw_cache_extract_mesh.cc intern/draw_cache_extract_mesh_extractors.c intern/draw_cache_extract_mesh_render_data.c - intern/draw_cache_extract_mesh.cc intern/mesh_extractors/extract_mesh_ibo_edituv.cc intern/mesh_extractors/extract_mesh_ibo_fdots.cc + intern/mesh_extractors/extract_mesh_ibo_lines.cc intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc - intern/mesh_extractors/extract_mesh_ibo_lines.cc intern/mesh_extractors/extract_mesh_ibo_points.cc intern/mesh_extractors/extract_mesh_ibo_tris.cc + intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc + intern/mesh_extractors/extract_mesh_vbo_edit_data.cc + intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc + intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc + intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc + intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc + intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc + intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc + intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc + intern/mesh_extractors/extract_mesh_vbo_lnor.cc + intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc + intern/mesh_extractors/extract_mesh_vbo_orco.cc + intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc + intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc + intern/mesh_extractors/extract_mesh_vbo_select_idx.cc + intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc + intern/mesh_extractors/extract_mesh_vbo_tan.cc + intern/mesh_extractors/extract_mesh_vbo_uv.cc + intern/mesh_extractors/extract_mesh_vbo_vcol.cc + intern/mesh_extractors/extract_mesh_vbo_weights.cc intern/draw_cache_impl_curve.cc intern/draw_cache_impl_displist.c intern/draw_cache_impl_gpencil.c @@ -185,8 +205,8 @@ set(SRC intern/draw_manager_profiling.h intern/draw_manager_testing.h intern/draw_manager_text.h - intern/draw_view.h intern/draw_shader.h + intern/draw_view.h intern/smaa_textures.h engines/basic/basic_engine.h engines/eevee/eevee_engine.h @@ -495,6 +515,8 @@ if(WITH_GTESTS) set(TEST_SRC tests/draw_testing.cc tests/shaders_test.cc + + tests/draw_testing.hh ) set(TEST_INC "../../../intern/ghost/" diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 88fd823bc72..9d4f7865c32 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -22,7 +22,7 @@ #include "DRW_render.h" -#include "draw_color_management.h" /* TODO remove dependency */ +#include "draw_color_management.h" /* TODO: remove dependency. */ #include "BLI_rand.h" @@ -189,7 +189,7 @@ static void eevee_cache_finish(void *vedata) /* As renders in an HDR offscreen buffer, we need draw everything once * during the background pass. This way the other drawing callback between * the background and the scene pass are visible. - * Note: we could break it up in two passes using some depth test + * NOTE: we could break it up in two passes using some depth test * to reduce the fillrate */ static void eevee_draw_scene(void *vedata) { @@ -481,7 +481,7 @@ static void eevee_render_to_image(void *vedata, time -= shuttertime; break; default: - BLI_assert(!"Invalid motion blur position enum!"); + BLI_assert_msg(0, "Invalid motion blur position enum!"); break; } diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index cdd66759308..9a85037ac77 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -75,7 +75,7 @@ (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_X) * \ (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y) -/* TODO should be replace by a more elegant alternative. */ +/* TODO: should be replace by a more elegant alternative. */ extern void DRW_opengl_context_enable(void); extern void DRW_opengl_context_disable(void); @@ -165,7 +165,7 @@ typedef struct EEVEE_LightBake { bool own_resources; /** If the light-cache was created for baking, it's first owned by the baker. */ bool own_light_cache; - /** ms. delay the start of the baking to not slowdown interactions (TODO remove) */ + /** ms. delay the start of the baking to not slowdown interactions (TODO: remove). */ int delay; /** Scene frame to bake. */ int frame; @@ -715,7 +715,7 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake) * by the DRW mutex. */ lbake->lcache = eevee->light_cache_data; - /* TODO validate irradiance and reflection cache independently... */ + /* TODO: validate irradiance and reflection cache independently... */ if (!EEVEE_lightcache_validate( lbake->lcache, lbake->cube_len, lbake->ref_cube_res, lbake->grid_len, lbake->irr_size)) { eevee->light_cache_data = lbake->lcache = NULL; @@ -764,7 +764,7 @@ wmJob *EEVEE_lightbake_job_create(struct wmWindowManager *wm, if (old_lbake && (old_lbake->view_layer_input == view_layer) && (old_lbake->bmain == bmain)) { lbake = MEM_callocN(sizeof(EEVEE_LightBake), "EEVEE_LightBake"); /* Cannot reuse depsgraph for now because we cannot get the update from the - * main database directly. TODO reuse depsgraph and only update positions. */ + * main database directly. TODO: reuse depsgraph and only update positions. */ /* lbake->depsgraph = old_lbake->depsgraph; */ lbake->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER); @@ -838,7 +838,7 @@ void EEVEE_lightbake_job_data_free(void *custom_data) { EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data; - /* TODO reuse depsgraph. */ + /* TODO: reuse depsgraph. */ /* if (lbake->own_resources) { */ DEG_graph_free(lbake->depsgraph); /* } */ @@ -923,7 +923,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb stl->g_data->background_alpha = 1.0f; stl->g_data->render_timesteps = 1; - /* XXX TODO remove this. This is in order to make the init functions work. */ + /* XXX TODO: remove this. This is in order to make the init functions work. */ if (DRW_view_default_get() == NULL) { float winmat[4][4], viewmat[4][4]; unit_m4(viewmat); @@ -1010,7 +1010,7 @@ static void eevee_lightbake_render_world_sample(void *ved, void *user_data) float clamp = scene_eval->eevee.gi_glossy_clamp; float filter_quality = scene_eval->eevee.gi_filter_quality; - /* TODO do this once for the whole bake when we have independent DRWManagers. */ + /* TODO: do this once for the whole bake when we have independent DRWManagers. */ eevee_lightbake_cache_create(vedata, lbake); sldata->common_data.ray_type = EEVEE_RAY_GLOSSY; @@ -1133,7 +1133,7 @@ static void eevee_lightbake_render_grid_sample(void *ved, void *user_data) /* Use the previous bounce for rendering this bounce. */ SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx.tex); - /* TODO do this once for the whole bake when we have independent DRWManagers. + /* TODO: do this once for the whole bake when we have independent DRWManagers. * Warning: Some of the things above require this. */ eevee_lightbake_cache_create(vedata, lbake); @@ -1210,7 +1210,7 @@ static void eevee_lightbake_render_probe_sample(void *ved, void *user_data) float clamp = scene_eval->eevee.gi_glossy_clamp; float filter_quality = scene_eval->eevee.gi_filter_quality; - /* TODO do this once for the whole bake when we have independent DRWManagers. */ + /* TODO: do this once for the whole bake when we have independent DRWManagers. */ eevee_lightbake_cache_create(vedata, lbake); /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */ @@ -1420,7 +1420,7 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float /* HACK: Sleep to delay the first rendering operation * that causes a small freeze (caused by VBO generation) * because this step is locking at this moment. */ - /* TODO remove this. */ + /* TODO: remove this. */ if (lbake->delay) { PIL_sleep_ms(lbake->delay); } diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index e2e865bcfad..8598655477f 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -59,7 +59,7 @@ static struct { /* *********** FUNCTIONS *********** */ -/* TODO find a better way than this. This does not support dupli objects if +/* TODO: find a better way than this. This does not support dupli objects if * the original object is hidden. */ bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data) { @@ -94,11 +94,11 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref) EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *fx = stl->effects; - /* XXX TODO OPTIMIZATION: This is a complete waist of texture memory. + /* XXX TODO: OPTIMIZATION: This is a complete waist of texture memory. * Instead of allocating each planar probe for each viewport, * only alloc them once using the biggest viewport resolution. */ - /* TODO get screen percentage from layer setting */ + /* TODO: get screen percentage from layer setting. */ // const DRWContextState *draw_ctx = DRW_context_state_get(); // ViewLayer *view_layer = draw_ctx->view_layer; int screen_divider = 1; @@ -1133,7 +1133,7 @@ void EEVEE_lightbake_filter_visibility(EEVEE_ViewLayerData *sldata, EEVEE_LightProbesInfo *pinfo = sldata->probes; LightCache *light_cache = vedata->stl->g_data->light_cache; - pinfo->samples_len = 512.0f; /* TODO refine */ + pinfo->samples_len = 512.0f; /* TODO: refine. */ pinfo->shres = vis_size; pinfo->visibility_range = vis_range; pinfo->visibility_blur = vis_blur; diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index e23a5a81169..afaf604322c 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -88,7 +88,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) /* Make illumination power constant */ if (la->type == LA_AREA) { power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */ - 0.8f; /* XXX : Empirical, Fit cycles power */ + 0.8f; /* XXX: Empirical, Fit cycles power. */ if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { /* Scale power to account for the lower area of the ellipse compared to the surrounding * rectangle. */ @@ -99,7 +99,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI); /* `1/(4*(r^2)*(Pi^2))` */ /* for point lights (a.k.a radius == 0.0) */ - // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */ + // power = M_PI * M_PI * 0.78; /* XXX: Empirical, Fit cycles power. */ } else { /* LA_SUN */ power = 1.0f / (evli->radius * evli->radius * M_PI); diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index a9998b33b7e..f4dc553e982 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -205,7 +205,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, stl->lookdev_lightcache = EEVEE_lightcache_create( 1, 1, cube_res, 8, (int[3]){grid_res, grid_res, 1}); - /* XXX: Fix memleak. TODO find out why. */ + /* XXX: Fix memleak. TODO: find out why. */ MEM_SAFE_FREE(stl->lookdev_cube_mips); /* We do this to use a special light cache for lookdev. diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 7dd3449ad6e..9ecb737192e 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -70,7 +70,7 @@ typedef struct EeveeMaterialCache { /* *********** FUNCTIONS *********** */ -/* XXX TODO define all shared resources in a shared place without duplication */ +/* XXX TODO: define all shared resources in a shared place without duplication. */ struct GPUTexture *EEVEE_materials_get_util_tex(void) { return e_data.util_tex; @@ -691,7 +691,7 @@ static EeveeMaterialCache material_transparent(EEVEE_Data *vedata, } { /* Shading */ - int ssr_id = -1; /* TODO transparent SSR */ + int ssr_id = -1; /* TODO: transparent SSR. */ int mat_options = VAR_MAT_MESH | VAR_MAT_BLEND; SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT); GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); @@ -866,7 +866,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, continue; } - /* XXX TODO rewrite this to include the dupli objects. + /* XXX TODO: rewrite this to include the dupli objects. * This means we cannot exclude dupli objects from reflections!!! */ EEVEE_ObjectEngineData *oedata = NULL; if ((ob->base_flag & BASE_FROM_DUPLI) == 0) { diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index ab297620afe..f51b4fa0127 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -44,12 +44,12 @@ struct RenderLayer; extern struct DrawEngineType draw_engine_eevee_type; /* Minimum UBO is 16384 bytes */ -#define MAX_PROBE 128 /* TODO : find size by dividing UBO max size by probe data size */ -#define MAX_GRID 64 /* TODO : find size by dividing UBO max size by grid data size */ -#define MAX_PLANAR 16 /* TODO : find size by dividing UBO max size by grid data size */ -#define MAX_LIGHT 128 /* TODO : find size by dividing UBO max size by light data size */ +#define MAX_PROBE 128 /* TODO: find size by dividing UBO max size by probe data size. */ +#define MAX_GRID 64 /* TODO: find size by dividing UBO max size by grid data size. */ +#define MAX_PLANAR 16 /* TODO: find size by dividing UBO max size by grid data size. */ +#define MAX_LIGHT 128 /* TODO: find size by dividing UBO max size by light data size. */ #define MAX_CASCADE_NUM 4 -#define MAX_SHADOW 128 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */ +#define MAX_SHADOW 128 /* TODO: Make this depends on #GL_MAX_ARRAY_TEXTURE_LAYERS. */ #define MAX_SHADOW_CASCADE 8 #define MAX_SHADOW_CUBE (MAX_SHADOW - MAX_CASCADE_NUM * MAX_SHADOW_CASCADE) #define MAX_BLOOM_STEP 16 @@ -238,7 +238,7 @@ typedef struct EEVEE_PlanarReflection { float clip_edge_y_pos, clip_edge_y_neg; float facing_scale, facing_bias, clipsta, pad; float reflectionmat[4][4]; /* Used for sampling the texture. */ - float mtx[4][4]; /* Not used in shader. TODO move elsewhere. */ + float mtx[4][4]; /* Not used in shader. TODO: move elsewhere. */ } EEVEE_PlanarReflection; /* --------------------------------------- */ @@ -680,7 +680,7 @@ typedef struct EEVEE_GeometryMotionData { int use_deform; struct GPUBatch *batch; /* Batch for time = t. */ - struct GPUVertBuf *vbo[2]; /* Vbo for time = t +/- step. */ + struct GPUVertBuf *vbo[2]; /* VBO for time = t +/- step. */ } EEVEE_GeometryMotionData; /* ************ EFFECTS DATA ************* */ @@ -1000,7 +1000,7 @@ typedef struct EEVEE_PrivateData { struct DRWShadingGroup *shadow_accum_shgrp; struct DRWCallBuffer *planar_display_shgrp; struct GHash *material_hash; - float background_alpha; /* TODO find a better place for this. */ + float background_alpha; /* TODO: find a better place for this. */ /* Chosen lightcache: can come from Lookdev or the viewlayer. */ struct LightCache *light_cache; /* For planar probes */ diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index aaa087f9eb4..d214409c458 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -114,7 +114,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * /* XXX overriding viewport size. Simplify things but is not really 100% safe. */ DRW_render_viewport_size_set(final_res); - /* TODO 32 bit depth */ + /* TODO: 32 bit depth. */ DRW_texture_ensure_fullscreen_2d(&dtxl->depth, GPU_DEPTH24_STENCIL8, 0); DRW_texture_ensure_fullscreen_2d(&txl->color, GPU_RGBA32F, DRW_TEX_FILTER); diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 5ada53ab98c..aa42deb13fa 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -23,7 +23,7 @@ #include "DRW_engine.h" #include "DRW_render.h" -#include "draw_color_management.h" /* TODO remove dependency. */ +#include "draw_color_management.h" /* TODO: remove dependency. */ #include "BKE_global.h" /* for G.debug_value */ diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 7af0f60748b..17cc1a46e23 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -76,7 +76,7 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const int divisor = (effects->reflection_trace_full) ? 1 : 2; int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor}; const int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - const bool high_qual_input = true; /* TODO dither low quality input */ + const bool high_qual_input = true; /* TODO: dither low quality input. */ const eGPUTextureFormat format = (high_qual_input) ? GPU_RGBA16F : GPU_RGBA8; tracing_res[0] = max_ii(1, tracing_res[0]); diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index a4e4352ac16..56ae7185b51 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -1439,7 +1439,7 @@ static void eevee_material_post_eval(GPUMaterial *mat, const bool is_mesh = (options & VAR_MAT_MESH) != 0; /* Force geometry usage if GPU_BARYCENTRIC_DIST or GPU_BARYCENTRIC_TEXCO are used. - * Note: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */ + * NOTE: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */ if (!is_hair && is_mesh && GPU_material_flag_get(mat, GPU_MATFLAG_BARYCENTRIC) && *geom_code == NULL) { *geom_code = e_data.surface_geom_barycentric; @@ -1493,7 +1493,7 @@ static struct GPUMaterial *eevee_material_get_ex( return mat; } -/* Note: Compilation is not deferred. */ +/* NOTE: Compilation is not deferred. */ struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options) { Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() : diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 5060c209b8b..ee1a6652809 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -193,7 +193,7 @@ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob) static bool sphere_bbox_intersect(const BoundSphere *bs, const EEVEE_BoundBox *bb) { /* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */ - /* TODO test speed with AABB vs Sphere. */ + /* TODO: test speed with AABB vs Sphere. */ bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius); bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius); bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius); diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c index 6cb4b39fafa..22ee821933c 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c +++ b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c @@ -112,7 +112,7 @@ static void frustum_min_bounding_sphere(const float corners[8][3], } } - /* TODO try to reduce the radius further by moving the center. + /* TODO: try to reduce the radius further by moving the center. * Remember we need a __stable__ solution! */ /* Try to reduce float imprecision leading to shimmering. */ diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 129822ed8a9..b7bcd127859 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -144,7 +144,7 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), /* Clear texture. * Due to the late initialization of the SSS it can happen that the `taa_current_sample` is * already higher than one. This is noticeable when loading a file that has the diffuse light - * pass in look dev mode active. `texture_created` will make sure that newly created textures + * pass in look-dev mode active. `texture_created` will make sure that newly created textures * are cleared. */ if (effects->taa_current_sample == 1 || texture_created) { const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -198,7 +198,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, /* Limit of 8 bit stencil buffer. ID 255 is refraction. */ if (effects->sss_surface_count >= 254) { - /* TODO : display message. */ + /* TODO: display message. */ printf("Error: Too many different Subsurface shader in the scene.\n"); return; } diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index e30f5d52d56..b03172a1270 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -197,7 +197,7 @@ void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, const dou } /* Update the matrices based on the current sample. - * Note: `DRW_MAT_PERS` and `DRW_MAT_VIEW` needs to read the original matrices. */ + * NOTE: `DRW_MAT_PERS` and `DRW_MAT_VIEW` needs to read the original matrices. */ void EEVEE_temporal_sampling_update_matrices(EEVEE_Data *vedata) { EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; @@ -407,7 +407,7 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata) GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT); /* Do reprojection for noise reduction */ - /* TODO : do AA jitter if in only render view. */ + /* TODO: do AA jitter if in only render view. */ if (!DRW_state_is_image_render() && (effects->enabled_effects & EFFECT_TAA_REPROJECT) != 0 && stl->g_data->valid_taa_history) { GPU_framebuffer_bind(effects->target_buffer); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 56c5b367f7e..47e8aeeb6e2 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -129,7 +129,7 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->vol_coord_scale[2] = 1.0f / viewport_size[0]; common_data->vol_coord_scale[3] = 1.0f / viewport_size[1]; - /* TODO compute snap to maxZBuffer for clustered rendering */ + /* TODO: compute snap to maxZBuffer for clustered rendering. */ if ((common_data->vol_tex_size[0] != tex_size[0]) || (common_data->vol_tex_size[1] != tex_size[1]) || (common_data->vol_tex_size[2] != tex_size[2])) { @@ -554,8 +554,8 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, } } - /* TODO Reduce to number of slices intersecting. */ - /* TODO Preemptive culling. */ + /* TODO: Reduce to number of slices intersecting. */ + /* TODO: Preemptive culling. */ DRW_shgroup_call_procedural_triangles(grp, ob, sldata->common_data.vol_tex_size[2]); vedata->stl->effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl index 4fcfac36376..e0f52338914 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl @@ -116,7 +116,7 @@ vec3 sample_uniform_cone(vec3 rand, float angle) vec3 sample_uniform_cone(vec3 rand, float angle, vec3 N, vec3 T, vec3 B) { vec3 Ht = sample_uniform_cone(rand, angle); - /* TODO pdf? */ + /* TODO: pdf? */ return tangent_to_world(Ht, N, T, B); } diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl index da34b221104..e5b68637563 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl @@ -324,7 +324,7 @@ float dof_coc_max_slight_focus(float coc1, float coc2) struct DofGatherData { vec4 color; float weight; - float dist; /* TODO remove */ + float dist; /* TODO: remove. */ /* For scatter occlusion. */ float coc; float coc_sqr; diff --git a/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl index 6f2619127e3..7689e730bf3 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl @@ -40,9 +40,9 @@ vec4 ssr_get_scene_color_and_mask(vec3 hit_vP, int planar_index, float mip) } else { /* Find hit position in previous frame. */ - /* TODO Combine matrices. */ + /* TODO: Combine matrices. */ vec3 hit_P = transform_point(ViewMatrixInverse, hit_vP); - /* TODO real reprojection with motion vectors, etc... */ + /* TODO: real reprojection with motion vectors, etc... */ uv = project_point(pastViewProjectionMatrix, hit_P).xy * 0.5 + 0.5; } diff --git a/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl index cd574c6c9fd..2f1efd588f7 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl @@ -89,7 +89,7 @@ void main() if (fade > 0.5) { /* Find view vector / reflection plane intersection. */ - /* TODO optimize, use view space for all. */ + /* TODO: optimize, use view space for all. */ vec3 P_plane = line_plane_intersect(P, V, pd.pl_plane_eq); vP = transform_point(ViewMatrix, P_plane); diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl index b79cd17c567..58bbb825043 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -23,7 +23,7 @@ layout(location = 0) out vec4 sssRadiance; void main(void) { - vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */ + vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO: precompute. */ vec2 uvs = gl_FragCoord.xy * pixel_size; vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb; float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w; diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl index 165aed2a46f..3c49caf11a9 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl @@ -85,7 +85,7 @@ void main() color_history.rgb = clip_to_aabb(color_history.rgb, min_col.rgb, max_col.rgb, avg_col.rgb); /* Luminance weighting. */ - /* TODO correct luminance */ + /* TODO: correct luminance. */ float lum0 = dot(color.rgb, vec3(0.333)); float lum1 = dot(color_history.rgb, vec3(0.333)); float diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2)); diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl index 97b31a972e3..ee48c468630 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl @@ -35,8 +35,8 @@ vec3 sss_profile(float s) float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector) { float power, falloff; - /* XXX : Removing Area Power. */ - /* TODO : put this out of the shader. */ + /* XXX: Removing Area Power. */ + /* TODO: put this out of the shader. */ if (ld.l_type >= AREA_RECT) { power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); if (ld.l_type == AREA_ELLIPSE) { @@ -134,7 +134,7 @@ vec3 light_translucent(LightData ld, vec3 P, vec3 N, vec4 l_vector, vec2 rand, f /* Size of a texel in world space. * FIXME This is only correct if l_right is the same right vector used for shadowmap creation. * This won't work if the shadow matrix is rotated (soft shadows). - * TODO precompute */ + * TODO: precompute. */ float unit_world_in_uv_space = length(mat3(scascade(data_id).shadowmat[int(id)]) * ld.l_right); float dx_scale = 2.0 * ofs.x / unit_world_in_uv_space; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl index d06ad553ca4..c9af2753baa 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl @@ -1,7 +1,7 @@ #pragma BLENDER_REQUIRE(common_view_lib.glsl) -/* XXX TODO fix code duplication */ +/* XXX TODO: fix code duplication. */ struct CubeData { vec4 position_type; vec4 attenuation_fac_type; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index a648e7a8b26..84626eac4cf 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -192,7 +192,7 @@ vec3 probe_evaluate_planar(int id, PlanarData pd, vec3 P, vec3 N, vec3 V, float vec3 point_on_plane = line_plane_intersect(P, V, pd.pl_plane_eq); /* How far the pixel is from the plane. */ - float ref_depth = 1.0; /* TODO parameter */ + float ref_depth = 1.0; /* TODO: parameter. */ /* Compute distorded reflection vector based on the distance to the reflected object. * In other words find intersection between reflection vector and the sphere center @@ -278,7 +278,7 @@ vec3 probe_evaluate_grid(GridData gd, vec3 P, vec3 N, vec3 localpos) float ws_dist_point_to_cell = length(ws_point_to_cell); vec3 ws_light = ws_point_to_cell / ws_dist_point_to_cell; - /* Smooth backface test */ + /* Smooth back-face test. */ float weight = saturate(dot(ws_light, N)); /* Precomputed visibility */ diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl index 2f1fd0ce5f8..dc98a00a1cd 100644 --- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -176,7 +176,7 @@ float sample_cube_shadow(int shadow_id, vec3 P) float dist = max(sd(shadow_id).sh_near, max_v3(abs(cubevec)) - sd(shadow_id).sh_bias); dist = buffer_depth(true, dist, sd(shadow_id).sh_far, sd(shadow_id).sh_near); /* Manual Shadow Cube Layer indexing. */ - /* TODO Shadow Cube Array. */ + /* TODO: Shadow Cube Array. */ float face = cubeFaceIndexEEVEE(cubevec); vec2 coord = cubeFaceCoordEEVEE(cubevec, face, shadowCubeTexture); /* tex_id == data_id for cube shadowmap */ diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index f1476e4f2c4..73c4b521b05 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -101,7 +101,7 @@ struct RayTraceParameters { }; /* Returns true on hit. */ -/* TODO fclem remove the backface check and do it the SSR resolve code. */ +/* TODO(fclem): remove the back-face check and do it the SSR resolve code. */ bool raytrace(Ray ray, RayTraceParameters params, const bool discard_backface, @@ -151,7 +151,7 @@ bool raytrace(Ray ray, /* ... and above it with the added thickness. */ hit = hit && (delta > ss_p.z - ss_p.w || abs(delta) < abs(ssray.direction.z * stride * 2.0)); } - /* Discard backface hits. */ + /* Discard back-face hits. */ hit = hit && !(discard_backface && prev_delta < 0.0); /* Reject hit if background. */ hit = hit && (depth_sample != 1.0); diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl index 1d52dfeab26..a563291bb90 100644 --- a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl @@ -63,7 +63,7 @@ vec4 screen_space_refraction(vec3 vP, vec3 N, vec3 V, float ior, float roughness float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos; /* Empirical fit for refraction. */ - /* TODO find a better fit or precompute inside the LUT. */ + /* TODO: find a better fit or precompute inside the LUT. */ cone_tan *= 0.5 * fast_sqrt(f0_from_ior((ior < 1.0) ? 1.0 / ior : ior)); float cone_footprint = hit_dist * cone_tan; diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl index b2d8a383809..5226da57a06 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl @@ -2,7 +2,7 @@ #pragma BLENDER_REQUIRE(common_view_lib.glsl) #ifdef MESH_SHADER -/* TODO tight slices */ +/* TODO: tight slices. */ layout(triangles) in; layout(triangle_strip, max_vertices = 3) out; #else /* World */ @@ -17,7 +17,7 @@ flat out int slice; RESOURCE_ID_VARYING #ifdef MESH_SHADER -/* TODO tight slices */ +/* TODO: tight slices. */ void main() { gl_Layer = slice = int(vPos[0].z); diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index adb21540afb..89ee3f1b293 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -314,7 +314,7 @@ static DrawEngineType draw_engine_external_type = { NULL, }; -/* Note: currently unused, +/* NOTE: currently unused, * we should not register unless we want to see this when debugging the view. */ RenderEngineType DRW_engine_viewport_external_type = { diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 1921055c3d7..d3a0c40fae5 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -262,7 +262,7 @@ void GPENCIL_cache_init(void *ved) pd->sbuffer_gpd = gpd; pd->sbuffer_stroke = DRW_cache_gpencil_sbuffer_stroke_data_get(pd->obact); pd->sbuffer_layer = BKE_gpencil_layer_active_get(pd->sbuffer_gpd); - pd->do_fast_drawing = false; /* TODO option */ + pd->do_fast_drawing = false; /* TODO: option. */ } } } @@ -640,13 +640,13 @@ void GPENCIL_cache_populate(void *ved, Object *ob) } } - BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL, - ob, - gpencil_layer_cache_populate, - gpencil_stroke_cache_populate, - &iter, - do_onion, - pd->cfra); + BKE_gpencil_visible_stroke_advanced_iter(is_final_render ? pd->view_layer : NULL, + ob, + gpencil_layer_cache_populate, + gpencil_stroke_cache_populate, + &iter, + do_onion, + pd->cfra); gpencil_drawcall_flush(&iter); diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c index 2522a445d8e..395d50fbc6b 100644 --- a/source/blender/draw/engines/image/image_engine.c +++ b/source/blender/draw/engines/image/image_engine.c @@ -31,6 +31,7 @@ #include "DNA_camera_types.h" #include "DNA_screen_types.h" +#include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "ED_image.h" @@ -116,7 +117,7 @@ static void space_image_gpu_texture_get(Image *image, const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf); if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { if (ibuf->zbuf) { - BLI_assert(!"Integer based depth buffers not supported"); + BLI_assert_msg(0, "Integer based depth buffers not supported"); } else if (ibuf->zbuf_float) { *r_gpu_texture = GPU_texture_create_2d( @@ -222,19 +223,30 @@ static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f); } else if ((sima_flag & SI_SHOW_R) != 0) { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING; + draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f); } else if ((sima_flag & SI_SHOW_G) != 0) { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING; + draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f); } else if ((sima_flag & SI_SHOW_B) != 0) { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING; + draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f); } else /* RGB */ { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } } } if (space_type == SPACE_NODE) { @@ -248,19 +260,30 @@ static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f); } else if ((snode->flag & SNODE_SHOW_R) != 0) { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING; + draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f); } else if ((snode->flag & SNODE_SHOW_G) != 0) { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING; + draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f); } else if ((snode->flag & SNODE_SHOW_B) != 0) { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING; + draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f); } else /* RGB */ { - draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + if (IMB_alpha_affects_rgb(ibuf)) { + draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA; + } } } diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 0e350ea5a68..9d15f0e176d 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -37,6 +37,7 @@ #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_deform.h" #include "BKE_modifier.h" #include "DEG_depsgraph_query.h" @@ -699,7 +700,7 @@ static void drw_shgroup_bone_ik_spline_lines(ArmatureDrawContext *ctx, /* -------------------------------------------------------------------- */ /** \name Drawing Theme Helpers * - * Note, this section is duplicate of code in 'drawarmature.c'. + * \note this section is duplicate of code in 'drawarmature.c'. * * \{ */ @@ -1036,7 +1037,7 @@ static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel * float(*disp_mat)[4]; float(*disp_tail_mat)[4]; - /* TODO : This should be moved to depsgraph or armature refresh + /* TODO: This should be moved to depsgraph or armature refresh * and not be tight to the draw pass creation. * This would refresh armature without invalidating the draw cache */ if (pchan) { @@ -1200,9 +1201,9 @@ static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pc float(*bone_mat)[4]; short bbone_segments; - /* TODO : This should be moved to depsgraph or armature refresh + /* TODO: This should be moved to depsgraph or armature refresh * and not be tight to the draw pass creation. - * This would refresh armature without invalidating the draw cache */ + * This would refresh armature without invalidating the draw cache. */ if (pchan) { length = pchan->bone->length; xwidth = pchan->bone->xwidth; @@ -1268,7 +1269,7 @@ static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan) float(*disp_tail_mat)[4]; float rot_mat[3][3]; - /* See TODO above */ + /* See TODO: above. */ mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, PCHAN_CUSTOM_BONE_LENGTH(pchan)); bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat; disp_mat = pchan->disp_mat; @@ -2040,7 +2041,8 @@ static void draw_armature_pose(ArmatureDrawContext *ctx) const Object *obact_orig = DEG_get_original_object(draw_ctx->obact); - LISTBASE_FOREACH (bDeformGroup *, dg, &obact_orig->defbase) { + const ListBase *defbase = BKE_object_defgroup_list(obact_orig); + LISTBASE_FOREACH (const bDeformGroup *, dg, defbase) { if (dg->flag & DG_LOCK_WEIGHT) { pchan = BKE_pose_channel_find_name(ob->pose, dg->name); diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index 7639911286f..a7ed6c777e8 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -26,6 +26,7 @@ #include "DNA_mesh_types.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "draw_cache_impl.h" diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c index 01ab47ac1de..c2b130163e8 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_uv.c +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c @@ -24,6 +24,7 @@ #include "draw_cache_impl.h" #include "draw_manager_text.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_image.h" #include "BKE_layer.h" diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index 81b07b49784..235104245cc 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -200,7 +200,7 @@ static void OVERLAY_cache_init(void *vedata) case CTX_MODE_OBJECT: break; default: - BLI_assert(!"Draw mode invalid"); + BLI_assert_msg(0, "Draw mode invalid"); break; } OVERLAY_antialiasing_cache_init(vedata); diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index b70c71de188..f5be9c846d1 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -928,7 +928,7 @@ static void camera_view3d_reconstruction(OVERLAY_ExtraCallBuffers *cb, const float *bundle_color; if (track->flag & TRACK_CUSTOMCOLOR) { /* Meh, hardcoded srgb transform here. */ - /* TODO change the actual DNA color to be linear. */ + /* TODO: change the actual DNA color to be linear. */ srgb_to_linearrgb_v3_v3(bundle_color_custom, track->color); bundle_color = bundle_color_custom; } diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c index aa26aa47faa..5c03d70d7be 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.c +++ b/source/blender/draw/engines/overlay/overlay_gpencil.c @@ -431,7 +431,7 @@ static void OVERLAY_gpencil_color_names(Object *ob) const DRWContextState *draw_ctx = DRW_context_state_get(); int cfra = DEG_get_ctime(draw_ctx->depsgraph); - BKE_gpencil_visible_stroke_iter( + BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra); } diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c index a2c3b5bf4aa..e3f01d968ae 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.c +++ b/source/blender/draw/engines/overlay/overlay_outline.c @@ -36,7 +36,7 @@ /* Returns the normal plane in NDC space. */ static void gpencil_depth_plane(Object *ob, float r_plane[4]) { - /* TODO put that into private data. */ + /* TODO: put that into private data. */ float viewinv[4][4]; DRW_view_viewmat_get(NULL, viewinv, true); float *camera_z_axis = viewinv[2]; @@ -92,7 +92,7 @@ void OVERLAY_outline_init(OVERLAY_Data *vedata) DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); if (DRW_state_is_fbo()) { - /* TODO only alloc if needed. */ + /* TODO: only alloc if needed. */ DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0); DRW_texture_ensure_fullscreen_2d(&txl->outlines_id_tx, GPU_R16UI, 0); @@ -263,13 +263,13 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob) gpencil_depth_plane(ob, iter.plane); } - BKE_gpencil_visible_stroke_iter(NULL, - ob, - gpencil_layer_cache_populate, - gpencil_stroke_cache_populate, - &iter, - false, - pd->cfra); + BKE_gpencil_visible_stroke_advanced_iter(NULL, + ob, + gpencil_layer_cache_populate, + gpencil_stroke_cache_populate, + &iter, + false, + pd->cfra); } static void OVERLAY_outline_volume(OVERLAY_PrivateData *pd, Object *ob) diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index a48b46a61fc..03bfaf56f24 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -314,7 +314,7 @@ typedef struct OVERLAY_PrivateData { DRWView *view_edit_text; DRWView *view_reference_images; - /** TODO get rid of this. */ + /** TODO: get rid of this. */ ListBase smoke_domains; ListBase bg_movie_clips; @@ -333,8 +333,8 @@ typedef struct OVERLAY_PrivateData { bool xray_enabled; bool xray_enabled_and_not_wire; float xray_opacity; - short v3d_flag; /* TODO move to View3DOverlay */ - short v3d_gridflag; /* TODO move to View3DOverlay */ + short v3d_flag; /* TODO: move to #View3DOverlay. */ + short v3d_gridflag; /* TODO: move to #View3DOverlay. */ int cfra; DRWState clipping_state; OVERLAY_ShadingData shdata; diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index c9c26e3faaa..7a7ae9a921b 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -1726,7 +1726,7 @@ OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) { {"boneStart", DRW_ATTR_FLOAT, 3}, {"boneEnd", DRW_ATTR_FLOAT, 3}, - {"wireColor", DRW_ATTR_FLOAT, 4}, /* TODO uchar color */ + {"wireColor", DRW_ATTR_FLOAT, 4}, /* TODO: uchar color. */ {"boneColor", DRW_ATTR_FLOAT, 4}, {"headColor", DRW_ATTR_FLOAT, 4}, {"tailColor", DRW_ATTR_FLOAT, 4}, diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl index c204949cc45..67d172fbd01 100644 --- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl @@ -105,7 +105,7 @@ void main() float dist_raw = texelFetch(lineTex, center_texel, 0).b; float dist = decode_line_dist(dist_raw); - /* TODO Opti: use textureGather */ + /* TODO: Opti: use textureGather. */ vec4 neightbor_col0 = texelFetchOffset(colorTex, center_texel, 0, ivec2(1, 0)); vec4 neightbor_col1 = texelFetchOffset(colorTex, center_texel, 0, ivec2(-1, 0)); vec4 neightbor_col2 = texelFetchOffset(colorTex, center_texel, 0, ivec2(0, 1)); diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl index 45ebad0aafe..ddc6328e6a2 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl @@ -36,7 +36,7 @@ void main() /* This is slow and run per vertex, but it's still faster than * doing it per instance on CPU and sending it on via instance attribute. */ mat3 normal_mat = transpose(inverse(mat3(model_mat))); - /* TODO FIX: there is still a problem with this vector + /* TODO: FIX: there is still a problem with this vector * when the bone is scaled or in persp mode. But it's * barely visible at the outline corners. */ ssNor = normalize(normal_world_to_view(normal_mat * snor).xy); diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl index 17e8d0da5d9..26796c82f66 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl @@ -9,8 +9,8 @@ layout(location = 1) out vec4 lineOutput; void main() { - /* Manual backface cullling.. Not ideal for performance - * but needed for view clarity in xray mode and support + /* Manual back-face culling. Not ideal for performance + * but needed for view clarity in X-ray mode and support * for inverted bone matrices. */ if ((inverted == 1) == gl_FrontFacing) { discard; diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl index cb70a3b433c..b241a1f0568 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl @@ -11,7 +11,7 @@ out vec4 fillColor; out vec4 outlineColor; out vec4 radii; -/* TODO Theme? */ +/* TODO: Theme? */ const vec4 pinned_col = vec4(1.0, 0.0, 0.0, 1.0); void main() diff --git a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl index 1c54076f3ea..df10f3f7ae2 100644 --- a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl @@ -279,7 +279,7 @@ void main() vec2 line_start, line_end; vec2 line_ofs; bvec4 extra_edges, extra_edges2; - /* TODO simplify this branching hell. */ + /* TODO: simplify this branching hell. */ switch (edge_case) { /* Straight lines. */ case YPOS: diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl index 282799e1660..b89cd821b37 100644 --- a/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl @@ -40,7 +40,7 @@ void main() /* Don't outline if concave edge. */ /* That would hide a lot of non useful edge but it flickers badly. - * TODO revisit later... */ + * TODO: revisit later... */ // if (dot(n0, v13) > 0.01) // return; diff --git a/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl index 9d102bd4295..052ad2a7f36 100644 --- a/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl @@ -14,7 +14,7 @@ void main() vec3 world_pos = point_object_to_world(pos); gl_Position = point_world_to_ndc(world_pos); /* Add offset in Z to avoid zfighting and render selected wires on top. */ - /* TODO scale this bias using znear and zfar range. */ + /* TODO: scale this bias using znear and zfar range. */ gl_Position.z -= (is_select ? 2e-4 : 1e-4); if (is_hidden) { diff --git a/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl index d5a42d2d309..6a937d846c4 100644 --- a/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl @@ -16,7 +16,7 @@ void main() vec3 world_pos = point_object_to_world(pos); gl_Position = point_world_to_ndc(world_pos); /* Add offset in Z to avoid zfighting and render selected wires on top. */ - /* TODO scale this bias using znear and zfar range. */ + /* TODO: scale this bias using znear and zfar range. */ gl_Position.z -= (is_select ? 2e-4 : 1e-4); if (is_hidden) { diff --git a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl index 0b827601f8e..174b31b6816 100644 --- a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl @@ -33,7 +33,7 @@ const vec3 corners[4] = vec3[4](vec3(0.0, 0.2, -0.5), const int indices[12] = int[12](0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3); /* Straight Port from BKE_defvert_weight_to_rgb() - * TODO port this to a color ramp. */ + * TODO: port this to a color ramp. */ vec3 weight_to_color(float weight) { vec3 r_rgb = vec3(0.0); diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index c9c4a2076ef..86b4a0ac727 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -373,7 +373,7 @@ DrawEngineType draw_engine_select_type = { NULL, }; -/* Note: currently unused, we may want to register so we can see this when debugging the view. */ +/* NOTE: currently unused, we may want to register so we can see this when debugging the view. */ RenderEngineType DRW_engine_viewport_select_type = { NULL, diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl index d0d52c8485b..9038aae533b 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl @@ -43,7 +43,7 @@ void cavity_compute(vec2 screenco, /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */ offset *= 0.5; - /* Note. Putting noise usage here to put some ALU after texture fetch. */ + /* NOTE: Putting noise usage here to put some ALU after texture fetch. */ vec2 rotX = noise.rg; vec2 rotY = vec2(-rotX.y, rotX.x); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl index 6e10a656fc1..c5b2ce0fd99 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl @@ -24,7 +24,7 @@ void main() workbench_float_pair_decode(mat_data.a, roughness, metallic); #ifdef V3D_LIGHTING_MATCAP - /* When using matcaps, mat_data.a is the backface sign. */ + /* When using matcaps, mat_data.a is the back-face sign. */ N = (mat_data.a > 0.0) ? N : -N; fragColor.rgb = get_matcap_lighting(base_color, N, I); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl index 8f6940a6062..92d5df1a13a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl @@ -394,7 +394,7 @@ void main() vec2 pixel_size = 0.5 / vec2(textureSize(halfResColorTex, 0).xy); vec2 uv = gl_FragCoord.xy * pixel_size; - /* TODO MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH */ + /* TODO: MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH. */ float depth = texelFetch(sceneDepthTex, ivec2(gl_FragCoord.xy), 0).r; float zdepth = linear_depth(depth); float coc = calculate_coc(zdepth); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index 9bd49bb84f8..48102b4dcca 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -198,7 +198,7 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction) scattering *= exp(clamp(log(shadows) * densityScale * 0.1, -2.5, 0.0)) * M_PI; # ifdef VOLUME_SMOKE - /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */ + /* 800 is arbitrary and here to mimic old viewport. TODO: make it a parameter. */ scattering += emission.rgb * emission.a * 800.0; # endif #endif @@ -247,7 +247,7 @@ vec4 volume_integration(vec3 ray_ori, vec3 ray_dir, float ray_inc, float ray_max void main() { #ifdef VOLUME_SLICE - /* Manual depth test. TODO remove. */ + /* Manual depth test. TODO: remove. */ float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; if (gl_FragCoord.z >= depth) { discard; diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c index 10a782c9987..8206add7412 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c +++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c @@ -247,7 +247,7 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata) GPU_ATTACHMENT_TEXTURE(wpd->smaa_weight_tx), }); - /* TODO could be shared for all viewports. */ + /* TODO: could be shared for all viewports. */ if (txl->smaa_search_tx == NULL) { txl->smaa_search_tx = GPU_texture_create_2d( "smaa_search", SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 1, GPU_R8, NULL); diff --git a/source/blender/draw/engines/workbench/workbench_effect_cavity.c b/source/blender/draw/engines/workbench/workbench_effect_cavity.c index 199abe8cb2b..b294b9a62ca 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_cavity.c +++ b/source/blender/draw/engines/workbench/workbench_effect_cavity.c @@ -31,7 +31,7 @@ #include "BLI_rand.h" -#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */ +#include "../eevee/eevee_lut.h" /* TODO: find somewhere to share blue noise Table. */ #include "workbench_engine.h" #include "workbench_private.h" diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 0d7f2e67598..e9d6763fbe9 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -460,7 +460,7 @@ void workbench_cache_finish(void *ved) workbench_update_material_ubos(wpd); - /* TODO don't free reuse next redraw. */ + /* TODO: don't free reuse next redraw. */ for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < WORKBENCH_DATATYPE_MAX; k++) { diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 800d1085505..aaa1a5a6ff6 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -126,7 +126,7 @@ BLI_INLINE void workbench_material_get_image( break; } default: - BLI_assert(!"Node type not supported by workbench"); + BLI_assert_msg(0, "Node type not supported by workbench"); } } } diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c index 99d945c311e..3386d9b6390 100644 --- a/source/blender/draw/engines/workbench/workbench_shadow.c +++ b/source/blender/draw/engines/workbench/workbench_shadow.c @@ -65,7 +65,7 @@ static void workbench_shadow_update(WORKBENCH_PrivateData *wpd) const float up[3] = {0.0f, 0.0f, 1.0f}; unit_m4(wpd->shadow_mat); - /* TODO fix singularity. */ + /* TODO: fix singularity. */ copy_v3_v3(wpd->shadow_mat[2], wpd->shadow_direction_ws); cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up); normalize_v3(wpd->shadow_mat[0]); diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c index edeb17cd9a4..ad855cb284c 100644 --- a/source/blender/draw/engines/workbench/workbench_transparent.c +++ b/source/blender/draw/engines/workbench/workbench_transparent.c @@ -46,7 +46,7 @@ void workbench_transparent_engine_init(WORKBENCH_Data *data) DrawEngineType *owner = (DrawEngineType *)&workbench_transparent_engine_init; /* Reuse same format as opaque pipeline to reuse the textures. */ - /* Note: Floating point texture is required for the reveal_tex as it is used for + /* NOTE: Floating point texture is required for the reveal_tex as it is used for * the alpha accumulation component (see accumulation shader for more explanation). */ const eGPUTextureFormat accum_tex_format = GPU_RGBA16F; const eGPUTextureFormat reveal_tex_format = NORMAL_ENCODING_ENABLED() ? GPU_RG16F : GPU_RGBA32F; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 5d5a506c1e7..f5b95ac97ff 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -82,7 +82,7 @@ typedef struct DRWShadingGroup DRWShadingGroup; typedef struct DRWUniform DRWUniform; typedef struct DRWView DRWView; -/* TODO Put it somewhere else? */ +/* TODO: Put it somewhere else? */ typedef struct BoundSphere { float center[3], radius; } BoundSphere; @@ -91,7 +91,7 @@ typedef struct BoundSphere { typedef char DRWViewportEmptyList; #define DRW_VIEWPORT_LIST_SIZE(list) \ - (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : ((sizeof(list)) / sizeof(void *))) + (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : (sizeof(list) / sizeof(void *))) /* Unused members must be either pass list or 'char *' when not used. */ #define DRW_VIEWPORT_DATA_SIZE(ty) \ @@ -490,7 +490,7 @@ void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup, uint write_mask, uint reference, uint compare_mask); -/* TODO remove this function. Obsolete version. mask is actually reference value. */ +/* TODO: remove this function. Obsolete version. mask is actually reference value. */ void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask); /* Issue a clear command. */ diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index d55da3ed83b..a2e8dc20907 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -580,7 +580,7 @@ static void circle_dashed_verts( } } -/* XXX TODO move that 1 unit cube to more common/generic place? */ +/* XXX TODO: move that 1 unit cube to more common/generic place? */ static const float bone_box_verts[8][3] = { {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, -1.0f}, @@ -762,7 +762,7 @@ GPUBatch *DRW_cache_normal_arrow_get(void) GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); GPU_vertbuf_data_alloc(vbo, 2); - /* TODO real arrow. For now, it's a line positioned in the vertex shader. */ + /* TODO: real arrow. For now, it's a line positioned in the vertex shader. */ SHC.drw_normal_arrow = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); } @@ -802,7 +802,7 @@ GPUBatch *DRW_cache_object_all_edges_get(Object *ob) case OB_MESH: return DRW_cache_mesh_all_edges_get(ob); - /* TODO, should match 'DRW_cache_object_surface_get' */ + /* TODO: should match #DRW_cache_object_surface_get. */ default: return NULL; } @@ -2181,7 +2181,7 @@ GPUBatch *DRW_cache_bone_envelope_solid_get(void) float lat = 0.0f; float co1[3], co2[3]; - /* Note: the poles are duplicated on purpose, to restart the strip. */ + /* NOTE: the poles are duplicated on purpose, to restart the strip. */ /* 1st sphere */ for (int j = 0; j < lat_res; j++, lat += lat_inc) { @@ -2627,7 +2627,7 @@ GPUBatch *DRW_cache_bone_dof_sphere_get(void) pz = z; } } - /* TODO allocate right count from the beginning. */ + /* TODO: allocate right count from the beginning. */ GPU_vertbuf_data_resize(vbo, v); SHC.drw_bone_dof_sphere = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); @@ -3274,8 +3274,8 @@ GPUBatch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight) Lattice *lt = ob->data; int actdef = -1; - if (use_weight && ob->defbase.first && lt->editlatt->latt->dvert) { - actdef = ob->actdef - 1; + if (use_weight && !BLI_listbase_is_empty(<->vertex_group_names) && lt->editlatt->latt->dvert) { + actdef = lt->vertex_group_active_index - 1; } return DRW_lattice_batch_cache_get_all_edges(lt, use_weight, actdef); @@ -3599,7 +3599,7 @@ void drw_batch_cache_generate_requested(Object *ob) } DRW_curve_batch_cache_create_requested(ob, scene); break; - /* TODO all cases */ + /* TODO: all cases. */ default: break; } @@ -3625,7 +3625,7 @@ void DRW_batch_cache_free_old(Object *ob, int ctime) DRW_mesh_batch_cache_free_old(mesh_eval, ctime); } break; - /* TODO all cases */ + /* TODO: all cases. */ default: break; } diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index be61b0a9baf..a0694a08f0b 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -36,7 +36,7 @@ typedef struct DRW_MeshWeightState { short flags; char alert_mode; - /* Set of all selected bones for Multipaint. */ + /* Set of all selected bones for Multi-paint. */ bool *defgroup_sel; /* [defgroup_len] */ int defgroup_sel_count; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 344150014ed..6d71b01b7e0 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -76,27 +76,23 @@ struct ExtractorRunData { class ExtractorRunDatas : public Vector<ExtractorRunData> { public: - void filter_into(ExtractorRunDatas &result, eMRIterType iter_type) const + void filter_into(ExtractorRunDatas &result, eMRIterType iter_type, const bool is_mesh) const { for (const ExtractorRunData &data : *this) { const MeshExtract *extractor = data.extractor; - if ((iter_type & MR_ITER_LOOPTRI) && extractor->iter_looptri_bm) { - BLI_assert(extractor->iter_looptri_mesh); + if ((iter_type & MR_ITER_LOOPTRI) && *(&extractor->iter_looptri_bm + is_mesh)) { result.append(data); continue; } - if ((iter_type & MR_ITER_POLY) && extractor->iter_poly_bm) { - BLI_assert(extractor->iter_poly_mesh); + if ((iter_type & MR_ITER_POLY) && *(&extractor->iter_poly_bm + is_mesh)) { result.append(data); continue; } - if ((iter_type & MR_ITER_LEDGE) && extractor->iter_ledge_bm) { - BLI_assert(extractor->iter_ledge_mesh); + if ((iter_type & MR_ITER_LEDGE) && *(&extractor->iter_ledge_bm + is_mesh)) { result.append(data); continue; } - if ((iter_type & MR_ITER_LVERT) && extractor->iter_lvert_bm) { - BLI_assert(extractor->iter_lvert_mesh); + if ((iter_type & MR_ITER_LVERT) && *(&extractor->iter_lvert_bm + is_mesh)) { result.append(data); continue; } @@ -427,7 +423,7 @@ BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr, return; } - extractors->filter_into(range_data.extractors, iter_type); + extractors->filter_into(range_data.extractors, iter_type, is_mesh); BLI_task_parallel_range(0, stop, &range_data, func, settings); } diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c index 42cd571b089..e813f006351 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c @@ -25,29 +25,10 @@ #include "MEM_guardedalloc.h" -#include "atomic_ops.h" - #include "DNA_object_types.h" -#include "BLI_edgehash.h" -#include "BLI_jitter_2d.h" -#include "BLI_kdopbvh.h" -#include "BLI_string.h" - -#include "BKE_bvhutils.h" -#include "BKE_deform.h" -#include "BKE_editmesh.h" -#include "BKE_editmesh_bvh.h" -#include "BKE_editmesh_cache.h" -#include "BKE_editmesh_tangent.h" -#include "BKE_mesh.h" -#include "BKE_mesh_tangent.h" -#include "BKE_paint.h" - #include "ED_uvedit.h" -#include "GPU_capabilities.h" - #include "draw_cache_extract_mesh_private.h" #include "draw_cache_impl.h" @@ -120,1577 +101,13 @@ const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor, /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Position and Vertex Normal - * \{ */ - -typedef struct PosNorLoop { - float pos[3]; - GPUPackedNormal nor; -} PosNorLoop; - -typedef struct MeshExtract_PosNor_Data { - PosNorLoop *vbo_data; - GPUNormal *normals; -} MeshExtract_PosNor_Data; - -static void extract_pos_nor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* WARNING Adjust #PosNorLoop struct accordingly. */ - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_alias_add(&format, "vnor"); - } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - - /* Pack normals per vert, reduce amount of computation. */ - MeshExtract_PosNor_Data *data = tls_data; - data->vbo_data = (PosNorLoop *)GPU_vertbuf_get_data(vbo); - data->normals = MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__); - - /* Quicker than doing it for each loop. */ - if (mr->extract_type == MR_EXTRACT_BMESH) { - BMIter iter; - BMVert *eve; - int v; - BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) { - data->normals[v].low = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve)); - } - } - else { - const MVert *mv = mr->mvert; - for (int v = 0; v < mr->vert_len; v++, mv++) { - data->normals[v].low = GPU_normal_convert_i10_s3(mv->no); - } - } -} - -static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - MeshExtract_PosNor_Data *data = _data; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - PosNorLoop *vert = &data->vbo_data[l_index]; - copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v)); - vert->nor = data->normals[BM_elem_index_get(l_iter->v)].low; - vert->nor.w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int UNUSED(mp_index), - void *_data) -{ - MeshExtract_PosNor_Data *data = _data; - - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - - PosNorLoop *vert = &data->vbo_data[ml_index]; - const MVert *mv = &mr->mvert[ml->v]; - copy_v3_v3(vert->pos, mv->co); - vert->nor = data->normals[ml->v].low; - /* Flag for paint mode overlay. */ - if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || - ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && - (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { - vert->nor.w = -1; - } - else if (mv->flag & SELECT) { - vert->nor.w = 1; - } - else { - vert->nor.w = 0; - } - } -} - -static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr, - const BMEdge *eed, - const int ledge_index, - void *_data) -{ - MeshExtract_PosNor_Data *data = _data; - - int l_index = mr->loop_len + ledge_index * 2; - PosNorLoop *vert = &data->vbo_data[l_index]; - copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); - copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); - vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low; - vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low; -} - -static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr, - const MEdge *med, - const int ledge_index, - void *_data) -{ - MeshExtract_PosNor_Data *data = _data; - const int ml_index = mr->loop_len + ledge_index * 2; - PosNorLoop *vert = &data->vbo_data[ml_index]; - copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); - copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); - vert[0].nor = data->normals[med->v1].low; - vert[1].nor = data->normals[med->v2].low; -} - -static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr, - const BMVert *eve, - const int lvert_index, - void *_data) -{ - MeshExtract_PosNor_Data *data = _data; - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - - const int l_index = offset + lvert_index; - PosNorLoop *vert = &data->vbo_data[l_index]; - copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); - vert->nor = data->normals[BM_elem_index_get(eve)].low; -} - -static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, - const MVert *mv, - const int lvert_index, - void *_data) -{ - MeshExtract_PosNor_Data *data = _data; - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - - const int ml_index = offset + lvert_index; - const int v_index = mr->lverts[lvert_index]; - PosNorLoop *vert = &data->vbo_data[ml_index]; - copy_v3_v3(vert->pos, mv->co); - vert->nor = data->normals[v_index].low; -} - -static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *_data) -{ - MeshExtract_PosNor_Data *data = _data; - MEM_freeN(data->normals); -} - -const MeshExtract extract_pos_nor = { - .init = extract_pos_nor_init, - .iter_poly_bm = extract_pos_nor_iter_poly_bm, - .iter_poly_mesh = extract_pos_nor_iter_poly_mesh, - .iter_ledge_bm = extract_pos_nor_iter_ledge_bm, - .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh, - .iter_lvert_bm = extract_pos_nor_iter_lvert_bm, - .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh, - .finish = extract_pos_nor_finish, - .data_type = 0, - .data_size = sizeof(MeshExtract_PosNor_Data), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Position and High Quality Vertex Normal - * \{ */ - -typedef struct PosNorHQLoop { - float pos[3]; - short nor[4]; -} PosNorHQLoop; - -typedef struct MeshExtract_PosNorHQ_Data { - PosNorHQLoop *vbo_data; - GPUNormal *normals; -} MeshExtract_PosNorHQ_Data; - -static void extract_pos_nor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* WARNING Adjust #PosNorHQLoop struct accordingly. */ - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_alias_add(&format, "vnor"); - } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - - /* Pack normals per vert, reduce amount of computation. */ - MeshExtract_PosNorHQ_Data *data = tls_data; - data->vbo_data = (PosNorHQLoop *)GPU_vertbuf_get_data(vbo); - data->normals = MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__); - - /* Quicker than doing it for each loop. */ - if (mr->extract_type == MR_EXTRACT_BMESH) { - BMIter iter; - BMVert *eve; - int v; - BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) { - normal_float_to_short_v3(data->normals[v].high, bm_vert_no_get(mr, eve)); - } - } - else { - const MVert *mv = mr->mvert; - for (int v = 0; v < mr->vert_len; v++, mv++) { - copy_v3_v3_short(data->normals[v].high, mv->no); - } - } -} - -static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - MeshExtract_PosNorHQ_Data *data = _data; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - PosNorHQLoop *vert = &data->vbo_data[l_index]; - copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v)); - copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l_iter->v)].high); - - BMFace *efa = l_iter->f; - vert->nor[3] = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int UNUSED(mp_index), - void *_data) -{ - MeshExtract_PosNorHQ_Data *data = _data; - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - - PosNorHQLoop *vert = &data->vbo_data[ml_index]; - const MVert *mv = &mr->mvert[ml->v]; - copy_v3_v3(vert->pos, mv->co); - copy_v3_v3_short(vert->nor, data->normals[ml->v].high); - - /* Flag for paint mode overlay. */ - if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || - ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && - (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { - vert->nor[3] = -1; - } - else if (mv->flag & SELECT) { - vert->nor[3] = 1; - } - else { - vert->nor[3] = 0; - } - } -} - -static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr, - const BMEdge *eed, - const int ledge_index, - void *_data) -{ - MeshExtract_PosNorHQ_Data *data = _data; - int l_index = mr->loop_len + ledge_index * 2; - PosNorHQLoop *vert = &data->vbo_data[l_index]; - copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); - copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); - copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high); - vert[0].nor[3] = 0; - copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high); - vert[1].nor[3] = 0; -} - -static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr, - const MEdge *med, - const int ledge_index, - void *_data) -{ - MeshExtract_PosNorHQ_Data *data = _data; - const int ml_index = mr->loop_len + ledge_index * 2; - PosNorHQLoop *vert = &data->vbo_data[ml_index]; - copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); - copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); - copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high); - vert[0].nor[3] = 0; - copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high); - vert[1].nor[3] = 0; -} - -static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr, - const BMVert *eve, - const int lvert_index, - void *_data) -{ - MeshExtract_PosNorHQ_Data *data = _data; - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - - const int l_index = offset + lvert_index; - PosNorHQLoop *vert = &data->vbo_data[l_index]; - copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); - copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high); - vert->nor[3] = 0; -} - -static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr, - const MVert *mv, - const int lvert_index, - void *_data) -{ - MeshExtract_PosNorHQ_Data *data = _data; - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - - const int ml_index = offset + lvert_index; - const int v_index = mr->lverts[lvert_index]; - PosNorHQLoop *vert = &data->vbo_data[ml_index]; - copy_v3_v3(vert->pos, mv->co); - copy_v3_v3_short(vert->nor, data->normals[v_index].high); - vert->nor[3] = 0; -} - -static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *_data) -{ - MeshExtract_PosNorHQ_Data *data = _data; - MEM_freeN(data->normals); -} - -const MeshExtract extract_pos_nor_hq = { - .init = extract_pos_nor_hq_init, - .iter_poly_bm = extract_pos_nor_hq_iter_poly_bm, - .iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh, - .iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm, - .iter_ledge_mesh = extract_pos_nor_hq_iter_ledge_mesh, - .iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm, - .iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh, - .finish = extract_pos_nor_hq_finish, - .data_type = 0, - .data_size = sizeof(MeshExtract_PosNorHQ_Data), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor)}; - -/** \} */ -/* ---------------------------------------------------------------------- */ -/** \name Extract HQ Loop Normal - * \{ */ - -typedef struct gpuHQNor { - short x, y, z, w; -} gpuHQNor; - -static void extract_lnor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_alias_add(&format, "lnor"); - } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - *(gpuHQNor **)tls_data = GPU_vertbuf_get_data(vbo); -} - -static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *data) -{ - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - if (mr->loop_normals) { - normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]); - } - else { - if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { - normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_vert_no_get(mr, l_iter->v)); - } - else { - normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_face_no_get(mr, f)); - } - } - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *data) -{ - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; - if (mr->loop_normals) { - normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); - } - else if (mp->flag & ME_SMOOTH) { - copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no); - } - else { - normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]); - } - - /* Flag for paint mode overlay. - * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. - * In paint mode it will use the un-mapped data to draw the wire-frame. */ - if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && - (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { - lnor_data->w = -1; - } - else if (mp->flag & ME_FACE_SEL) { - lnor_data->w = 1; - } - else { - lnor_data->w = 0; - } - } -} - -const MeshExtract extract_lnor_hq = { - .init = extract_lnor_hq_init, - .iter_poly_bm = extract_lnor_hq_iter_poly_bm, - .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh, - .data_type = MR_DATA_LOOP_NOR, - .data_size = sizeof(gpuHQNor *), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor), -}; - -/** \} */ -/* ---------------------------------------------------------------------- */ -/** \name Extract Loop Normal - * \{ */ - -static void extract_lnor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_alias_add(&format, "lnor"); - } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - *(GPUPackedNormal **)tls_data = GPU_vertbuf_get_data(vbo); -} - -static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *data) -{ - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - if (mr->loop_normals) { - (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); - } - else { - if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { - (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3( - bm_vert_no_get(mr, l_iter->v)); - } - else { - (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f)); - } - } - (*(GPUPackedNormal **)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *data) -{ - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; - if (mr->loop_normals) { - *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); - } - else if (mp->flag & ME_SMOOTH) { - *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no); - } - else { - *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]); - } - - /* Flag for paint mode overlay. - * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. - * In paint mode it will use the un-mapped data to draw the wire-frame. */ - if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && - (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { - lnor_data->w = -1; - } - else if (mp->flag & ME_FACE_SEL) { - lnor_data->w = 1; - } - else { - lnor_data->w = 0; - } - } -} - -const MeshExtract extract_lnor = { - .init = extract_lnor_init, - .iter_poly_bm = extract_lnor_iter_poly_bm, - .iter_poly_mesh = extract_lnor_iter_poly_mesh, - .data_type = MR_DATA_LOOP_NOR, - .data_size = sizeof(GPUPackedNormal *), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract UV layers - * \{ */ - -static void extract_uv_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - GPUVertFormat format = {0}; - GPU_vertformat_deinterleave(&format); - - CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - uint32_t uv_layers = cache->cd_used.uv; - /* HACK to fix T68857 */ - if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { - int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); - if (layer != -1) { - uv_layers |= (1 << layer); - } - } - - for (int i = 0; i < MAX_MTFACE; i++) { - if (uv_layers & (1 << i)) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); - - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - /* UV layer name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "u%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - /* Auto layer name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); - GPU_vertformat_alias_add(&format, attr_name); - /* Active render layer name. */ - if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) { - GPU_vertformat_alias_add(&format, "u"); - } - /* Active display layer name. */ - if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) { - GPU_vertformat_alias_add(&format, "au"); - /* Alias to `pos` for edit uvs. */ - GPU_vertformat_alias_add(&format, "pos"); - } - /* Stencil mask uv layer name. */ - if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) { - GPU_vertformat_alias_add(&format, "mu"); - } - } - } - - int v_len = mr->loop_len; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - /* VBO will not be used, only allocate minimum of memory. */ - v_len = 1; - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, v_len); - - float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo); - for (int i = 0; i < MAX_MTFACE; i++) { - if (uv_layers & (1 << i)) { - if (mr->extract_type == MR_EXTRACT_BMESH) { - int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i); - BMIter f_iter; - BMFace *efa; - BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs); - memcpy(uv_data, luv->uv, sizeof(*uv_data)); - uv_data++; - } while ((l_iter = l_iter->next) != l_first); - } - } - else { - MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) { - memcpy(uv_data, layer_data->uv, sizeof(*uv_data)); - } - } - } - } -} - -const MeshExtract extract_uv = { - .init = extract_uv_init, - .data_type = 0, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Tangent layers - * \{ */ - -static void extract_tan_ex_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - GPUVertBuf *vbo, - const bool do_hq) -{ - GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10; - GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT; - - GPUVertFormat format = {0}; - GPU_vertformat_deinterleave(&format); - - CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; - uint32_t tan_layers = cache->cd_used.tan; - float(*orco)[3] = CustomData_get_layer(cd_vdata, CD_ORCO); - bool orco_allocated = false; - const bool use_orco_tan = cache->cd_used.tan_orco != 0; - - int tan_len = 0; - char tangent_names[MAX_MTFACE][MAX_CUSTOMDATA_LAYER_NAME]; - - for (int i = 0; i < MAX_MTFACE; i++) { - if (tan_layers & (1 << i)) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - /* Tangent layer name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode); - /* Active render layer name. */ - if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) { - GPU_vertformat_alias_add(&format, "t"); - } - /* Active display layer name. */ - if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) { - GPU_vertformat_alias_add(&format, "at"); - } - - BLI_strncpy(tangent_names[tan_len++], layer_name, MAX_CUSTOMDATA_LAYER_NAME); - } - } - if (use_orco_tan && orco == NULL) { - /* If `orco` is not available compute it ourselves */ - orco_allocated = true; - orco = MEM_mallocN(sizeof(*orco) * mr->vert_len, __func__); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - BMesh *bm = mr->bm; - for (int v = 0; v < mr->vert_len; v++) { - const BMVert *eve = BM_vert_at_index(bm, v); - /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords. - * not the distorted ones. */ - copy_v3_v3(orco[v], eve->co); - } - } - else { - const MVert *mv = mr->mvert; - for (int v = 0; v < mr->vert_len; v++, mv++) { - copy_v3_v3(orco[v], mv->co); - } - } - BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0); - } - - /* Start Fresh */ - CustomData loop_data; - CustomData_reset(&loop_data); - if (tan_len != 0 || use_orco_tan) { - short tangent_mask = 0; - bool calc_active_tangent = false; - if (mr->extract_type == MR_EXTRACT_BMESH) { - BKE_editmesh_loop_tangent_calc(mr->edit_bmesh, - calc_active_tangent, - tangent_names, - tan_len, - mr->poly_normals, - mr->loop_normals, - orco, - &loop_data, - mr->loop_len, - &tangent_mask); - } - else { - BKE_mesh_calc_loop_tangent_ex(mr->mvert, - mr->mpoly, - mr->poly_len, - mr->mloop, - mr->mlooptri, - mr->tri_len, - cd_ldata, - calc_active_tangent, - tangent_names, - tan_len, - mr->poly_normals, - mr->loop_normals, - orco, - &loop_data, - mr->loop_len, - &tangent_mask); - } - } - - if (use_orco_tan) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name(&loop_data, CD_TANGENT, 0); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode); - GPU_vertformat_alias_add(&format, "t"); - GPU_vertformat_alias_add(&format, "at"); - } - - if (orco_allocated) { - MEM_SAFE_FREE(orco); - } - - int v_len = mr->loop_len; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - /* VBO will not be used, only allocate minimum of memory. */ - v_len = 1; - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, v_len); - - if (do_hq) { - short(*tan_data)[4] = (short(*)[4])GPU_vertbuf_get_data(vbo); - for (int i = 0; i < tan_len; i++) { - const char *name = tangent_names[i]; - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named( - &loop_data, CD_TANGENT, name); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { - normal_float_to_short_v3(*tan_data, layer_data[ml_index]); - (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; - tan_data++; - } - } - if (use_orco_tan) { - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { - normal_float_to_short_v3(*tan_data, layer_data[ml_index]); - (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; - tan_data++; - } - } - } - else { - GPUPackedNormal *tan_data = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo); - for (int i = 0; i < tan_len; i++) { - const char *name = tangent_names[i]; - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named( - &loop_data, CD_TANGENT, name); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { - *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]); - tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2; - tan_data++; - } - } - if (use_orco_tan) { - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { - *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]); - tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2; - tan_data++; - } - } - } - - CustomData_free(&loop_data, mr->loop_len); -} - -static void extract_tan_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *UNUSED(tls_data)) -{ - extract_tan_ex_init(mr, cache, buf, false); -} - -const MeshExtract extract_tan = { - .init = extract_tan_init, - .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract HQ Tangent layers - * \{ */ - -static void extract_tan_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *UNUSED(tls_data)) -{ - extract_tan_ex_init(mr, cache, buf, true); -} - -const MeshExtract extract_tan_hq = { - .init = extract_tan_hq_init, - .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Sculpt Data +/** \name Extract Edit Flag Utils * \{ */ -static void extract_sculpt_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - GPUVertFormat format = {0}; - - CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; - CustomData *cd_pdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata; - - float *cd_mask = CustomData_get_layer(cd_vdata, CD_PAINT_MASK); - int *cd_face_set = CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS); - - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - typedef struct gpuSculptData { - uint8_t face_set_color[4]; - float mask; - } gpuSculptData; - - gpuSculptData *vbo_data = (gpuSculptData *)GPU_vertbuf_get_data(vbo); - MLoop *loops = CustomData_get_layer(cd_ldata, CD_MLOOP); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - int cd_mask_ofs = CustomData_get_offset(cd_vdata, CD_PAINT_MASK); - int cd_face_set_ofs = CustomData_get_offset(cd_pdata, CD_SCULPT_FACE_SETS); - BMIter f_iter; - BMFace *efa; - BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - float v_mask = 0.0f; - if (cd_mask) { - v_mask = BM_ELEM_CD_GET_FLOAT(l_iter->v, cd_mask_ofs); - } - vbo_data->mask = v_mask; - uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - if (cd_face_set) { - const int face_set_id = BM_ELEM_CD_GET_INT(l_iter->f, cd_face_set_ofs); - if (face_set_id != mr->me->face_sets_color_default) { - BKE_paint_face_set_overlay_color_get( - face_set_id, mr->me->face_sets_color_seed, face_set_color); - } - } - copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color); - vbo_data++; - } while ((l_iter = l_iter->next) != l_first); - } - } - else { - int mp_loop = 0; - for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { - const MPoly *p = &mr->mpoly[mp_index]; - for (int l = 0; l < p->totloop; l++) { - float v_mask = 0.0f; - if (cd_mask) { - v_mask = cd_mask[loops[mp_loop].v]; - } - vbo_data->mask = v_mask; - - uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - if (cd_face_set) { - const int face_set_id = cd_face_set[mp_index]; - /* Skip for the default color Face Set to render it white. */ - if (face_set_id != mr->me->face_sets_color_default) { - BKE_paint_face_set_overlay_color_get( - face_set_id, mr->me->face_sets_color_seed, face_set_color); - } - } - copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color); - mp_loop++; - vbo_data++; - } - } - } -} - -const MeshExtract extract_sculpt_data = { - .init = extract_sculpt_data_init, - .data_type = 0, - .data_size = 0, - /* TODO: enable threading. */ - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract VCol - * \{ */ - -static void extract_vcol_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - GPUVertFormat format = {0}; - GPU_vertformat_deinterleave(&format); - - CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; - uint32_t vcol_layers = cache->cd_used.vcol; - uint32_t svcol_layers = cache->cd_used.sculpt_vcol; - - for (int i = 0; i < MAX_MCOL; i++) { - if (vcol_layers & (1 << i)) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - - BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) { - GPU_vertformat_alias_add(&format, "c"); - } - if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) { - GPU_vertformat_alias_add(&format, "ac"); - } - - /* Gather number of auto layers. */ - /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */ - if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 && - CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) { - BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); - GPU_vertformat_alias_add(&format, attr_name); - } - } - } - - /* Sculpt Vertex Colors */ - if (U.experimental.use_sculpt_vertex_colors) { - for (int i = 0; i < 8; i++) { - if (svcol_layers & (1 << i)) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - - BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { - GPU_vertformat_alias_add(&format, "c"); - } - if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { - GPU_vertformat_alias_add(&format, "ac"); - } - /* Gather number of auto layers. */ - /* We only do `vcols` that are not overridden by `uvs`. */ - if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { - BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); - GPU_vertformat_alias_add(&format, attr_name); - } - } - } - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - typedef struct gpuMeshVcol { - ushort r, g, b, a; - } gpuMeshVcol; - - gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo); - MLoop *loops = CustomData_get_layer(cd_ldata, CD_MLOOP); - - for (int i = 0; i < MAX_MCOL; i++) { - if (vcol_layers & (1 << i)) { - if (mr->extract_type == MR_EXTRACT_BMESH) { - int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i); - BMIter f_iter; - BMFace *efa; - BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs); - vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); - vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); - vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); - vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); - vcol_data++; - } while ((l_iter = l_iter->next) != l_first); - } - } - else { - const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) { - vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); - vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); - vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); - vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); - } - } - } - - if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) { - if (mr->extract_type == MR_EXTRACT_BMESH) { - int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i); - BMIter f_iter; - BMFace *efa; - BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - const MPropCol *prop_col = BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs); - vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]); - vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]); - vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]); - vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]); - vcol_data++; - } while ((l_iter = l_iter->next) != l_first); - } - } - else { - MPropCol *vcol = CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) { - vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]); - vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]); - vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]); - vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]); - } - } - } - } -} - -const MeshExtract extract_vcol = { - .init = extract_vcol_init, - .data_type = 0, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Orco - * \{ */ - -typedef struct MeshExtract_Orco_Data { - float (*vbo_data)[4]; - float (*orco)[3]; -} MeshExtract_Orco_Data; - -static void extract_orco_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex - * attributes. This is a substantial waste of video-ram and should be done another way. - * Unfortunately, at the time of writing, I did not found any other "non disruptive" - * alternative. */ - GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - CustomData *cd_vdata = &mr->me->vdata; - - MeshExtract_Orco_Data *data = tls_data; - data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo); - data->orco = CustomData_get_layer(cd_vdata, CD_ORCO); - /* Make sure `orco` layer was requested only if needed! */ - BLI_assert(data->orco); -} - -static void extract_orco_iter_poly_bm(const MeshRenderData *UNUSED(mr), - const BMFace *f, - const int UNUSED(f_index), - void *data) -{ - MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - float *loop_orco = orco_data->vbo_data[l_index]; - copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(l_iter->v)]); - loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int UNUSED(mp_index), - void *data) -{ - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; - float *loop_orco = orco_data->vbo_data[ml_index]; - copy_v3_v3(loop_orco, orco_data->orco[ml->v]); - loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ - } -} - -const MeshExtract extract_orco = { - .init = extract_orco_init, - .iter_poly_bm = extract_orco_iter_poly_bm, - .iter_poly_mesh = extract_orco_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(MeshExtract_Orco_Data), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Edge Factor - * Defines how much an edge is visible. - * \{ */ - -typedef struct MeshExtract_EdgeFac_Data { - uchar *vbo_data; - bool use_edge_render; - /* Number of loop per edge. */ - uchar *edge_loop_count; -} MeshExtract_EdgeFac_Data; - -static float loop_edge_factor_get(const float f_no[3], - const float v_co[3], - const float v_no[3], - const float v_next_co[3]) -{ - float enor[3], evec[3]; - sub_v3_v3v3(evec, v_next_co, v_co); - cross_v3_v3v3(enor, v_no, evec); - normalize_v3(enor); - float d = fabsf(dot_v3v3(enor, f_no)); - /* Re-scale to the slider range. */ - d *= (1.0f / 0.065f); - CLAMP(d, 0.0f, 1.0f); - return d; -} - -static void extract_edge_fac_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - - MeshExtract_EdgeFac_Data *data = tls_data; - - if (mr->extract_type == MR_EXTRACT_MESH) { - data->edge_loop_count = MEM_callocN(sizeof(uint32_t) * mr->edge_len, __func__); - - /* HACK(fclem) Detecting the need for edge render. - * We could have a flag in the mesh instead or check the modifier stack. */ - const MEdge *med = mr->medge; - for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) { - if ((med->flag & ME_EDGERENDER) == 0) { - data->use_edge_render = true; - break; - } - } - } - else { - /* HACK to bypass non-manifold check in mesh_edge_fac_finish(). */ - data->use_edge_render = true; - } - - data->vbo_data = GPU_vertbuf_get_data(vbo); -} - -static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - MeshExtract_EdgeFac_Data *data = _data; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - - if (BM_edge_is_manifold(l_iter->e)) { - float ratio = loop_edge_factor_get(bm_face_no_get(mr, f), - bm_vert_co_get(mr, l_iter->v), - bm_vert_no_get(mr, l_iter->v), - bm_vert_co_get(mr, l_iter->next->v)); - data->vbo_data[l_index] = ratio * 253 + 1; - } - else { - data->vbo_data[l_index] = 255; - } - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *_data) -{ - MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; - - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - - if (data->use_edge_render) { - const MEdge *med = &mr->medge[ml->e]; - data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0; - } - else { - - /* Count loop per edge to detect non-manifold. */ - if (data->edge_loop_count[ml->e] < 3) { - data->edge_loop_count[ml->e]++; - } - if (data->edge_loop_count[ml->e] == 2) { - /* Manifold */ - const int ml_index_last = mp->totloop + mp->loopstart - 1; - const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); - const MLoop *ml_next = &mr->mloop[ml_index_other]; - const MVert *v1 = &mr->mvert[ml->v]; - const MVert *v2 = &mr->mvert[ml_next->v]; - float vnor_f[3]; - normal_short_to_float_v3(vnor_f, v1->no); - float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co); - data->vbo_data[ml_index] = ratio * 253 + 1; - } - else { - /* Non-manifold */ - data->vbo_data[ml_index] = 255; - } - } - } -} - -static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr, - const BMEdge *UNUSED(eed), - const int ledge_index, - void *_data) -{ - MeshExtract_EdgeFac_Data *data = _data; - data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255; - data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255; -} - -static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr, - const MEdge *UNUSED(med), - const int ledge_index, - void *_data) -{ - MeshExtract_EdgeFac_Data *data = _data; - - data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255; - data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255; -} - -static void extract_edge_fac_finish(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *_data) -{ - GPUVertBuf *vbo = buf; - MeshExtract_EdgeFac_Data *data = _data; - - if (GPU_crappy_amd_driver()) { - /* Some AMD drivers strangely crash with VBO's with a one byte format. - * To workaround we reinitialize the VBO with another format and convert - * all bytes to floats. */ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } - /* We keep the data reference in data->vbo_data. */ - data->vbo_data = GPU_vertbuf_steal_data(vbo); - GPU_vertbuf_clear(vbo); - - int buf_len = mr->loop_len + mr->loop_loose_len; - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, buf_len); - - float *fdata = (float *)GPU_vertbuf_get_data(vbo); - for (int ml_index = 0; ml_index < buf_len; ml_index++, fdata++) { - *fdata = data->vbo_data[ml_index] / 255.0f; - } - /* Free old byte data. */ - MEM_freeN(data->vbo_data); - } - MEM_SAFE_FREE(data->edge_loop_count); -} - -const MeshExtract extract_edge_fac = { - .init = extract_edge_fac_init, - .iter_poly_bm = extract_edge_fac_iter_poly_bm, - .iter_poly_mesh = extract_edge_fac_iter_poly_mesh, - .iter_ledge_bm = extract_edge_fac_iter_ledge_bm, - .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh, - .finish = extract_edge_fac_finish, - .data_type = MR_DATA_POLY_NOR, - .data_size = sizeof(MeshExtract_EdgeFac_Data), - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac)}; - -/** \} */ -/* ---------------------------------------------------------------------- */ -/** \name Extract Vertex Weight - * \{ */ - -typedef struct MeshExtract_Weight_Data { - float *vbo_data; - const DRW_MeshWeightState *wstate; - const MDeformVert *dvert; /* For #Mesh. */ - int cd_ofs; /* For #BMesh. */ -} MeshExtract_Weight_Data; - -static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate) -{ - /* Error state. */ - if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) { - return -2.0f; - } - if (dvert == NULL) { - return (wstate->alert_mode != OB_DRAW_GROUPUSER_NONE) ? -1.0f : 0.0f; - } - - float input = 0.0f; - if (wstate->flags & DRW_MESH_WEIGHT_STATE_MULTIPAINT) { - /* Multi-Paint feature */ - bool is_normalized = (wstate->flags & (DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE | - DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE)); - input = BKE_defvert_multipaint_collective_weight(dvert, - wstate->defgroup_len, - wstate->defgroup_sel, - wstate->defgroup_sel_count, - is_normalized); - /* make it black if the selected groups have no weight on a vertex */ - if (input == 0.0f) { - return -1.0f; - } - } - else { - /* default, non tricky behavior */ - input = BKE_defvert_find_weight(dvert, wstate->defgroup_active); - - if (input == 0.0f) { - switch (wstate->alert_mode) { - case OB_DRAW_GROUPUSER_ACTIVE: - return -1.0f; - break; - case OB_DRAW_GROUPUSER_ALL: - if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) { - return -1.0f; - } - break; - } - } - } - - /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */ - if (wstate->flags & DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE) { - input = BKE_defvert_lock_relative_weight( - input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked); - } - - CLAMP(input, 0.0f, 1.0f); - return input; -} - -static void extract_weights_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - - MeshExtract_Weight_Data *data = tls_data; - data->vbo_data = (float *)GPU_vertbuf_get_data(vbo); - data->wstate = &cache->weight_state; - - if (data->wstate->defgroup_active == -1) { - /* Nothing to show. */ - data->dvert = NULL; - data->cd_ofs = -1; - } - else if (mr->extract_type == MR_EXTRACT_BMESH) { - data->dvert = NULL; - data->cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MDEFORMVERT); - } - else { - data->dvert = CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT); - data->cd_ofs = -1; - } -} - -static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr), - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - MeshExtract_Weight_Data *data = _data; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - if (data->cd_ofs != -1) { - const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(l_iter->v, data->cd_ofs); - data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate); - } - else { - data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate); - } - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int UNUSED(mp_index), - void *_data) -{ - MeshExtract_Weight_Data *data = _data; - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - if (data->dvert != NULL) { - const MDeformVert *dvert = &data->dvert[ml->v]; - data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); - } - else { - const MDeformVert *dvert = NULL; - data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); - } - } -} - -const MeshExtract extract_weights = { - .init = extract_weights_init, - .iter_poly_bm = extract_weights_iter_poly_bm, - .iter_poly_mesh = extract_weights_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(MeshExtract_Weight_Data), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights), -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Edit Mode Data / Flags - * \{ */ - -typedef struct EditLoopData { - uchar v_flag; - uchar e_flag; - uchar crease; - uchar bweight; -} EditLoopData; - -static void mesh_render_data_face_flag(const MeshRenderData *mr, - const BMFace *efa, - const int cd_ofs, - EditLoopData *eattr) +void mesh_render_data_face_flag(const MeshRenderData *mr, + const BMFace *efa, + const int cd_ofs, + EditLoopData *eattr) { if (efa == mr->efa_act) { eattr->v_flag |= VFLAG_FACE_ACTIVE; @@ -1708,7 +125,8 @@ static void mesh_render_data_face_flag(const MeshRenderData *mr, #ifdef WITH_FREESTYLE if (mr->freestyle_face_ofs != -1) { - const FreestyleFace *ffa = BM_ELEM_CD_GET_VOID_P(efa, mr->freestyle_face_ofs); + const FreestyleFace *ffa = (const FreestyleFace *)BM_ELEM_CD_GET_VOID_P( + efa, mr->freestyle_face_ofs); if (ffa->flag & FREESTYLE_FACE_MARK) { eattr->v_flag |= VFLAG_FACE_FREESTYLE; } @@ -1716,78 +134,15 @@ static void mesh_render_data_face_flag(const MeshRenderData *mr, #endif } -static void mesh_render_data_edge_flag(const MeshRenderData *mr, - const BMEdge *eed, - EditLoopData *eattr) -{ - const ToolSettings *ts = mr->toolsettings; - const bool is_vertex_select_mode = (ts != NULL) && (ts->selectmode & SCE_SELECT_VERTEX) != 0; - const bool is_face_only_select_mode = (ts != NULL) && (ts->selectmode == SCE_SELECT_FACE); - - if (eed == mr->eed_act) { - eattr->e_flag |= VFLAG_EDGE_ACTIVE; - } - if (!is_vertex_select_mode && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - eattr->e_flag |= VFLAG_EDGE_SELECTED; - } - if (is_vertex_select_mode && BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) && - BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) { - eattr->e_flag |= VFLAG_EDGE_SELECTED; - eattr->e_flag |= VFLAG_VERT_SELECTED; - } - if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) { - eattr->e_flag |= VFLAG_EDGE_SEAM; - } - if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) { - eattr->e_flag |= VFLAG_EDGE_SHARP; - } - - /* Use active edge color for active face edges because - * specular highlights make it hard to see T55456#510873. - * - * This isn't ideal since it can't be used when mixing edge/face modes - * but it's still better than not being able to see the active face. */ - if (is_face_only_select_mode) { - if (mr->efa_act != NULL) { - if (BM_edge_in_face(eed, mr->efa_act)) { - eattr->e_flag |= VFLAG_EDGE_ACTIVE; - } - } - } - - /* Use a byte for value range */ - if (mr->crease_ofs != -1) { - float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->crease_ofs); - if (crease > 0) { - eattr->crease = (uchar)(crease * 255.0f); - } - } - /* Use a byte for value range */ - if (mr->bweight_ofs != -1) { - float bweight = BM_ELEM_CD_GET_FLOAT(eed, mr->bweight_ofs); - if (bweight > 0) { - eattr->bweight = (uchar)(bweight * 255.0f); - } - } -#ifdef WITH_FREESTYLE - if (mr->freestyle_edge_ofs != -1) { - const FreestyleEdge *fed = BM_ELEM_CD_GET_VOID_P(eed, mr->freestyle_edge_ofs); - if (fed->flag & FREESTYLE_EDGE_MARK) { - eattr->e_flag |= VFLAG_EDGE_FREESTYLE; - } - } -#endif -} - -static void mesh_render_data_loop_flag(const MeshRenderData *mr, - BMLoop *l, - const int cd_ofs, - EditLoopData *eattr) +void mesh_render_data_loop_flag(const MeshRenderData *mr, + BMLoop *l, + const int cd_ofs, + EditLoopData *eattr) { if (cd_ofs == -1) { return; } - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_ofs); + MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_ofs); if (luv != NULL && (luv->flag & MLOOPUV_PINNED)) { eattr->v_flag |= VFLAG_VERT_UV_PINNED; } @@ -1796,10 +151,10 @@ static void mesh_render_data_loop_flag(const MeshRenderData *mr, } } -static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr, - BMLoop *l, - const int cd_ofs, - EditLoopData *eattr) +void mesh_render_data_loop_edge_flag(const MeshRenderData *mr, + BMLoop *l, + const int cd_ofs, + EditLoopData *eattr) { if (cd_ofs == -1) { return; @@ -1810,1879 +165,4 @@ static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr, } } -static void mesh_render_data_vert_flag(const MeshRenderData *mr, - const BMVert *eve, - EditLoopData *eattr) -{ - if (eve == mr->eve_act) { - eattr->e_flag |= VFLAG_VERT_ACTIVE; - } - if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - eattr->e_flag |= VFLAG_VERT_SELECTED; - } -} - -static void extract_edit_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* WARNING: Adjust #EditLoopData struct accordingly. */ - GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); - GPU_vertformat_alias_add(&format, "flag"); - } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - EditLoopData *vbo_data = GPU_vertbuf_get_data(vbo); - *(EditLoopData **)tls_data = vbo_data; -} - -static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - EditLoopData *vbo_data = *(EditLoopData **)_data; - - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - - EditLoopData *data = vbo_data + l_index; - memset(data, 0x0, sizeof(*data)); - mesh_render_data_face_flag(mr, f, -1, data); - mesh_render_data_edge_flag(mr, l_iter->e, data); - mesh_render_data_vert_flag(mr, l_iter->v, data); - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *_data) -{ - EditLoopData *vbo_data = *(EditLoopData **)_data; - - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - EditLoopData *data = vbo_data + ml_index; - memset(data, 0x0, sizeof(*data)); - BMFace *efa = bm_original_face_get(mr, mp_index); - BMEdge *eed = bm_original_edge_get(mr, ml->e); - BMVert *eve = bm_original_vert_get(mr, ml->v); - if (efa) { - mesh_render_data_face_flag(mr, efa, -1, data); - } - if (eed) { - mesh_render_data_edge_flag(mr, eed, data); - } - if (eve) { - mesh_render_data_vert_flag(mr, eve, data); - } - } -} - -static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr, - const BMEdge *eed, - const int ledge_index, - void *_data) -{ - EditLoopData *vbo_data = *(EditLoopData **)_data; - EditLoopData *data = vbo_data + mr->loop_len + (ledge_index * 2); - memset(data, 0x0, sizeof(*data) * 2); - mesh_render_data_edge_flag(mr, eed, &data[0]); - data[1] = data[0]; - mesh_render_data_vert_flag(mr, eed->v1, &data[0]); - mesh_render_data_vert_flag(mr, eed->v2, &data[1]); -} - -static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr, - const MEdge *med, - const int ledge_index, - void *_data) -{ - EditLoopData *vbo_data = *(EditLoopData **)_data; - EditLoopData *data = vbo_data + mr->loop_len + ledge_index * 2; - memset(data, 0x0, sizeof(*data) * 2); - const int e_index = mr->ledges[ledge_index]; - BMEdge *eed = bm_original_edge_get(mr, e_index); - BMVert *eve1 = bm_original_vert_get(mr, med->v1); - BMVert *eve2 = bm_original_vert_get(mr, med->v2); - if (eed) { - mesh_render_data_edge_flag(mr, eed, &data[0]); - data[1] = data[0]; - } - if (eve1) { - mesh_render_data_vert_flag(mr, eve1, &data[0]); - } - if (eve2) { - mesh_render_data_vert_flag(mr, eve2, &data[1]); - } -} - -static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr, - const BMVert *eve, - const int lvert_index, - void *_data) -{ - EditLoopData *vbo_data = *(EditLoopData **)_data; - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - EditLoopData *data = vbo_data + offset + lvert_index; - memset(data, 0x0, sizeof(*data)); - mesh_render_data_vert_flag(mr, eve, data); -} - -static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, - const MVert *UNUSED(mv), - const int lvert_index, - void *_data) -{ - EditLoopData *vbo_data = *(EditLoopData **)_data; - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - - EditLoopData *data = vbo_data + offset + lvert_index; - memset(data, 0x0, sizeof(*data)); - const int v_index = mr->lverts[lvert_index]; - BMVert *eve = bm_original_vert_get(mr, v_index); - if (eve) { - mesh_render_data_vert_flag(mr, eve, data); - } -} - -const MeshExtract extract_edit_data = { - .init = extract_edit_data_init, - .iter_poly_bm = extract_edit_data_iter_poly_bm, - .iter_poly_mesh = extract_edit_data_iter_poly_mesh, - .iter_ledge_bm = extract_edit_data_iter_ledge_bm, - .iter_ledge_mesh = extract_edit_data_iter_ledge_mesh, - .iter_lvert_bm = extract_edit_data_iter_lvert_bm, - .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh, - .data_type = 0, - .data_size = sizeof(EditLoopData *), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data)}; - /** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Edit UV Data / Flags - * \{ */ - -typedef struct MeshExtract_EditUVData_Data { - EditLoopData *vbo_data; - int cd_ofs; -} MeshExtract_EditUVData_Data; - -static void extract_edituv_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* WARNING: Adjust #EditLoopData struct accordingly. */ - GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); - GPU_vertformat_alias_add(&format, "flag"); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - - MeshExtract_EditUVData_Data *data = tls_data; - data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); - data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); -} - -static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - MeshExtract_EditUVData_Data *data = _data; - EditLoopData *eldata = &data->vbo_data[l_index]; - memset(eldata, 0x0, sizeof(*eldata)); - mesh_render_data_loop_flag(mr, l_iter, data->cd_ofs, eldata); - mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); - mesh_render_data_loop_edge_flag(mr, l_iter, data->cd_ofs, eldata); - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *_data) -{ - MeshExtract_EditUVData_Data *data = _data; - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - - EditLoopData *eldata = &data->vbo_data[ml_index]; - memset(eldata, 0x0, sizeof(*eldata)); - BMFace *efa = bm_original_face_get(mr, mp_index); - if (efa) { - BMEdge *eed = bm_original_edge_get(mr, ml->e); - BMVert *eve = bm_original_vert_get(mr, ml->v); - if (eed && eve) { - /* Loop on an edge endpoint. */ - BMLoop *l = BM_face_edge_share_loop(efa, eed); - mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata); - mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); - } - else { - if (eed == NULL) { - /* Find if the loop's vert is not part of an edit edge. - * For this, we check if the previous loop was on an edge. */ - const int ml_index_last = mp->loopstart + mp->totloop - 1; - const int l_prev = (ml_index == mp->loopstart) ? ml_index_last : (ml_index - 1); - const MLoop *ml_prev = &mr->mloop[l_prev]; - eed = bm_original_edge_get(mr, ml_prev->e); - } - if (eed) { - /* Mapped points on an edge between two edit verts. */ - BMLoop *l = BM_face_edge_share_loop(efa, eed); - mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); - } - } - } - } -} - -const MeshExtract extract_edituv_data = { - .init = extract_edituv_data_init, - .iter_poly_bm = extract_edituv_data_iter_poly_bm, - .iter_poly_mesh = extract_edituv_data_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(MeshExtract_EditUVData_Data), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Edit UV area stretch - * \{ */ - -static void extract_edituv_stretch_area_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); -} - -BLI_INLINE float area_ratio_get(float area, float uvarea) -{ - if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) { - /* Tag inversion by using the sign. */ - return (area > uvarea) ? (uvarea / area) : -(area / uvarea); - } - return 0.0f; -} - -BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio) -{ - ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio; - return (ratio > 1.0f) ? (1.0f / ratio) : ratio; -} - -static void extract_edituv_stretch_area_finish(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *UNUSED(data)) -{ - GPUVertBuf *vbo = buf; - float tot_area = 0.0f, tot_uv_area = 0.0f; - float *area_ratio = MEM_mallocN(sizeof(float) * mr->poly_len, __func__); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - CustomData *cd_ldata = &mr->bm->ldata; - int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); - - BMFace *efa; - BMIter f_iter; - int f; - BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { - float area = BM_face_calc_area(efa); - float uvarea = BM_face_calc_area_uv(efa, uv_ofs); - tot_area += area; - tot_uv_area += uvarea; - area_ratio[f] = area_ratio_get(area, uvarea); - } - } - else { - BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); - const MLoopUV *uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); - const MPoly *mp = mr->mpoly; - for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { - float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert); - float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data); - tot_area += area; - tot_uv_area += uvarea; - area_ratio[mp_index] = area_ratio_get(area, uvarea); - } - } - - cache->tot_area = tot_area; - cache->tot_uv_area = tot_uv_area; - - /* Convert in place to avoid an extra allocation */ - uint16_t *poly_stretch = (uint16_t *)area_ratio; - for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { - poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX; - } - - /* Copy face data for each loop. */ - uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - BMFace *efa; - BMIter f_iter; - int f, l_index = 0; - BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { - for (int i = 0; i < efa->len; i++, l_index++) { - loop_stretch[l_index] = poly_stretch[f]; - } - } - } - else { - BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); - const MPoly *mp = mr->mpoly; - for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { - for (int i = 0; i < mp->totloop; i++, l_index++) { - loop_stretch[l_index] = poly_stretch[mp_index]; - } - } - } - - MEM_freeN(area_ratio); -} - -const MeshExtract extract_edituv_stretch_area = { - .init = extract_edituv_stretch_area_init, - .finish = extract_edituv_stretch_area_finish, - .data_type = 0, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Edit UV angle stretch - * \{ */ - -typedef struct UVStretchAngle { - int16_t angle; - int16_t uv_angles[2]; -} UVStretchAngle; - -typedef struct MeshExtract_StretchAngle_Data { - UVStretchAngle *vbo_data; - MLoopUV *luv; - float auv[2][2], last_auv[2]; - float av[2][3], last_av[3]; - int cd_ofs; -} MeshExtract_StretchAngle_Data; - -static void compute_normalize_edge_vectors(float auv[2][2], - float av[2][3], - const float uv[2], - const float uv_prev[2], - const float co[3], - const float co_prev[3]) -{ - /* Move previous edge. */ - copy_v2_v2(auv[0], auv[1]); - copy_v3_v3(av[0], av[1]); - /* 2d edge */ - sub_v2_v2v2(auv[1], uv_prev, uv); - normalize_v2(auv[1]); - /* 3d edge */ - sub_v3_v3v3(av[1], co_prev, co); - normalize_v3(av[1]); -} - -static short v2_to_short_angle(const float v[2]) -{ - return atan2f(v[1], v[0]) * (float)M_1_PI * SHRT_MAX; -} - -static void edituv_get_edituv_stretch_angle(float auv[2][2], - const float av[2][3], - UVStretchAngle *r_stretch) -{ - /* Send UV's to the shader and let it compute the aspect corrected angle. */ - r_stretch->uv_angles[0] = v2_to_short_angle(auv[0]); - r_stretch->uv_angles[1] = v2_to_short_angle(auv[1]); - /* Compute 3D angle here. */ - r_stretch->angle = angle_normalized_v3v3(av[0], av[1]) * (float)M_1_PI * SHRT_MAX; - -#if 0 /* here for reference, this is done in shader now. */ - float uvang = angle_normalized_v2v2(auv0, auv1); - float ang = angle_normalized_v3v3(av0, av1); - float stretch = fabsf(uvang - ang) / (float)M_PI; - return 1.0f - pow2f(1.0f - stretch); -#endif -} - -static void extract_edituv_stretch_angle_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* Waning: adjust #UVStretchAngle struct accordingly. */ - GPU_vertformat_attr_add(&format, "angle", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - MeshExtract_StretchAngle_Data *data = tls_data; - data->vbo_data = (UVStretchAngle *)GPU_vertbuf_get_data(vbo); - - /* Special iterator needed to save about half of the computing cost. */ - if (mr->extract_type == MR_EXTRACT_BMESH) { - data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); - } - else { - BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); - data->luv = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); - } -} - -static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - MeshExtract_StretchAngle_Data *data = _data; - float(*auv)[2] = data->auv, *last_auv = data->last_auv; - float(*av)[3] = data->av, *last_av = data->last_av; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - - const MLoopUV *luv, *luv_next; - BMLoop *l_next = l_iter->next; - if (l_iter == BM_FACE_FIRST_LOOP(f)) { - /* First loop in face. */ - BMLoop *l_tmp = l_iter->prev; - BMLoop *l_next_tmp = l_iter; - luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs); - luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs); - compute_normalize_edge_vectors(auv, - av, - luv->uv, - luv_next->uv, - bm_vert_co_get(mr, l_tmp->v), - bm_vert_co_get(mr, l_next_tmp->v)); - /* Save last edge. */ - copy_v2_v2(last_auv, auv[1]); - copy_v3_v3(last_av, av[1]); - } - if (l_next == BM_FACE_FIRST_LOOP(f)) { - /* Move previous edge. */ - copy_v2_v2(auv[0], auv[1]); - copy_v3_v3(av[0], av[1]); - /* Copy already calculated last edge. */ - copy_v2_v2(auv[1], last_auv); - copy_v3_v3(av[1], last_av); - } - else { - luv = BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs); - luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs); - compute_normalize_edge_vectors(auv, - av, - luv->uv, - luv_next->uv, - bm_vert_co_get(mr, l_iter->v), - bm_vert_co_get(mr, l_next->v)); - } - edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]); - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int UNUSED(mp_index), - void *_data) -{ - MeshExtract_StretchAngle_Data *data = _data; - - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - float(*auv)[2] = data->auv, *last_auv = data->last_auv; - float(*av)[3] = data->av, *last_av = data->last_av; - int l_next = ml_index + 1; - const MVert *v, *v_next; - if (ml_index == mp->loopstart) { - /* First loop in face. */ - const int ml_index_last = ml_index_end - 1; - const int l_next_tmp = mp->loopstart; - v = &mr->mvert[mr->mloop[ml_index_last].v]; - v_next = &mr->mvert[mr->mloop[l_next_tmp].v]; - compute_normalize_edge_vectors( - auv, av, data->luv[ml_index_last].uv, data->luv[l_next_tmp].uv, v->co, v_next->co); - /* Save last edge. */ - copy_v2_v2(last_auv, auv[1]); - copy_v3_v3(last_av, av[1]); - } - if (l_next == ml_index_end) { - l_next = mp->loopstart; - /* Move previous edge. */ - copy_v2_v2(auv[0], auv[1]); - copy_v3_v3(av[0], av[1]); - /* Copy already calculated last edge. */ - copy_v2_v2(auv[1], last_auv); - copy_v3_v3(av[1], last_av); - } - else { - v = &mr->mvert[mr->mloop[ml_index].v]; - v_next = &mr->mvert[mr->mloop[l_next].v]; - compute_normalize_edge_vectors( - auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co); - } - edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]); - } -} - -const MeshExtract extract_edituv_stretch_angle = { - .init = extract_edituv_stretch_angle_init, - .iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm, - .iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(MeshExtract_StretchAngle_Data), - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Edit Mesh Analysis Colors - * \{ */ - -static void extract_mesh_analysis_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); -} - -static void axis_from_enum_v3(float v[3], const char axis) -{ - zero_v3(v); - if (axis < 3) { - v[axis] = 1.0f; - } - else { - v[axis - 3] = -1.0f; - } -} - -BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange) -{ - if (fac < min) { - fac = 1.0f; - } - else if (fac > max) { - fac = -1.0f; - } - else { - fac = (fac - min) * minmax_irange; - fac = 1.0f - fac; - CLAMP(fac, 0.0f, 1.0f); - } - return fac; -} - -static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang) -{ - const MeshStatVis *statvis = &mr->toolsettings->statvis; - const float min = statvis->overhang_min / (float)M_PI; - const float max = statvis->overhang_max / (float)M_PI; - const char axis = statvis->overhang_axis; - BMEditMesh *em = mr->edit_bmesh; - BMIter iter; - BMesh *bm = em->bm; - BMFace *f; - float dir[3]; - const float minmax_irange = 1.0f / (max - min); - - BLI_assert(min <= max); - - axis_from_enum_v3(dir, axis); - - /* now convert into global space */ - mul_transposed_mat3_m4_v3(mr->obmat, dir); - normalize_v3(dir); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - int l_index = 0; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI; - fac = overhang_remap(fac, min, max, minmax_irange); - for (int i = 0; i < f->len; i++, l_index++) { - r_overhang[l_index] = fac; - } - } - } - else { - const MPoly *mp = mr->mpoly; - for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { - float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI; - fac = overhang_remap(fac, min, max, minmax_irange); - for (int i = 0; i < mp->totloop; i++, l_index++) { - r_overhang[l_index] = fac; - } - } - } -} - -/** - * Needed so we can use jitter values for face interpolation. - */ -static void uv_from_jitter_v2(float uv[2]) -{ - uv[0] += 0.5f; - uv[1] += 0.5f; - if (uv[0] + uv[1] > 1.0f) { - uv[0] = 1.0f - uv[0]; - uv[1] = 1.0f - uv[1]; - } - - clamp_v2(uv, 0.0f, 1.0f); -} - -BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange) -{ - /* important not '<=' */ - if (fac < max) { - fac = (fac - min) * minmax_irange; - fac = 1.0f - fac; - CLAMP(fac, 0.0f, 1.0f); - } - else { - fac = -1.0f; - } - return fac; -} - -static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) -{ - const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */ - /* cheating to avoid another allocation */ - float *face_dists = r_thickness + (mr->loop_len - mr->poly_len); - BMEditMesh *em = mr->edit_bmesh; - const float scale = 1.0f / mat4_to_scale(mr->obmat); - const MeshStatVis *statvis = &mr->toolsettings->statvis; - const float min = statvis->thickness_min * scale; - const float max = statvis->thickness_max * scale; - const float minmax_irange = 1.0f / (max - min); - const int samples = statvis->thickness_samples; - float jit_ofs[32][2]; - BLI_assert(samples <= 32); - BLI_assert(min <= max); - - copy_vn_fl(face_dists, mr->poly_len, max); - - BLI_jitter_init(jit_ofs, samples); - for (int j = 0; j < samples; j++) { - uv_from_jitter_v2(jit_ofs[j]); - } - - if (mr->extract_type == MR_EXTRACT_BMESH) { - BMesh *bm = em->bm; - BM_mesh_elem_index_ensure(bm, BM_FACE); - - struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, NULL, false); - struct BMLoop *(*looptris)[3] = em->looptris; - for (int i = 0; i < mr->tri_len; i++) { - BMLoop **ltri = looptris[i]; - const int index = BM_elem_index_get(ltri[0]->f); - const float *cos[3] = { - bm_vert_co_get(mr, ltri[0]->v), - bm_vert_co_get(mr, ltri[1]->v), - bm_vert_co_get(mr, ltri[2]->v), - }; - float ray_co[3]; - float ray_no[3]; - - normal_tri_v3(ray_no, cos[2], cos[1], cos[0]); - - for (int j = 0; j < samples; j++) { - float dist = face_dists[index]; - interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]); - madd_v3_v3fl(ray_co, ray_no, eps_offset); - - BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, NULL, NULL); - if (f_hit && dist < face_dists[index]) { - float angle_fac = fabsf( - dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit))); - angle_fac = 1.0f - angle_fac; - angle_fac = angle_fac * angle_fac * angle_fac; - angle_fac = 1.0f - angle_fac; - dist /= angle_fac; - if (dist < face_dists[index]) { - face_dists[index] = dist; - } - } - } - } - BKE_bmbvh_free(bmtree); - - BMIter iter; - BMFace *f; - int l_index = 0; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - float fac = face_dists[BM_elem_index_get(f)]; - fac = thickness_remap(fac, min, max, minmax_irange); - for (int i = 0; i < f->len; i++, l_index++) { - r_thickness[l_index] = fac; - } - } - } - else { - BVHTreeFromMesh treeData = {NULL}; - - BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4); - const MLoopTri *mlooptri = mr->mlooptri; - for (int i = 0; i < mr->tri_len; i++, mlooptri++) { - const int index = mlooptri->poly; - const float *cos[3] = {mr->mvert[mr->mloop[mlooptri->tri[0]].v].co, - mr->mvert[mr->mloop[mlooptri->tri[1]].v].co, - mr->mvert[mr->mloop[mlooptri->tri[2]].v].co}; - float ray_co[3]; - float ray_no[3]; - - normal_tri_v3(ray_no, cos[2], cos[1], cos[0]); - - for (int j = 0; j < samples; j++) { - interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]); - madd_v3_v3fl(ray_co, ray_no, eps_offset); - - BVHTreeRayHit hit; - hit.index = -1; - hit.dist = face_dists[index]; - if ((BLI_bvhtree_ray_cast( - tree, ray_co, ray_no, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) && - hit.dist < face_dists[index]) { - float angle_fac = fabsf(dot_v3v3(mr->poly_normals[index], hit.no)); - angle_fac = 1.0f - angle_fac; - angle_fac = angle_fac * angle_fac * angle_fac; - angle_fac = 1.0f - angle_fac; - hit.dist /= angle_fac; - if (hit.dist < face_dists[index]) { - face_dists[index] = hit.dist; - } - } - } - } - - const MPoly *mp = mr->mpoly; - for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { - float fac = face_dists[mp_index]; - fac = thickness_remap(fac, min, max, minmax_irange); - for (int i = 0; i < mp->totloop; i++, l_index++) { - r_thickness[l_index] = fac; - } - } - } -} - -struct BVHTree_OverlapData { - const Mesh *me; - const MLoopTri *mlooptri; - float epsilon; -}; - -static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread)) -{ - struct BVHTree_OverlapData *data = userdata; - const Mesh *me = data->me; - - const MLoopTri *tri_a = &data->mlooptri[index_a]; - const MLoopTri *tri_b = &data->mlooptri[index_b]; - - if (UNLIKELY(tri_a->poly == tri_b->poly)) { - return false; - } - - const float *tri_a_co[3] = {me->mvert[me->mloop[tri_a->tri[0]].v].co, - me->mvert[me->mloop[tri_a->tri[1]].v].co, - me->mvert[me->mloop[tri_a->tri[2]].v].co}; - const float *tri_b_co[3] = {me->mvert[me->mloop[tri_b->tri[0]].v].co, - me->mvert[me->mloop[tri_b->tri[1]].v].co, - me->mvert[me->mloop[tri_b->tri[2]].v].co}; - float ix_pair[2][3]; - int verts_shared = 0; - - verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) + - ELEM(tri_a_co[2], UNPACK3(tri_b_co))); - - /* if 2 points are shared, bail out */ - if (verts_shared >= 2) { - return false; - } - - return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) && - /* if we share a vertex, check the intersection isn't a 'point' */ - ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon))); -} - -static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) -{ - BMEditMesh *em = mr->edit_bmesh; - - for (int l_index = 0; l_index < mr->loop_len; l_index++) { - r_intersect[l_index] = -1.0f; - } - - if (mr->extract_type == MR_EXTRACT_BMESH) { - uint overlap_len; - BMesh *bm = em->bm; - - BM_mesh_elem_index_ensure(bm, BM_FACE); - - struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, NULL, false); - BVHTreeOverlap *overlap = BKE_bmbvh_overlap_self(bmtree, &overlap_len); - - if (overlap) { - for (int i = 0; i < overlap_len; i++) { - BMFace *f_hit_pair[2] = { - em->looptris[overlap[i].indexA][0]->f, - em->looptris[overlap[i].indexB][0]->f, - }; - for (int j = 0; j < 2; j++) { - BMFace *f_hit = f_hit_pair[j]; - BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit); - int l_index = BM_elem_index_get(l_first); - for (int k = 0; k < f_hit->len; k++, l_index++) { - r_intersect[l_index] = 1.0f; - } - } - } - MEM_freeN(overlap); - } - - BKE_bmbvh_free(bmtree); - } - else { - uint overlap_len; - BVHTreeFromMesh treeData = {NULL}; - - BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4); - - struct BVHTree_OverlapData data = { - .me = mr->me, .mlooptri = mr->mlooptri, .epsilon = BLI_bvhtree_get_epsilon(tree)}; - - BVHTreeOverlap *overlap = BLI_bvhtree_overlap(tree, tree, &overlap_len, bvh_overlap_cb, &data); - if (overlap) { - for (int i = 0; i < overlap_len; i++) { - const MPoly *f_hit_pair[2] = { - &mr->mpoly[mr->mlooptri[overlap[i].indexA].poly], - &mr->mpoly[mr->mlooptri[overlap[i].indexB].poly], - }; - for (int j = 0; j < 2; j++) { - const MPoly *f_hit = f_hit_pair[j]; - int l_index = f_hit->loopstart; - for (int k = 0; k < f_hit->totloop; k++, l_index++) { - r_intersect[l_index] = 1.0f; - } - } - } - MEM_freeN(overlap); - } - } -} - -BLI_INLINE float distort_remap(float fac, float min, float UNUSED(max), float minmax_irange) -{ - if (fac >= min) { - fac = (fac - min) * minmax_irange; - CLAMP(fac, 0.0f, 1.0f); - } - else { - /* fallback */ - fac = -1.0f; - } - return fac; -} - -static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) -{ - BMEditMesh *em = mr->edit_bmesh; - const MeshStatVis *statvis = &mr->toolsettings->statvis; - const float min = statvis->distort_min; - const float max = statvis->distort_max; - const float minmax_irange = 1.0f / (max - min); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - BMIter iter; - BMesh *bm = em->bm; - BMFace *f; - - if (mr->bm_vert_coords != NULL) { - BKE_editmesh_cache_ensure_poly_normals(em, mr->edit_data); - - /* Most likely this is already valid, ensure just in case. - * Needed for #BM_loop_calc_face_normal_safe_vcos. */ - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - } - - int l_index = 0; - int f_index = 0; - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) { - float fac = -1.0f; - - if (f->len > 3) { - BMLoop *l_iter, *l_first; - - fac = 0.0f; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const float *no_face; - float no_corner[3]; - if (mr->bm_vert_coords != NULL) { - no_face = mr->bm_poly_normals[f_index]; - BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner); - } - else { - no_face = f->no; - BM_loop_calc_face_normal_safe(l_iter, no_corner); - } - - /* simple way to detect (what is most likely) concave */ - if (dot_v3v3(no_face, no_corner) < 0.0f) { - negate_v3(no_corner); - } - fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner)); - - } while ((l_iter = l_iter->next) != l_first); - fac *= 2.0f; - } - - fac = distort_remap(fac, min, max, minmax_irange); - for (int i = 0; i < f->len; i++, l_index++) { - r_distort[l_index] = fac; - } - } - } - else { - const MPoly *mp = mr->mpoly; - for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { - float fac = -1.0f; - - if (mp->totloop > 3) { - float *f_no = mr->poly_normals[mp_index]; - fac = 0.0f; - - for (int i = 1; i <= mp->totloop; i++) { - const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop]; - const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop]; - const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop]; - float no_corner[3]; - normal_tri_v3(no_corner, - mr->mvert[l_prev->v].co, - mr->mvert[l_curr->v].co, - mr->mvert[l_next->v].co); - /* simple way to detect (what is most likely) concave */ - if (dot_v3v3(f_no, no_corner) < 0.0f) { - negate_v3(no_corner); - } - fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner)); - } - fac *= 2.0f; - } - - fac = distort_remap(fac, min, max, minmax_irange); - for (int i = 0; i < mp->totloop; i++, l_index++) { - r_distort[l_index] = fac; - } - } - } -} - -BLI_INLINE float sharp_remap(float fac, float min, float UNUSED(max), float minmax_irange) -{ - /* important not '>=' */ - if (fac > min) { - fac = (fac - min) * minmax_irange; - CLAMP(fac, 0.0f, 1.0f); - } - else { - /* fallback */ - fac = -1.0f; - } - return fac; -} - -static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) -{ - BMEditMesh *em = mr->edit_bmesh; - const MeshStatVis *statvis = &mr->toolsettings->statvis; - const float min = statvis->sharp_min; - const float max = statvis->sharp_max; - const float minmax_irange = 1.0f / (max - min); - - /* Can we avoid this extra allocation? */ - float *vert_angles = MEM_mallocN(sizeof(float) * mr->vert_len, __func__); - copy_vn_fl(vert_angles, mr->vert_len, -M_PI); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - BMIter iter; - BMesh *bm = em->bm; - BMFace *efa; - BMEdge *e; - /* first assign float values to verts */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - float angle = BM_edge_calc_face_angle_signed(e); - float *col1 = &vert_angles[BM_elem_index_get(e->v1)]; - float *col2 = &vert_angles[BM_elem_index_get(e->v2)]; - *col1 = max_ff(*col1, angle); - *col2 = max_ff(*col2, angle); - } - /* Copy vert value to loops. */ - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - int l_index = BM_elem_index_get(l_iter); - int v_index = BM_elem_index_get(l_iter->v); - r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange); - } while ((l_iter = l_iter->next) != l_first); - } - } - else { - /* first assign float values to verts */ - const MPoly *mp = mr->mpoly; - - EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len); - - for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { - for (int i = 0; i < mp->totloop; i++) { - const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop]; - const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop]; - const MVert *v_curr = &mr->mvert[l_curr->v]; - const MVert *v_next = &mr->mvert[l_next->v]; - float angle; - void **pval; - bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval); - if (!value_is_init) { - *pval = mr->poly_normals[mp_index]; - /* non-manifold edge, yet... */ - continue; - } - if (*pval != NULL) { - const float *f1_no = mr->poly_normals[mp_index]; - const float *f2_no = *pval; - angle = angle_normalized_v3v3(f1_no, f2_no); - angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle; - /* Tag as manifold. */ - *pval = NULL; - } - else { - /* non-manifold edge */ - angle = DEG2RADF(90.0f); - } - float *col1 = &vert_angles[l_curr->v]; - float *col2 = &vert_angles[l_next->v]; - *col1 = max_ff(*col1, angle); - *col2 = max_ff(*col2, angle); - } - } - /* Remaining non manifold edges. */ - EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh); - for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - if (BLI_edgehashIterator_getValue(ehi) != NULL) { - uint v1, v2; - const float angle = DEG2RADF(90.0f); - BLI_edgehashIterator_getKey(ehi, &v1, &v2); - float *col1 = &vert_angles[v1]; - float *col2 = &vert_angles[v2]; - *col1 = max_ff(*col1, angle); - *col2 = max_ff(*col2, angle); - } - } - BLI_edgehashIterator_free(ehi); - BLI_edgehash_free(eh, NULL); - - const MLoop *ml = mr->mloop; - for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) { - r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange); - } - } - - MEM_freeN(vert_angles); -} - -static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(data)) -{ - GPUVertBuf *vbo = buf; - BLI_assert(mr->edit_bmesh); - - float *l_weight = (float *)GPU_vertbuf_get_data(vbo); - - switch (mr->toolsettings->statvis.type) { - case SCE_STATVIS_OVERHANG: - statvis_calc_overhang(mr, l_weight); - break; - case SCE_STATVIS_THICKNESS: - statvis_calc_thickness(mr, l_weight); - break; - case SCE_STATVIS_INTERSECT: - statvis_calc_intersect(mr, l_weight); - break; - case SCE_STATVIS_DISTORT: - statvis_calc_distort(mr, l_weight); - break; - case SCE_STATVIS_SHARP: - statvis_calc_sharp(mr, l_weight); - break; - } -} - -const MeshExtract extract_mesh_analysis = { - .init = extract_mesh_analysis_init, - .finish = extract_analysis_iter_finish_mesh, - /* This is not needed for all visualization types. - * * Maybe split into different extract. */ - .data_type = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Face-dots positions - * \{ */ - -static void extract_fdots_pos_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->poly_len); - *(float(**)[3])tls_data = GPU_vertbuf_get_data(vbo); -} - -static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int f_index, - void *data) -{ - float(*center)[3] = *(float(**)[3])data; - - float *co = center[f_index]; - zero_v3(co); - - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - add_v3_v3(co, bm_vert_co_get(mr, l_iter->v)); - } while ((l_iter = l_iter->next) != l_first); - mul_v3_fl(co, 1.0f / (float)f->len); -} - -static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *data) -{ - float(*center)[3] = *(float(**)[3])data; - float *co = center[mp_index]; - zero_v3(co); - - const MVert *mvert = mr->mvert; - const MLoop *mloop = mr->mloop; - - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - if (mr->use_subsurf_fdots) { - const MVert *mv = &mr->mvert[ml->v]; - if (mv->flag & ME_VERT_FACEDOT) { - copy_v3_v3(center[mp_index], mv->co); - break; - } - } - else { - const MVert *mv = &mvert[ml->v]; - add_v3_v3(center[mp_index], mv->co); - } - } - - if (!mr->use_subsurf_fdots) { - mul_v3_fl(co, 1.0f / (float)mp->totloop); - } -} - -const MeshExtract extract_fdots_pos = { - .init = extract_fdots_pos_init, - .iter_poly_bm = extract_fdots_pos_iter_poly_bm, - .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(float (*)[3]), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Face-dots Normal and edit flag - * \{ */ -#define NOR_AND_FLAG_DEFAULT 0 -#define NOR_AND_FLAG_SELECT 1 -#define NOR_AND_FLAG_ACTIVE -1 -#define NOR_AND_FLAG_HIDDEN -2 - -static void extract_fdots_nor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->poly_len); -} - -static void extract_fdots_nor_finish(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(data)) -{ - GPUVertBuf *vbo = buf; - static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; - GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo); - BMFace *efa; - - /* Quicker than doing it for each loop. */ - if (mr->extract_type == MR_EXTRACT_BMESH) { - for (int f = 0; f < mr->poly_len; f++) { - efa = BM_face_at_index(mr->bm, f); - const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); - if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && - mr->p_origindex[f] == ORIGINDEX_NONE)) { - nor[f] = GPU_normal_convert_i10_v3(invalid_normal); - nor[f].w = NOR_AND_FLAG_HIDDEN; - } - else { - nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa)); - /* Select / Active Flag. */ - nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? - ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : - NOR_AND_FLAG_DEFAULT); - } - } - } - else { - for (int f = 0; f < mr->poly_len; f++) { - efa = bm_original_face_get(mr, f); - const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN); - if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && - mr->p_origindex[f] == ORIGINDEX_NONE)) { - nor[f] = GPU_normal_convert_i10_v3(invalid_normal); - nor[f].w = NOR_AND_FLAG_HIDDEN; - } - else { - nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa)); - /* Select / Active Flag. */ - nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? - ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : - NOR_AND_FLAG_DEFAULT); - } - } - } -} - -const MeshExtract extract_fdots_nor = { - .init = extract_fdots_nor_init, - .finish = extract_fdots_nor_finish, - .data_type = MR_DATA_POLY_NOR, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Face-dots High Quality Normal and edit flag - * \{ */ -static void extract_fdots_nor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->poly_len); -} - -static void extract_fdots_nor_hq_finish(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(data)) -{ - GPUVertBuf *vbo = buf; - static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; - short *nor = (short *)GPU_vertbuf_get_data(vbo); - BMFace *efa; - - /* Quicker than doing it for each loop. */ - if (mr->extract_type == MR_EXTRACT_BMESH) { - for (int f = 0; f < mr->poly_len; f++) { - efa = BM_face_at_index(mr->bm, f); - const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); - if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && - mr->p_origindex[f] == ORIGINDEX_NONE)) { - normal_float_to_short_v3(&nor[f * 4], invalid_normal); - nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN; - } - else { - normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa)); - /* Select / Active Flag. */ - nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? - ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : - NOR_AND_FLAG_DEFAULT); - } - } - } - else { - for (int f = 0; f < mr->poly_len; f++) { - efa = bm_original_face_get(mr, f); - const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN); - if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && - mr->p_origindex[f] == ORIGINDEX_NONE)) { - normal_float_to_short_v3(&nor[f * 4], invalid_normal); - nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN; - } - else { - normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa)); - /* Select / Active Flag. */ - nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? - ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : - NOR_AND_FLAG_DEFAULT); - } - } - } -} - -const MeshExtract extract_fdots_nor_hq = { - .init = extract_fdots_nor_hq_init, - .finish = extract_fdots_nor_hq_finish, - .data_type = MR_DATA_POLY_NOR, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Face-dots UV - * \{ */ - -typedef struct MeshExtract_FdotUV_Data { - float (*vbo_data)[2]; - MLoopUV *uv_data; - int cd_ofs; -} MeshExtract_FdotUV_Data; - -static void extract_fdots_uv_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - GPU_vertformat_alias_add(&format, "au"); - GPU_vertformat_alias_add(&format, "pos"); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->poly_len); - - if (!mr->use_subsurf_fdots) { - /* Clear so we can accumulate on it. */ - memset(GPU_vertbuf_get_data(vbo), 0x0, mr->poly_len * GPU_vertbuf_get_format(vbo)->stride); - } - - MeshExtract_FdotUV_Data *data = tls_data; - data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo); - - if (mr->extract_type == MR_EXTRACT_BMESH) { - data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); - } - else { - data->uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); - } -} - -static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *UNUSED(mr), - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - MeshExtract_FdotUV_Data *data = _data; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - float w = 1.0f / (float)f->len; - const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs); - madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv->uv, w); - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *_data) -{ - MeshExtract_FdotUV_Data *data = _data; - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - if (mr->use_subsurf_fdots) { - const MVert *mv = &mr->mvert[ml->v]; - if (mv->flag & ME_VERT_FACEDOT) { - copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv); - } - } - else { - float w = 1.0f / (float)mp->totloop; - madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w); - } - } -} - -const MeshExtract extract_fdots_uv = { - .init = extract_fdots_uv_init, - .iter_poly_bm = extract_fdots_uv_iter_poly_bm, - .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(MeshExtract_FdotUV_Data), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Face-dots Edit UV flag - * \{ */ - -typedef struct MeshExtract_EditUVFdotData_Data { - EditLoopData *vbo_data; - int cd_ofs; -} MeshExtract_EditUVFdotData_Data; - -static void extract_fdots_edituv_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U8, 4, GPU_FETCH_INT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->poly_len); - - MeshExtract_EditUVFdotData_Data *data = tls_data; - data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); - data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); -} - -static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr, - const BMFace *f, - const int UNUSED(f_index), - void *_data) -{ - MeshExtract_EditUVFdotData_Data *data = _data; - EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)]; - memset(eldata, 0x0, sizeof(*eldata)); - mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); -} - -static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *UNUSED(mp), - const int mp_index, - void *_data) -{ - MeshExtract_EditUVFdotData_Data *data = _data; - EditLoopData *eldata = &data->vbo_data[mp_index]; - memset(eldata, 0x0, sizeof(*eldata)); - BMFace *efa = bm_original_face_get(mr, mp_index); - if (efa) { - mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata); - } -} - -const MeshExtract extract_fdots_edituv_data = { - .init = extract_fdots_edituv_data_init, - .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm, - .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(MeshExtract_EditUVFdotData_Data), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Skin Modifier Roots - * \{ */ - -typedef struct SkinRootData { - float size; - float local_pos[3]; -} SkinRootData; - -static void extract_skin_roots_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = buf; - /* Exclusively for edit mode. */ - BLI_assert(mr->bm); - - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "local_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->bm->totvert); - - SkinRootData *vbo_data = (SkinRootData *)GPU_vertbuf_get_data(vbo); - - int root_len = 0; - int cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MVERT_SKIN); - - BMIter iter; - BMVert *eve; - BM_ITER_MESH (eve, &iter, mr->bm, BM_VERTS_OF_MESH) { - const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_ofs); - if (vs->flag & MVERT_SKIN_ROOT) { - vbo_data->size = (vs->radius[0] + vs->radius[1]) * 0.5f; - copy_v3_v3(vbo_data->local_pos, bm_vert_co_get(mr, eve)); - vbo_data++; - root_len++; - } - } - - /* It's really unlikely that all verts will be roots. Resize to avoid losing VRAM. */ - GPU_vertbuf_data_len_set(vbo, root_len); -} - -const MeshExtract extract_skin_roots = { - .init = extract_skin_roots_init, - .data_type = 0, - .data_size = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots)}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Extract Selection Index - * \{ */ - -static void extract_select_idx_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* TODO rename "color" to something more descriptive. */ - GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT); - } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - *(uint32_t **)tls_data = GPU_vertbuf_get_data(vbo); -} - -/* TODO Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the - * select element associated with this loop ID. This would remove the need for this separate - * index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the - * shader to output original index. */ - -static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - const BMFace *f, - const int f_index, - void *data) -{ - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - (*(uint32_t **)data)[l_index] = f_index; - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - const BMFace *f, - const int UNUSED(f_index), - void *data) -{ - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->e); - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - const BMFace *f, - const int UNUSED(f_index), - void *data) -{ - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->v); - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr, - const BMEdge *eed, - const int ledge_index, - void *data) -{ - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed); - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed); -} - -static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr, - const BMEdge *eed, - const int ledge_index, - void *data) -{ - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1); - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2); -} - -static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr, - const BMVert *eve, - const int lvert_index, - void *data) -{ - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - - (*(uint32_t **)data)[offset + lvert_index] = BM_elem_index_get(eve); -} - -static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int mp_index, - void *data) -{ - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - (*(uint32_t **)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index; - } -} - -static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int UNUSED(mp_index), - void *data) -{ - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - (*(uint32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e; - } -} - -static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *mp, - const int UNUSED(mp_index), - void *data) -{ - const MLoop *mloop = mr->mloop; - const int ml_index_end = mp->loopstart + mp->totloop; - for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; - (*(uint32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v; - } -} - -static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr, - const MEdge *UNUSED(med), - const int ledge_index, - void *data) -{ - const int e_index = mr->ledges[ledge_index]; - const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index; - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig; - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig; -} - -static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr, - const MEdge *med, - const int ledge_index, - void *data) -{ - int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1; - int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2; - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig; - (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig; -} - -static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr, - const MVert *UNUSED(mv), - const int lvert_index, - void *data) -{ - const int offset = mr->loop_len + (mr->edge_loose_len * 2); - - const int v_index = mr->lverts[lvert_index]; - const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index; - (*(uint32_t **)data)[offset + lvert_index] = v_orig; -} - -const MeshExtract extract_poly_idx = { - .init = extract_select_idx_init, - .iter_poly_bm = extract_poly_idx_iter_poly_bm, - .iter_poly_mesh = extract_poly_idx_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(uint32_t *), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx)}; - -const MeshExtract extract_edge_idx = { - .init = extract_select_idx_init, - .iter_poly_bm = extract_edge_idx_iter_poly_bm, - .iter_poly_mesh = extract_edge_idx_iter_poly_mesh, - .iter_ledge_bm = extract_edge_idx_iter_ledge_bm, - .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh, - .data_type = 0, - .data_size = sizeof(uint32_t *), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx)}; - -const MeshExtract extract_vert_idx = { - .init = extract_select_idx_init, - .iter_poly_bm = extract_vert_idx_iter_poly_bm, - .iter_poly_mesh = extract_vert_idx_iter_poly_mesh, - .iter_ledge_bm = extract_vert_idx_iter_ledge_bm, - .iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh, - .iter_lvert_bm = extract_vert_idx_iter_lvert_bm, - .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh, - .data_type = 0, - .data_size = sizeof(uint32_t *), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx)}; - -static void extract_fdot_idx_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf, - void *tls_data) -{ - GPUVertBuf *vbo = buf; - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* TODO rename "color" to something more descriptive. */ - GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->poly_len); - *(uint32_t **)tls_data = GPU_vertbuf_get_data(vbo); -} - -static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - const BMFace *UNUSED(f), - const int f_index, - void *data) -{ - (*(uint32_t **)data)[f_index] = f_index; -} - -static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *UNUSED(mp), - const int mp_index, - void *data) -{ - if (mr->p_origindex != NULL) { - (*(uint32_t **)data)[mp_index] = mr->p_origindex[mp_index]; - } - else { - (*(uint32_t **)data)[mp_index] = mp_index; - } -} - -const MeshExtract extract_fdot_idx = { - .init = extract_fdot_idx_init, - .iter_poly_bm = extract_fdot_idx_iter_poly_bm, - .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh, - .data_type = 0, - .data_size = sizeof(uint32_t *), - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx)}; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_private.h b/source/blender/draw/intern/draw_cache_extract_mesh_private.h index 1b4521335ec..5f670bdc5ec 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_private.h +++ b/source/blender/draw/intern/draw_cache_extract_mesh_private.h @@ -30,6 +30,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "draw_cache_extract.h" @@ -258,11 +259,30 @@ void mesh_render_data_update_looptris(MeshRenderData *mr, const eMRDataType data_flag); /* draw_cache_extract_mesh_extractors.c */ +typedef struct EditLoopData { + uchar v_flag; + uchar e_flag; + uchar crease; + uchar bweight; +} EditLoopData; + void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferCache *mbc); eMRIterType mesh_extract_iter_type(const MeshExtract *ext); const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor, const bool do_hq_normals, const bool do_single_mat); +void mesh_render_data_face_flag(const MeshRenderData *mr, + const BMFace *efa, + const int cd_ofs, + EditLoopData *eattr); +void mesh_render_data_loop_flag(const MeshRenderData *mr, + BMLoop *l, + const int cd_ofs, + EditLoopData *eattr); +void mesh_render_data_loop_edge_flag(const MeshRenderData *mr, + BMLoop *l, + const int cd_ofs, + EditLoopData *eattr); extern const MeshExtract extract_tris; extern const MeshExtract extract_tris_single_mat; diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 5743f39f7da..220a7f37c3d 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -219,7 +219,7 @@ struct GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(struct Mesh *me); struct GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu); struct GPUVertBuf *DRW_mball_batch_cache_pos_vertbuf_get(struct Object *ob); -int DRW_mesh_material_count_get(struct Mesh *me); +int DRW_mesh_material_count_get(const struct Mesh *me); /* See 'common_globals_lib.glsl' for duplicate defines. */ diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc index c4cd547ef43..51bd4c535cd 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.cc +++ b/source/blender/draw/intern/draw_cache_impl_curve.cc @@ -363,7 +363,7 @@ static void curve_cd_calc_used_gpu_layers(CustomDataMask *cd_layers, int type = gpu_attr->type; /* Curves cannot have named layers. - * Note: We could relax this assumption later. */ + * NOTE: We could relax this assumption later. */ if (name[0] != '\0') { continue; } diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index 1d4f411c94d..1fed5d79697 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -365,7 +365,7 @@ static void surf_uv_quad(const DispList *dl, const uint quad[4], float r_uv[4][2 } for (int i = 0; i < 4; i++) { - /* Note: For some reason the shading U and V are swapped compared to the + /* NOTE: For some reason the shading U and V are swapped compared to the * one described in the surface format. */ /* find uv based on vertex index into grid array */ r_uv[i][0] = (quad[i] / dl->nr) / (float)orco_sizev; diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index bea9ba1122b..336ccd40d5c 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -301,7 +301,7 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts, int v, bool is_endpoint) { - /* Note: we use the sign of strength and thickness to pass cap flag. */ + /* NOTE: we use the sign of strength and thickness to pass cap flag. */ const bool round_cap0 = (gps->caps[0] == GP_STROKE_CAP_ROUND); const bool round_cap1 = (gps->caps[1] == GP_STROKE_CAP_ROUND); gpStrokeVert *vert = &verts[v]; @@ -422,7 +422,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr .tri_len = 0, .curve_len = 0, }; - BKE_gpencil_visible_stroke_iter( + BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra); /* Create VBOs. */ @@ -439,7 +439,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len); /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra); + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra); /* Mark last 2 verts as invalid. */ for (int i = 0; i < 2; i++) { @@ -514,7 +515,7 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob) /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ bool do_onion = true; - BKE_gpencil_visible_stroke_iter( + BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, gpencil_lines_indices_cb, &iter, do_onion, cfra); GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo); @@ -843,8 +844,8 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in int vert_len = GPU_vertbuf_get_vertex_len(cache->vbo); gpEditIterData iter; - iter.vgindex = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, iter.vgindex)) { + iter.vgindex = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, iter.vgindex)) { iter.vgindex = -1; } @@ -856,7 +857,7 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in iter.verts = (gpEditVert *)GPU_vertbuf_get_data(cache->edit_vbo); /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_iter( + BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra); /* Create the batches */ @@ -883,7 +884,7 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in cache->edit_curve_vbo = GPU_vertbuf_create_with_format(format); /* Count data. */ - BKE_gpencil_visible_stroke_iter( + BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, gpencil_edit_curve_stroke_count_cb, &iterdata, false, cfra); gpEditCurveIterData iter; @@ -894,7 +895,7 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in iter.verts = (gpEditCurveVert *)GPU_vertbuf_get_data(cache->edit_curve_vbo); /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_iter( + BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, gpencil_edit_curve_stroke_iter_cb, &iter, false, cfra); cache->edit_curve_handles_batch = GPU_batch_create( diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c index eabef49fa22..0a1c7d9581a 100644 --- a/source/blender/draw/intern/draw_cache_impl_lattice.c +++ b/source/blender/draw/intern/draw_cache_impl_lattice.c @@ -84,7 +84,7 @@ static int lattice_render_verts_len_get(Lattice *lt) return vert_len_calc(u, v, w); } - /* TODO remove internal coords */ + /* TODO: remove internal coords. */ return vert_len_calc(u, v, w); } @@ -102,7 +102,7 @@ static int lattice_render_edges_len_get(Lattice *lt) return edge_len_calc(u, v, w); } - /* TODO remove internal coords */ + /* TODO: remove internal coords. */ return edge_len_calc(u, v, w); } @@ -305,7 +305,7 @@ void DRW_lattice_batch_cache_dirty_tag(Lattice *lt, int mode) cache->is_dirty = true; break; case BKE_LATTICE_BATCH_DIRTY_SELECT: - /* TODO Separate Flag vbo */ + /* TODO: Separate Flag VBO. */ GPU_BATCH_DISCARD_SAFE(cache->overlay_verts); break; default: diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 33f8ec38a54..0c002ff09f2 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -544,8 +544,8 @@ static void drw_mesh_weight_state_extract(Object *ob, /* Extract complete vertex weight group selection state and mode flags. */ memset(wstate, 0, sizeof(*wstate)); - wstate->defgroup_active = ob->actdef - 1; - wstate->defgroup_len = BLI_listbase_count(&ob->defbase); + wstate->defgroup_active = me->vertex_group_active_index - 1; + wstate->defgroup_len = BLI_listbase_count(&me->vertex_group_names); wstate->alert_mode = ts->weightuser; @@ -821,6 +821,17 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode) mesh_batch_cache_discard_shaded_tri(cache); mesh_batch_cache_discard_uvedit(cache); break; + case BKE_MESH_BATCH_DIRTY_DEFORM: + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor); + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor); + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_pos); + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_nor); + GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.tris); + } + batch_map = MDEPS_CREATE_MAP(vbo.pos_nor, vbo.lnor, vbo.fdots_pos, vbo.fdots_nor, ibo.tris); + mesh_batch_cache_discard_batch(cache, batch_map); + break; case BKE_MESH_BATCH_DIRTY_UVEDIT_ALL: mesh_batch_cache_discard_uvedit(cache); break; @@ -1052,7 +1063,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me) return cache->batch.surface; } -int DRW_mesh_material_count_get(Mesh *me) +int DRW_mesh_material_count_get(const Mesh *me) { return mesh_render_mat_len_get(me); } @@ -1278,7 +1289,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Mesh *me) * \{ */ /* Thread safety need to be assured by caller. Don't call this during drawing. - * Note: For now this only free the shading batches / vbo if any cd layers is + * NOTE: For now this only free the shading batches / vbo if any cd layers is * not needed anymore. */ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) { @@ -1305,7 +1316,7 @@ static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, M { MeshBatchCache *cache = mesh_batch_cache_get(me); /* Make sure all requested batches have been setup. */ - /* Note: The next line creates a different scheduling than during release builds what can lead to + /* NOTE: The next line creates a different scheduling than during release builds what can lead to * some issues (See T77867 where we needed to disable this function in order to debug what was * happening in release builds). */ BLI_task_graph_work_and_wait(task_graph); diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c index ff969f920da..4d3a990ec72 100644 --- a/source/blender/draw/intern/draw_cache_impl_metaball.c +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -140,7 +140,7 @@ static void metaball_batch_cache_clear(MetaBall *mb) GPU_BATCH_DISCARD_SAFE(cache->edge_detection); GPU_VERTBUF_DISCARD_SAFE(cache->pos_nor_in_order); GPU_INDEXBUF_DISCARD_SAFE(cache->edges_adj_lines); - /* Note: shaded_triangles[0] is already freed by cache->batch */ + /* NOTE: shaded_triangles[0] is already freed by `cache->batch`. */ MEM_SAFE_FREE(cache->shaded_triangles); cache->mat_len = 0; cache->is_manifold = false; diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index a9febcedbf9..5c51f24a435 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -181,7 +181,7 @@ static void particle_batch_cache_clear_point(ParticlePointCache *point_cache) void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache) { - /* TODO more granular update tagging. */ + /* TODO: more granular update tagging. */ GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf); DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex); @@ -560,7 +560,7 @@ static int particle_batch_cache_fill_segments(ParticleSystem *psys, (is_simple && is_child) ? (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]); } for (int k = 0; k < num_col_layers; k++) { - /* TODO Put the conversion outside the loop */ + /* TODO: Put the conversion outside the loop. */ ushort scol[4]; particle_pack_mcol( (is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], @@ -587,7 +587,7 @@ static int particle_batch_cache_fill_segments(ParticleSystem *psys, uv[k]); } for (int k = 0; k < num_col_layers; k++) { - /* TODO Put the conversion outside the loop */ + /* TODO: Put the conversion outside the loop. */ ushort scol[4]; particle_pack_mcol((is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], @@ -1500,7 +1500,7 @@ static void particle_batch_cache_ensure_edit_pos_and_seg(PTCacheEdit *edit, edit, particle, edit->pathcache, 0, edit->totcached, &elb, &data_step); } else { - BLI_assert(!"Hairs are not in edit mode!"); + BLI_assert_msg(0, "Hairs are not in edit mode!"); } hair_cache->indices = GPU_indexbuf_build(&elb); } diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h index 6e537a3bffa..b977d0cdda2 100644 --- a/source/blender/draw/intern/draw_cache_inline.h +++ b/source/blender/draw/intern/draw_cache_inline.h @@ -74,7 +74,7 @@ BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo) BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo) { - /* TODO do not rely on data uploaded. This prevents multithreading. + /* TODO: do not rely on data uploaded. This prevents multithreading. * (need access to a gl context) */ return (ibo != NULL && !GPU_indexbuf_is_init(ibo)); } diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index d3a90ccfbd0..62d715460bb 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -192,7 +192,7 @@ void DRW_globals_update(void) (max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f)); gb->sizeVertexGpencil = U.pixelsize * UI_GetThemeValuef(TH_GP_VERTEX_SIZE); gb->sizeFaceDot = U.pixelsize * UI_GetThemeValuef(TH_FACEDOT_SIZE); - gb->sizeEdge = U.pixelsize * (1.0f / 2.0f); /* TODO Theme */ + gb->sizeEdge = U.pixelsize * (1.0f / 2.0f); /* TODO: Theme. */ gb->sizeEdgeFix = U.pixelsize * (0.5f + 2.0f * (2.0f * (gb->sizeEdge * (float)M_SQRT1_2))); const float(*screen_vecs)[3] = (float(*)[3])DRW_viewport_screenvecs_get(); @@ -210,7 +210,7 @@ void DRW_globals_update(void) { float *color = gb->UBO_FIRST_COLOR; do { - /* TODO more accurate transform. */ + /* TODO: more accurate transform. */ srgb_to_linearrgb_v4(color, color); color += 4; } while (color <= gb->UBO_LAST_COLOR); @@ -291,7 +291,7 @@ DRWView *DRW_view_create_with_zoffset(const DRWView *parent_view, /* ******************************************** COLOR UTILS ************************************ */ -/* TODO FINISH */ +/* TODO: FINISH. */ /** * Get the wire color theme_id of an object based on its state * \a r_color is a way to get a pointer to the static color var associated @@ -304,7 +304,7 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color /* confusing logic here, there are 2 methods of setting the color * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id. * - * note: no theme yet for 'colindex' */ + * NOTE: no theme yet for 'colindex'. */ int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE; if (is_edit) { diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 7e6e1f03f8a..1eaf2bee236 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -35,7 +35,7 @@ struct ViewLayer; /* Used as ubo but colors can be directly referenced as well */ /* Keep in sync with: common_globals_lib.glsl (globalsBlock) */ -/* NOTE! Also keep all color as vec4 and between UBO_FIRST_COLOR and UBO_LAST_COLOR */ +/* NOTE: Also keep all color as vec4 and between #UBO_FIRST_COLOR and #UBO_LAST_COLOR. */ typedef struct GlobalsUboStorage { /* UBOs data needs to be 16 byte aligned (size of vec4) */ float colorWire[4]; @@ -141,7 +141,7 @@ typedef struct GlobalsUboStorage { float colorUVShadow[4]; - /* NOTE! Put all color before UBO_LAST_COLOR */ + /* NOTE: Put all color before #UBO_LAST_COLOR. */ float screenVecs[2][4]; /* Padded as vec4. */ float sizeViewport[2], sizeViewportInv[2]; /* Packed as vec4 in GLSL. */ diff --git a/source/blender/draw/intern/draw_fluid.c b/source/blender/draw/intern/draw_fluid.c index a21402e6392..9cfdbf7c688 100644 --- a/source/blender/draw/intern/draw_fluid.c +++ b/source/blender/draw/intern/draw_fluid.c @@ -589,7 +589,7 @@ void DRW_fluid_ensure_range_field(FluidModifierData *fmd) #endif /* WITH_FLUID */ } -/* TODO Unify with the other GPU_free_smoke. */ +/* TODO: Unify with the other #GPU_free_smoke. */ void DRW_smoke_free_velocity(FluidModifierData *fmd) { if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) { diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index d101df737ff..c2e25389091 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -197,7 +197,7 @@ static ParticleHairCache *drw_hair_particle_cache_get( return cache; } -/* Note: Only valid after DRW_hair_update(). */ +/* NOTE: Only valid after DRW_hair_update(). */ GPUVertBuf *DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, ModifierData *md) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -262,7 +262,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent); - /* TODO optimize this. Only bind the ones GPUMaterial needs. */ + /* TODO: optimize this. Only bind the ones GPUMaterial needs. */ for (int i = 0; i < hair_cache->num_uv_layers; i++) { for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; n++) { DRW_shgroup_uniform_texture(shgrp, hair_cache->uv_layer_names[i][n], hair_cache->uv_tex[i]); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index db64c7deb63..6f5e041fa79 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1645,7 +1645,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_draw_scene(); - /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */ + /* Fix 3D view "lagging" on APPLE and WIN32+NVIDIA. (See T56996, T61474) */ GPU_flush(); DRW_stats_reset(); @@ -2315,7 +2315,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, } if (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) { if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) { - /* Note: don't use "BKE_object_pose_armature_get" here, it breaks selection. */ + /* NOTE: don't use "BKE_object_pose_armature_get" here, it breaks selection. */ Object *obpose = OBPOSE_FROM_OBACT(obact); if (obpose == NULL) { Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact); @@ -3147,7 +3147,7 @@ void DRW_opengl_render_context_enable(void *re_gl_context) /* If thread is main you should use DRW_opengl_context_enable(). */ BLI_assert(!BLI_thread_is_main()); - /* TODO get rid of the blocking. Only here because of the static global DST. */ + /* TODO: get rid of the blocking. Only here because of the static global DST. */ BLI_ticket_mutex_lock(DST.gl_context_mutex); WM_opengl_context_activate(re_gl_context); } @@ -3155,7 +3155,7 @@ void DRW_opengl_render_context_enable(void *re_gl_context) void DRW_opengl_render_context_disable(void *re_gl_context) { WM_opengl_context_release(re_gl_context); - /* TODO get rid of the blocking. */ + /* TODO: get rid of the blocking. */ BLI_ticket_mutex_unlock(DST.gl_context_mutex); } diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 373b51a67e0..c4e8d0a980d 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -467,7 +467,7 @@ typedef struct DRWCommandSmallChunk { uint32_t command_len; uint32_t command_used; /* 4bits for each command. */ - /* TODO reduce size of command_type. */ + /* TODO: reduce size of command_type. */ uint64_t command_type[6]; DRWCommand commands[6]; } DRWCommandSmallChunk; @@ -498,7 +498,7 @@ typedef struct DRWDebugSphere { #define STENCIL_UNDEFINED 256 #define DRW_DRAWLIST_LEN 256 typedef struct DRWManager { - /* TODO clean up this struct a bit */ + /* TODO: clean up this struct a bit. */ /* Cache generation */ ViewportMemoryPool *vmempool; DRWInstanceDataList *idatalist; diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 5eedca4507e..0a0e1ba9ac3 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -94,7 +94,7 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool) int ubo_len = 1 + chunk_id - ((elem_id == 0) ? 1 : 0); size_t list_size = sizeof(GPUUniformBuf *) * ubo_len; - /* TODO find a better system. currently a lot of obinfos UBO are going to be unused + /* TODO: find a better system. currently a lot of obinfos UBO are going to be unused * if not rendering with Eevee. */ if (vmempool->matrices_ubo == NULL) { @@ -782,7 +782,7 @@ static void drw_command_set_mutable_state(DRWShadingGroup *shgroup, DRWState enable, DRWState disable) { - /* TODO Restrict what state can be changed. */ + /* TODO: Restrict what state can be changed. */ DRWCommandSetMutableState *cmd = drw_command_create(shgroup, DRW_CMD_DRWSTATE); cmd->enable = enable; cmd->disable = disable; @@ -1263,7 +1263,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 0, 1); } else { - /* Note: This is only here to support old hardware fallback where uniform buffer is still + /* NOTE: This is only here to support old hardware fallback where uniform buffer is still * too slow or buggy. */ int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL); int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV); @@ -1456,7 +1456,7 @@ void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup, drw_command_set_stencil_mask(shgroup, write_mask, reference, compare_mask); } -/* TODO remove this function. */ +/* TODO: remove this function. */ void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask) { drw_command_set_stencil_mask(shgroup, 0xFF, mask, 0xFF); diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index f29caebeb84..7f7696d485c 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -225,7 +225,7 @@ void drw_state_set(DRWState state) GPU_shadow_offset(false); } - /* TODO this should be part of shader state. */ + /* TODO: this should be part of shader state. */ if (state & DRW_STATE_CLIP_PLANES) { GPU_clip_distances(DST.view_active->clip_planes_len); } @@ -383,10 +383,10 @@ static bool draw_culling_sphere_test(const BoundSphere *frustum_bsphere, if (center_dist_sq > square_f(radius_sum)) { return false; } - /* TODO we could test against the inscribed sphere of the frustum to early out positively. */ + /* TODO: we could test against the inscribed sphere of the frustum to early out positively. */ /* Test against the 6 frustum planes. */ - /* TODO order planes with sides first then far then near clip. Should be better culling + /* TODO: order planes with sides first then far then near clip. Should be better culling * heuristic when sculpting. */ for (int p = 0; p < 6; p++) { float dist = plane_point_side_v3(frustum_planes[p], bsphere->center); @@ -701,7 +701,7 @@ BLI_INLINE void draw_select_buffer(DRWShadingGroup *shgroup, int count = 1; int tot = is_instancing ? GPU_vertbuf_get_vertex_len(batch->inst[0]) : GPU_vertbuf_get_vertex_len(batch->verts[0]); - /* Hack : get "vbo" data without actually drawing. */ + /* HACK: get VBO data without actually drawing. */ int *select_id = (void *)GPU_vertbuf_get_data(state->select_buf); /* Batching */ @@ -818,7 +818,7 @@ static void draw_call_single_do(DRWShadingGroup *shgroup, draw_call_resource_bind(state, &handle); - /* TODO This is Legacy. Need to be removed. */ + /* TODO: This is Legacy. Need to be removed. */ if (state->obmats_loc == -1 && (state->obmat_loc != -1 || state->obinv_loc != -1)) { draw_legacy_matrix_update(shgroup, &handle, state->obmat_loc, state->obinv_loc); } @@ -1076,7 +1076,7 @@ static void drw_update_view(void) /* TODO(fclem): update a big UBO and only bind ranges here. */ GPU_uniformbuf_update(G_draw.view_ubo, &DST.view_active->storage); - /* TODO get rid of this. */ + /* TODO: get rid of this. */ DST.view_storage_cpy = DST.view_active->storage; draw_compute_culling(DST.view_active); diff --git a/source/blender/draw/intern/draw_shader.c b/source/blender/draw/intern/draw_shader.c index 9c756065353..121a0acd059 100644 --- a/source/blender/draw/intern/draw_shader.c +++ b/source/blender/draw/intern/draw_shader.c @@ -104,7 +104,7 @@ GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement, sh = hair_refine_shader_transform_feedback_workaround_create(refinement); break; default: - BLI_assert(!"Incorrect shader type"); + BLI_assert_msg(0, "Incorrect shader type"); } e_data.hair_refine_sh[refinement] = sh; } diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 2fb44d0030b..ae2c66881ff 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -266,7 +266,7 @@ void DRW_draw_gizmo_3d(void) ARegion *region = draw_ctx->region; /* draw depth culled gizmos - gizmos need to be updated *after* view matrix was set up */ - /* TODO depth culling gizmos is not yet supported, just drawing _3D here, should + /* TODO: depth culling gizmos is not yet supported, just drawing _3D here, should * later become _IN_SCENE (and draw _3D separate) */ WM_gizmomap_draw(region->gizmo_map, draw_ctx->evil_C, WM_GIZMOMAP_DRAWSTEP_3D); } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc index 43ad28c2618..bdb9af1faf3 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc @@ -89,7 +89,7 @@ BLI_INLINE void lines_adjacency_triangle( *pval = POINTER_FROM_INT(NO_EDGE); bool inv_opposite = (v_data < 0); uint l_opposite = (uint)abs(v_data) - 1; - /* TODO Make this part thread-safe. */ + /* TODO: Make this part thread-safe. */ if (inv_opposite == inv_indices) { /* Don't share edge if triangles have non matching winding. */ GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l1); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc new file mode 100644 index 00000000000..1bc4c7e330f --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc @@ -0,0 +1,241 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "GPU_capabilities.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Edge Factor + * Defines how much an edge is visible. + * \{ */ + +struct MeshExtract_EdgeFac_Data { + uchar *vbo_data; + bool use_edge_render; + /* Number of loop per edge. */ + uchar *edge_loop_count; +}; + +static float loop_edge_factor_get(const float f_no[3], + const float v_co[3], + const float v_no[3], + const float v_next_co[3]) +{ + float enor[3], evec[3]; + sub_v3_v3v3(evec, v_next_co, v_co); + cross_v3_v3v3(enor, v_no, evec); + normalize_v3(enor); + float d = fabsf(dot_v3v3(enor, f_no)); + /* Re-scale to the slider range. */ + d *= (1.0f / 0.065f); + CLAMP(d, 0.0f, 1.0f); + return d; +} + +static void extract_edge_fac_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); + + MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(tls_data); + + if (mr->extract_type == MR_EXTRACT_MESH) { + data->edge_loop_count = static_cast<uchar *>( + MEM_callocN(sizeof(uint32_t) * mr->edge_len, __func__)); + + /* HACK(fclem) Detecting the need for edge render. + * We could have a flag in the mesh instead or check the modifier stack. */ + const MEdge *med = mr->medge; + for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) { + if ((med->flag & ME_EDGERENDER) == 0) { + data->use_edge_render = true; + break; + } + } + } + else { + /* HACK to bypass non-manifold check in mesh_edge_fac_finish(). */ + data->use_edge_render = true; + } + + data->vbo_data = static_cast<uchar *>(GPU_vertbuf_get_data(vbo)); +} + +static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + + if (BM_edge_is_manifold(l_iter->e)) { + float ratio = loop_edge_factor_get(bm_face_no_get(mr, f), + bm_vert_co_get(mr, l_iter->v), + bm_vert_no_get(mr, l_iter->v), + bm_vert_co_get(mr, l_iter->next->v)); + data->vbo_data[l_index] = ratio * 253 + 1; + } + else { + data->vbo_data[l_index] = 255; + } + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *_data) +{ + MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data); + + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + + if (data->use_edge_render) { + const MEdge *med = &mr->medge[ml->e]; + data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0; + } + else { + + /* Count loop per edge to detect non-manifold. */ + if (data->edge_loop_count[ml->e] < 3) { + data->edge_loop_count[ml->e]++; + } + if (data->edge_loop_count[ml->e] == 2) { + /* Manifold */ + const int ml_index_last = mp->totloop + mp->loopstart - 1; + const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); + const MLoop *ml_next = &mr->mloop[ml_index_other]; + const MVert *v1 = &mr->mvert[ml->v]; + const MVert *v2 = &mr->mvert[ml_next->v]; + float vnor_f[3]; + normal_short_to_float_v3(vnor_f, v1->no); + float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co); + data->vbo_data[ml_index] = ratio * 253 + 1; + } + else { + /* Non-manifold */ + data->vbo_data[ml_index] = 255; + } + } + } +} + +static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr, + const BMEdge *UNUSED(eed), + const int ledge_index, + void *_data) +{ + MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data); + data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255; + data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255; +} + +static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr, + const MEdge *UNUSED(med), + const int ledge_index, + void *_data) +{ + MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data); + + data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255; + data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255; +} + +static void extract_edge_fac_finish(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data); + + if (GPU_crappy_amd_driver()) { + /* Some AMD drivers strangely crash with VBO's with a one byte format. + * To workaround we reinitialize the VBO with another format and convert + * all bytes to floats. */ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + /* We keep the data reference in data->vbo_data. */ + data->vbo_data = static_cast<uchar *>(GPU_vertbuf_steal_data(vbo)); + GPU_vertbuf_clear(vbo); + + int buf_len = mr->loop_len + mr->loop_loose_len; + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, buf_len); + + float *fdata = (float *)GPU_vertbuf_get_data(vbo); + for (int ml_index = 0; ml_index < buf_len; ml_index++, fdata++) { + *fdata = data->vbo_data[ml_index] / 255.0f; + } + /* Free old byte data. */ + MEM_freeN(data->vbo_data); + } + MEM_SAFE_FREE(data->edge_loop_count); +} + +constexpr MeshExtract create_extractor_edge_fac() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_edge_fac_init; + extractor.iter_poly_bm = extract_edge_fac_iter_poly_bm; + extractor.iter_poly_mesh = extract_edge_fac_iter_poly_mesh; + extractor.iter_ledge_bm = extract_edge_fac_iter_ledge_bm; + extractor.iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh; + extractor.finish = extract_edge_fac_finish; + extractor.data_type = MR_DATA_POLY_NOR; + extractor.data_size = sizeof(MeshExtract_EdgeFac_Data); + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_edge_fac = blender::draw::create_extractor_edge_fac(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc new file mode 100644 index 00000000000..ff250a30ec4 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc @@ -0,0 +1,265 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" +#include "draw_cache_impl.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Edit Mode Data / Flags + * \{ */ + +static void mesh_render_data_edge_flag(const MeshRenderData *mr, + const BMEdge *eed, + EditLoopData *eattr) +{ + const ToolSettings *ts = mr->toolsettings; + const bool is_vertex_select_mode = (ts != nullptr) && (ts->selectmode & SCE_SELECT_VERTEX) != 0; + const bool is_face_only_select_mode = (ts != nullptr) && (ts->selectmode == SCE_SELECT_FACE); + + if (eed == mr->eed_act) { + eattr->e_flag |= VFLAG_EDGE_ACTIVE; + } + if (!is_vertex_select_mode && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + eattr->e_flag |= VFLAG_EDGE_SELECTED; + } + if (is_vertex_select_mode && BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) && + BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) { + eattr->e_flag |= VFLAG_EDGE_SELECTED; + eattr->e_flag |= VFLAG_VERT_SELECTED; + } + if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) { + eattr->e_flag |= VFLAG_EDGE_SEAM; + } + if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) { + eattr->e_flag |= VFLAG_EDGE_SHARP; + } + + /* Use active edge color for active face edges because + * specular highlights make it hard to see T55456#510873. + * + * This isn't ideal since it can't be used when mixing edge/face modes + * but it's still better than not being able to see the active face. */ + if (is_face_only_select_mode) { + if (mr->efa_act != nullptr) { + if (BM_edge_in_face(eed, mr->efa_act)) { + eattr->e_flag |= VFLAG_EDGE_ACTIVE; + } + } + } + + /* Use a byte for value range */ + if (mr->crease_ofs != -1) { + float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->crease_ofs); + if (crease > 0) { + eattr->crease = (uchar)(crease * 255.0f); + } + } + /* Use a byte for value range */ + if (mr->bweight_ofs != -1) { + float bweight = BM_ELEM_CD_GET_FLOAT(eed, mr->bweight_ofs); + if (bweight > 0) { + eattr->bweight = (uchar)(bweight * 255.0f); + } + } +#ifdef WITH_FREESTYLE + if (mr->freestyle_edge_ofs != -1) { + const FreestyleEdge *fed = (const FreestyleEdge *)BM_ELEM_CD_GET_VOID_P( + eed, mr->freestyle_edge_ofs); + if (fed->flag & FREESTYLE_EDGE_MARK) { + eattr->e_flag |= VFLAG_EDGE_FREESTYLE; + } + } +#endif +} + +static void mesh_render_data_vert_flag(const MeshRenderData *mr, + const BMVert *eve, + EditLoopData *eattr) +{ + if (eve == mr->eve_act) { + eattr->e_flag |= VFLAG_VERT_ACTIVE; + } + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + eattr->e_flag |= VFLAG_VERT_SELECTED; + } +} + +static void extract_edit_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* WARNING: Adjust #EditLoopData struct accordingly. */ + GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); + GPU_vertformat_alias_add(&format, "flag"); + } + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); + EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); + *(EditLoopData **)tls_data = vbo_data; +} + +static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + EditLoopData *vbo_data = *(EditLoopData **)_data; + + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + + EditLoopData *data = vbo_data + l_index; + memset(data, 0x0, sizeof(*data)); + mesh_render_data_face_flag(mr, f, -1, data); + mesh_render_data_edge_flag(mr, l_iter->e, data); + mesh_render_data_vert_flag(mr, l_iter->v, data); + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *_data) +{ + EditLoopData *vbo_data = *(EditLoopData **)_data; + + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + EditLoopData *data = vbo_data + ml_index; + memset(data, 0x0, sizeof(*data)); + BMFace *efa = bm_original_face_get(mr, mp_index); + BMEdge *eed = bm_original_edge_get(mr, ml->e); + BMVert *eve = bm_original_vert_get(mr, ml->v); + if (efa) { + mesh_render_data_face_flag(mr, efa, -1, data); + } + if (eed) { + mesh_render_data_edge_flag(mr, eed, data); + } + if (eve) { + mesh_render_data_vert_flag(mr, eve, data); + } + } +} + +static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr, + const BMEdge *eed, + const int ledge_index, + void *_data) +{ + EditLoopData *vbo_data = *(EditLoopData **)_data; + EditLoopData *data = vbo_data + mr->loop_len + (ledge_index * 2); + memset(data, 0x0, sizeof(*data) * 2); + mesh_render_data_edge_flag(mr, eed, &data[0]); + data[1] = data[0]; + mesh_render_data_vert_flag(mr, eed->v1, &data[0]); + mesh_render_data_vert_flag(mr, eed->v2, &data[1]); +} + +static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr, + const MEdge *med, + const int ledge_index, + void *_data) +{ + EditLoopData *vbo_data = *(EditLoopData **)_data; + EditLoopData *data = vbo_data + mr->loop_len + ledge_index * 2; + memset(data, 0x0, sizeof(*data) * 2); + const int e_index = mr->ledges[ledge_index]; + BMEdge *eed = bm_original_edge_get(mr, e_index); + BMVert *eve1 = bm_original_vert_get(mr, med->v1); + BMVert *eve2 = bm_original_vert_get(mr, med->v2); + if (eed) { + mesh_render_data_edge_flag(mr, eed, &data[0]); + data[1] = data[0]; + } + if (eve1) { + mesh_render_data_vert_flag(mr, eve1, &data[0]); + } + if (eve2) { + mesh_render_data_vert_flag(mr, eve2, &data[1]); + } +} + +static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr, + const BMVert *eve, + const int lvert_index, + void *_data) +{ + EditLoopData *vbo_data = *(EditLoopData **)_data; + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EditLoopData *data = vbo_data + offset + lvert_index; + memset(data, 0x0, sizeof(*data)); + mesh_render_data_vert_flag(mr, eve, data); +} + +static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, + const MVert *UNUSED(mv), + const int lvert_index, + void *_data) +{ + EditLoopData *vbo_data = *(EditLoopData **)_data; + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + + EditLoopData *data = vbo_data + offset + lvert_index; + memset(data, 0x0, sizeof(*data)); + const int v_index = mr->lverts[lvert_index]; + BMVert *eve = bm_original_vert_get(mr, v_index); + if (eve) { + mesh_render_data_vert_flag(mr, eve, data); + } +} + +constexpr MeshExtract create_extractor_edit_data() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_edit_data_init; + extractor.iter_poly_bm = extract_edit_data_iter_poly_bm; + extractor.iter_poly_mesh = extract_edit_data_iter_poly_mesh; + extractor.iter_ledge_bm = extract_edit_data_iter_ledge_bm; + extractor.iter_ledge_mesh = extract_edit_data_iter_ledge_mesh; + extractor.iter_lvert_bm = extract_edit_data_iter_lvert_bm; + extractor.iter_lvert_mesh = extract_edit_data_iter_lvert_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(EditLoopData *); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_edit_data = blender::draw::create_extractor_edit_data(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc new file mode 100644 index 00000000000..aa58266d56b --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc @@ -0,0 +1,140 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" +#include "draw_cache_impl.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Edit UV Data / Flags + * \{ */ + +struct MeshExtract_EditUVData_Data { + EditLoopData *vbo_data; + int cd_ofs; +}; + +static void extract_edituv_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* WARNING: Adjust #EditLoopData struct accordingly. */ + GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); + GPU_vertformat_alias_add(&format, "flag"); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + + MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(tls_data); + data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); + data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); +} + +static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data); + EditLoopData *eldata = &data->vbo_data[l_index]; + memset(eldata, 0x0, sizeof(*eldata)); + mesh_render_data_loop_flag(mr, l_iter, data->cd_ofs, eldata); + mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); + mesh_render_data_loop_edge_flag(mr, l_iter, data->cd_ofs, eldata); + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *_data) +{ + MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data); + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + + EditLoopData *eldata = &data->vbo_data[ml_index]; + memset(eldata, 0x0, sizeof(*eldata)); + BMFace *efa = bm_original_face_get(mr, mp_index); + if (efa) { + BMEdge *eed = bm_original_edge_get(mr, ml->e); + BMVert *eve = bm_original_vert_get(mr, ml->v); + if (eed && eve) { + /* Loop on an edge endpoint. */ + BMLoop *l = BM_face_edge_share_loop(efa, eed); + mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata); + mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); + } + else { + if (eed == nullptr) { + /* Find if the loop's vert is not part of an edit edge. + * For this, we check if the previous loop was on an edge. */ + const int ml_index_last = mp->loopstart + mp->totloop - 1; + const int l_prev = (ml_index == mp->loopstart) ? ml_index_last : (ml_index - 1); + const MLoop *ml_prev = &mr->mloop[l_prev]; + eed = bm_original_edge_get(mr, ml_prev->e); + } + if (eed) { + /* Mapped points on an edge between two edit verts. */ + BMLoop *l = BM_face_edge_share_loop(efa, eed); + mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); + } + } + } + } +} + +constexpr MeshExtract create_extractor_edituv_data() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_edituv_data_init; + extractor.iter_poly_bm = extract_edituv_data_iter_poly_bm; + extractor.iter_poly_mesh = extract_edituv_data_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_EditUVData_Data); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_edituv_data = blender::draw::create_extractor_edituv_data(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc new file mode 100644 index 00000000000..1d62637d172 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc @@ -0,0 +1,236 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BKE_mesh.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Edit UV angle stretch + * \{ */ + +struct UVStretchAngle { + int16_t angle; + int16_t uv_angles[2]; +}; + +struct MeshExtract_StretchAngle_Data { + UVStretchAngle *vbo_data; + MLoopUV *luv; + float auv[2][2], last_auv[2]; + float av[2][3], last_av[3]; + int cd_ofs; +}; + +static void compute_normalize_edge_vectors(float auv[2][2], + float av[2][3], + const float uv[2], + const float uv_prev[2], + const float co[3], + const float co_prev[3]) +{ + /* Move previous edge. */ + copy_v2_v2(auv[0], auv[1]); + copy_v3_v3(av[0], av[1]); + /* 2d edge */ + sub_v2_v2v2(auv[1], uv_prev, uv); + normalize_v2(auv[1]); + /* 3d edge */ + sub_v3_v3v3(av[1], co_prev, co); + normalize_v3(av[1]); +} + +static short v2_to_short_angle(const float v[2]) +{ + return atan2f(v[1], v[0]) * (float)M_1_PI * SHRT_MAX; +} + +static void edituv_get_edituv_stretch_angle(float auv[2][2], + const float av[2][3], + UVStretchAngle *r_stretch) +{ + /* Send UV's to the shader and let it compute the aspect corrected angle. */ + r_stretch->uv_angles[0] = v2_to_short_angle(auv[0]); + r_stretch->uv_angles[1] = v2_to_short_angle(auv[1]); + /* Compute 3D angle here. */ + r_stretch->angle = angle_normalized_v3v3(av[0], av[1]) * (float)M_1_PI * SHRT_MAX; + +#if 0 /* here for reference, this is done in shader now. */ + float uvang = angle_normalized_v2v2(auv0, auv1); + float ang = angle_normalized_v3v3(av0, av1); + float stretch = fabsf(uvang - ang) / (float)M_PI; + return 1.0f - pow2f(1.0f - stretch); +#endif +} + +static void extract_edituv_stretch_angle_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* Waning: adjust #UVStretchAngle struct accordingly. */ + GPU_vertformat_attr_add(&format, "angle", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + MeshExtract_StretchAngle_Data *data = static_cast<MeshExtract_StretchAngle_Data *>(tls_data); + data->vbo_data = (UVStretchAngle *)GPU_vertbuf_get_data(vbo); + + /* Special iterator needed to save about half of the computing cost. */ + if (mr->extract_type == MR_EXTRACT_BMESH) { + data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); + } + else { + BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); + data->luv = (MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); + } +} + +static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + MeshExtract_StretchAngle_Data *data = static_cast<MeshExtract_StretchAngle_Data *>(_data); + float(*auv)[2] = data->auv, *last_auv = data->last_auv; + float(*av)[3] = data->av, *last_av = data->last_av; + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + + const MLoopUV *luv, *luv_next; + BMLoop *l_next = l_iter->next; + if (l_iter == BM_FACE_FIRST_LOOP(f)) { + /* First loop in face. */ + BMLoop *l_tmp = l_iter->prev; + BMLoop *l_next_tmp = l_iter; + luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs); + luv_next = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs); + compute_normalize_edge_vectors(auv, + av, + luv->uv, + luv_next->uv, + bm_vert_co_get(mr, l_tmp->v), + bm_vert_co_get(mr, l_next_tmp->v)); + /* Save last edge. */ + copy_v2_v2(last_auv, auv[1]); + copy_v3_v3(last_av, av[1]); + } + if (l_next == BM_FACE_FIRST_LOOP(f)) { + /* Move previous edge. */ + copy_v2_v2(auv[0], auv[1]); + copy_v3_v3(av[0], av[1]); + /* Copy already calculated last edge. */ + copy_v2_v2(auv[1], last_auv); + copy_v3_v3(av[1], last_av); + } + else { + luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs); + luv_next = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs); + compute_normalize_edge_vectors(auv, + av, + luv->uv, + luv_next->uv, + bm_vert_co_get(mr, l_iter->v), + bm_vert_co_get(mr, l_next->v)); + } + edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]); + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int UNUSED(mp_index), + void *_data) +{ + MeshExtract_StretchAngle_Data *data = static_cast<MeshExtract_StretchAngle_Data *>(_data); + + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + float(*auv)[2] = data->auv, *last_auv = data->last_auv; + float(*av)[3] = data->av, *last_av = data->last_av; + int l_next = ml_index + 1; + const MVert *v, *v_next; + if (ml_index == mp->loopstart) { + /* First loop in face. */ + const int ml_index_last = ml_index_end - 1; + const int l_next_tmp = mp->loopstart; + v = &mr->mvert[mr->mloop[ml_index_last].v]; + v_next = &mr->mvert[mr->mloop[l_next_tmp].v]; + compute_normalize_edge_vectors( + auv, av, data->luv[ml_index_last].uv, data->luv[l_next_tmp].uv, v->co, v_next->co); + /* Save last edge. */ + copy_v2_v2(last_auv, auv[1]); + copy_v3_v3(last_av, av[1]); + } + if (l_next == ml_index_end) { + l_next = mp->loopstart; + /* Move previous edge. */ + copy_v2_v2(auv[0], auv[1]); + copy_v3_v3(av[0], av[1]); + /* Copy already calculated last edge. */ + copy_v2_v2(auv[1], last_auv); + copy_v3_v3(av[1], last_av); + } + else { + v = &mr->mvert[mr->mloop[ml_index].v]; + v_next = &mr->mvert[mr->mloop[l_next].v]; + compute_normalize_edge_vectors( + auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co); + } + edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]); + } +} + +constexpr MeshExtract create_extractor_edituv_edituv_stretch_angle() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_edituv_stretch_angle_init; + extractor.iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm; + extractor.iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_StretchAngle_Data); + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_edituv_stretch_angle = + blender::draw::create_extractor_edituv_edituv_stretch_angle(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc new file mode 100644 index 00000000000..16814653408 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc @@ -0,0 +1,157 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BKE_mesh.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Edit UV area stretch + * \{ */ + +static void extract_edituv_stretch_area_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); +} + +BLI_INLINE float area_ratio_get(float area, float uvarea) +{ + if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) { + /* Tag inversion by using the sign. */ + return (area > uvarea) ? (uvarea / area) : -(area / uvarea); + } + return 0.0f; +} + +BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio) +{ + ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio; + return (ratio > 1.0f) ? (1.0f / ratio) : ratio; +} + +static void extract_edituv_stretch_area_finish(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + float tot_area = 0.0f, tot_uv_area = 0.0f; + float *area_ratio = static_cast<float *>(MEM_mallocN(sizeof(float) * mr->poly_len, __func__)); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + CustomData *cd_ldata = &mr->bm->ldata; + int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); + + BMFace *efa; + BMIter f_iter; + int f; + BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { + float area = BM_face_calc_area(efa); + float uvarea = BM_face_calc_area_uv(efa, uv_ofs); + tot_area += area; + tot_uv_area += uvarea; + area_ratio[f] = area_ratio_get(area, uvarea); + } + } + else { + BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); + const MLoopUV *uv_data = (const MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); + const MPoly *mp = mr->mpoly; + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert); + float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data); + tot_area += area; + tot_uv_area += uvarea; + area_ratio[mp_index] = area_ratio_get(area, uvarea); + } + } + + cache->tot_area = tot_area; + cache->tot_uv_area = tot_uv_area; + + /* Convert in place to avoid an extra allocation */ + uint16_t *poly_stretch = (uint16_t *)area_ratio; + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { + poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX; + } + + /* Copy face data for each loop. */ + uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMFace *efa; + BMIter f_iter; + int f, l_index = 0; + BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { + for (int i = 0; i < efa->len; i++, l_index++) { + loop_stretch[l_index] = poly_stretch[f]; + } + } + } + else { + BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + for (int i = 0; i < mp->totloop; i++, l_index++) { + loop_stretch[l_index] = poly_stretch[mp_index]; + } + } + } + + MEM_freeN(area_ratio); +} + +constexpr MeshExtract create_extractor_edituv_stretch_area() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_edituv_stretch_area_init; + extractor.finish = extract_edituv_stretch_area_finish; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_edituv_stretch_area = + blender::draw::create_extractor_edituv_stretch_area(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc new file mode 100644 index 00000000000..5a988c73a7e --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" +#include "draw_cache_impl.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Face-dots Edit UV flag + * \{ */ + +struct MeshExtract_EditUVFdotData_Data { + EditLoopData *vbo_data; + int cd_ofs; +}; + +static void extract_fdots_edituv_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U8, 4, GPU_FETCH_INT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->poly_len); + + MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(tls_data); + data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); + data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); +} + +static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(_data); + EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)]; + memset(eldata, 0x0, sizeof(*eldata)); + mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); +} + +static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *UNUSED(mp), + const int mp_index, + void *_data) +{ + MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(_data); + EditLoopData *eldata = &data->vbo_data[mp_index]; + memset(eldata, 0x0, sizeof(*eldata)); + BMFace *efa = bm_original_face_get(mr, mp_index); + if (efa) { + mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata); + } +} + +constexpr MeshExtract create_extractor_fdots_edituv_data() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_fdots_edituv_data_init; + extractor.iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm; + extractor.iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_EditUVFdotData_Data); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_fdots_edituv_data = blender::draw::create_extractor_fdots_edituv_data(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc new file mode 100644 index 00000000000..fb9d34e7733 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc @@ -0,0 +1,200 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Face-dots Normal and edit flag + * \{ */ +#define NOR_AND_FLAG_DEFAULT 0 +#define NOR_AND_FLAG_SELECT 1 +#define NOR_AND_FLAG_ACTIVE -1 +#define NOR_AND_FLAG_HIDDEN -2 + +static void extract_fdots_nor_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->poly_len); +} + +static void extract_fdots_nor_finish(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; + GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo); + BMFace *efa; + + /* Quicker than doing it for each loop. */ + if (mr->extract_type == MR_EXTRACT_BMESH) { + for (int f = 0; f < mr->poly_len; f++) { + efa = BM_face_at_index(mr->bm, f); + const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); + if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && + mr->p_origindex[f] == ORIGINDEX_NONE)) { + nor[f] = GPU_normal_convert_i10_v3(invalid_normal); + nor[f].w = NOR_AND_FLAG_HIDDEN; + } + else { + nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa)); + /* Select / Active Flag. */ + nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? + ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : + NOR_AND_FLAG_DEFAULT); + } + } + } + else { + for (int f = 0; f < mr->poly_len; f++) { + efa = bm_original_face_get(mr, f); + const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN); + if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && + mr->p_origindex[f] == ORIGINDEX_NONE)) { + nor[f] = GPU_normal_convert_i10_v3(invalid_normal); + nor[f].w = NOR_AND_FLAG_HIDDEN; + } + else { + nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa)); + /* Select / Active Flag. */ + nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? + ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : + NOR_AND_FLAG_DEFAULT); + } + } + } +} + +constexpr MeshExtract create_extractor_fdots_nor() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_fdots_nor_init; + extractor.finish = extract_fdots_nor_finish; + extractor.data_type = MR_DATA_LOOP_NOR; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor); + return extractor; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Extract Face-dots High Quality Normal and edit flag + * \{ */ +static void extract_fdots_nor_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->poly_len); +} + +static void extract_fdots_nor_hq_finish(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; + short *nor = (short *)GPU_vertbuf_get_data(vbo); + BMFace *efa; + + /* Quicker than doing it for each loop. */ + if (mr->extract_type == MR_EXTRACT_BMESH) { + for (int f = 0; f < mr->poly_len; f++) { + efa = BM_face_at_index(mr->bm, f); + const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); + if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && + mr->p_origindex[f] == ORIGINDEX_NONE)) { + normal_float_to_short_v3(&nor[f * 4], invalid_normal); + nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN; + } + else { + normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa)); + /* Select / Active Flag. */ + nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? + ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : + NOR_AND_FLAG_DEFAULT); + } + } + } + else { + for (int f = 0; f < mr->poly_len; f++) { + efa = bm_original_face_get(mr, f); + const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN); + if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && + mr->p_origindex[f] == ORIGINDEX_NONE)) { + normal_float_to_short_v3(&nor[f * 4], invalid_normal); + nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN; + } + else { + normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa)); + /* Select / Active Flag. */ + nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? + ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : + NOR_AND_FLAG_DEFAULT); + } + } + } +} + +constexpr MeshExtract create_extractor_fdots_nor_hq() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_fdots_nor_hq_init; + extractor.finish = extract_fdots_nor_hq_finish; + extractor.data_type = MR_DATA_LOOP_NOR; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_fdots_nor = blender::draw::create_extractor_fdots_nor(); +const MeshExtract extract_fdots_nor_hq = blender::draw::create_extractor_fdots_nor_hq(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc new file mode 100644 index 00000000000..c4706c412c6 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc @@ -0,0 +1,119 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Face-dots positions + * \{ */ + +static void extract_fdots_pos_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->poly_len); + void *vbo_data = GPU_vertbuf_get_data(vbo); + *(float(**)[3])tls_data = static_cast<float(*)[3]>(vbo_data); +} + +static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int f_index, + void *data) +{ + float(*center)[3] = *static_cast<float(**)[3]>(data); + + float *co = center[f_index]; + zero_v3(co); + + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_v3_v3(co, bm_vert_co_get(mr, l_iter->v)); + } while ((l_iter = l_iter->next) != l_first); + mul_v3_fl(co, 1.0f / (float)f->len); +} + +static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *data) +{ + float(*center)[3] = *static_cast<float(**)[3]>(data); + float *co = center[mp_index]; + zero_v3(co); + + const MVert *mvert = mr->mvert; + const MLoop *mloop = mr->mloop; + + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + if (mr->use_subsurf_fdots) { + const MVert *mv = &mr->mvert[ml->v]; + if (mv->flag & ME_VERT_FACEDOT) { + copy_v3_v3(center[mp_index], mv->co); + break; + } + } + else { + const MVert *mv = &mvert[ml->v]; + add_v3_v3(center[mp_index], mv->co); + } + } + + if (!mr->use_subsurf_fdots) { + mul_v3_fl(co, 1.0f / (float)mp->totloop); + } +} + +constexpr MeshExtract create_extractor_fdots_pos() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_fdots_pos_init; + extractor.iter_poly_bm = extract_fdots_pos_iter_poly_bm; + extractor.iter_poly_mesh = extract_fdots_pos_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(float(*)[3]); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_fdots_pos = blender::draw::create_extractor_fdots_pos(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc new file mode 100644 index 00000000000..0289fd63a30 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc @@ -0,0 +1,127 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Face-dots UV + * \{ */ + +struct MeshExtract_FdotUV_Data { + float (*vbo_data)[2]; + MLoopUV *uv_data; + int cd_ofs; +}; + +static void extract_fdots_uv_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPU_vertformat_alias_add(&format, "au"); + GPU_vertformat_alias_add(&format, "pos"); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->poly_len); + + if (!mr->use_subsurf_fdots) { + /* Clear so we can accumulate on it. */ + memset(GPU_vertbuf_get_data(vbo), 0x0, mr->poly_len * GPU_vertbuf_get_format(vbo)->stride); + } + + MeshExtract_FdotUV_Data *data = static_cast<MeshExtract_FdotUV_Data *>(tls_data); + data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); + } + else { + data->uv_data = (MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); + } +} + +static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *UNUSED(mr), + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + MeshExtract_FdotUV_Data *data = static_cast<MeshExtract_FdotUV_Data *>(_data); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + float w = 1.0f / (float)f->len; + const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs); + madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv->uv, w); + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *_data) +{ + MeshExtract_FdotUV_Data *data = static_cast<MeshExtract_FdotUV_Data *>(_data); + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + if (mr->use_subsurf_fdots) { + const MVert *mv = &mr->mvert[ml->v]; + if (mv->flag & ME_VERT_FACEDOT) { + copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv); + } + } + else { + float w = 1.0f / (float)mp->totloop; + madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w); + } + } +} + +constexpr MeshExtract create_extractor_fdots_uv() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_fdots_uv_init; + extractor.iter_poly_bm = extract_fdots_uv_iter_poly_bm; + extractor.iter_poly_mesh = extract_fdots_uv_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_FdotUV_Data); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_fdots_uv = blender::draw::create_extractor_fdots_uv(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc new file mode 100644 index 00000000000..b942068352b --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -0,0 +1,228 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Loop Normal + * \{ */ + +static void extract_lnor_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_alias_add(&format, "lnor"); + } + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + *(GPUPackedNormal **)tls_data = static_cast<GPUPackedNormal *>(GPU_vertbuf_get_data(vbo)); +} + +static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *data) +{ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + if (mr->loop_normals) { + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); + } + else { + if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3( + bm_vert_no_get(mr, l_iter->v)); + } + else { + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f)); + } + } + (*(GPUPackedNormal **)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *data) +{ + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; + if (mr->loop_normals) { + *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); + } + else if (mp->flag & ME_SMOOTH) { + *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no); + } + else { + *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]); + } + + /* Flag for paint mode overlay. + * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. + * In paint mode it will use the un-mapped data to draw the wire-frame. */ + if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && + (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + lnor_data->w = -1; + } + else if (mp->flag & ME_FACE_SEL) { + lnor_data->w = 1; + } + else { + lnor_data->w = 0; + } + } +} + +constexpr MeshExtract create_extractor_lnor() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_lnor_init; + extractor.iter_poly_bm = extract_lnor_iter_poly_bm; + extractor.iter_poly_mesh = extract_lnor_iter_poly_mesh; + extractor.data_type = MR_DATA_LOOP_NOR; + extractor.data_size = sizeof(GPUPackedNormal *); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor); + return extractor; +} + +/** \} */ +/* ---------------------------------------------------------------------- */ +/** \name Extract HQ Loop Normal + * \{ */ + +struct gpuHQNor { + short x, y, z, w; +}; + +static void extract_lnor_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_alias_add(&format, "lnor"); + } + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + *(gpuHQNor **)tls_data = static_cast<gpuHQNor *>(GPU_vertbuf_get_data(vbo)); +} + +static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *data) +{ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + if (mr->loop_normals) { + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]); + } + else { + if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_vert_no_get(mr, l_iter->v)); + } + else { + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_face_no_get(mr, f)); + } + } + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *data) +{ + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; + if (mr->loop_normals) { + normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); + } + else if (mp->flag & ME_SMOOTH) { + copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no); + } + else { + normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]); + } + + /* Flag for paint mode overlay. + * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. + * In paint mode it will use the un-mapped data to draw the wire-frame. */ + if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && + (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + lnor_data->w = -1; + } + else if (mp->flag & ME_FACE_SEL) { + lnor_data->w = 1; + } + else { + lnor_data->w = 0; + } + } +} + +constexpr MeshExtract create_extractor_lnor_hq() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_lnor_hq_init; + extractor.iter_poly_bm = extract_lnor_hq_iter_poly_bm; + extractor.iter_poly_mesh = extract_lnor_hq_iter_poly_mesh; + extractor.data_type = MR_DATA_LOOP_NOR; + extractor.data_size = sizeof(gpuHQNor *); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_lnor = blender::draw::create_extractor_lnor(); +const MeshExtract extract_lnor_hq = blender::draw::create_extractor_lnor_hq(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc new file mode 100644 index 00000000000..b734061b76a --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc @@ -0,0 +1,654 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_edgehash.h" +#include "BLI_jitter_2d.h" + +#include "BKE_bvhutils.h" +#include "BKE_editmesh_bvh.h" +#include "BKE_editmesh_cache.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Edit Mesh Analysis Colors + * \{ */ + +static void extract_mesh_analysis_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); +} + +static void axis_from_enum_v3(float v[3], const char axis) +{ + zero_v3(v); + if (axis < 3) { + v[axis] = 1.0f; + } + else { + v[axis - 3] = -1.0f; + } +} + +BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange) +{ + if (fac < min) { + fac = 1.0f; + } + else if (fac > max) { + fac = -1.0f; + } + else { + fac = (fac - min) * minmax_irange; + fac = 1.0f - fac; + CLAMP(fac, 0.0f, 1.0f); + } + return fac; +} + +static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang) +{ + const MeshStatVis *statvis = &mr->toolsettings->statvis; + const float min = statvis->overhang_min / (float)M_PI; + const float max = statvis->overhang_max / (float)M_PI; + const char axis = statvis->overhang_axis; + BMEditMesh *em = mr->edit_bmesh; + BMIter iter; + BMesh *bm = em->bm; + BMFace *f; + float dir[3]; + const float minmax_irange = 1.0f / (max - min); + + BLI_assert(min <= max); + + axis_from_enum_v3(dir, axis); + + /* now convert into global space */ + mul_transposed_mat3_m4_v3(mr->obmat, dir); + normalize_v3(dir); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + int l_index = 0; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI; + fac = overhang_remap(fac, min, max, minmax_irange); + for (int i = 0; i < f->len; i++, l_index++) { + r_overhang[l_index] = fac; + } + } + } + else { + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI; + fac = overhang_remap(fac, min, max, minmax_irange); + for (int i = 0; i < mp->totloop; i++, l_index++) { + r_overhang[l_index] = fac; + } + } + } +} + +/** + * Needed so we can use jitter values for face interpolation. + */ +static void uv_from_jitter_v2(float uv[2]) +{ + uv[0] += 0.5f; + uv[1] += 0.5f; + if (uv[0] + uv[1] > 1.0f) { + uv[0] = 1.0f - uv[0]; + uv[1] = 1.0f - uv[1]; + } + + clamp_v2(uv, 0.0f, 1.0f); +} + +BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange) +{ + /* important not '<=' */ + if (fac < max) { + fac = (fac - min) * minmax_irange; + fac = 1.0f - fac; + CLAMP(fac, 0.0f, 1.0f); + } + else { + fac = -1.0f; + } + return fac; +} + +static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) +{ + const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */ + /* cheating to avoid another allocation */ + float *face_dists = r_thickness + (mr->loop_len - mr->poly_len); + BMEditMesh *em = mr->edit_bmesh; + const float scale = 1.0f / mat4_to_scale(mr->obmat); + const MeshStatVis *statvis = &mr->toolsettings->statvis; + const float min = statvis->thickness_min * scale; + const float max = statvis->thickness_max * scale; + const float minmax_irange = 1.0f / (max - min); + const int samples = statvis->thickness_samples; + float jit_ofs[32][2]; + BLI_assert(samples <= 32); + BLI_assert(min <= max); + + copy_vn_fl(face_dists, mr->poly_len, max); + + BLI_jitter_init(jit_ofs, samples); + for (int j = 0; j < samples; j++) { + uv_from_jitter_v2(jit_ofs[j]); + } + + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMesh *bm = em->bm; + BM_mesh_elem_index_ensure(bm, BM_FACE); + + struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false); + struct BMLoop *(*looptris)[3] = em->looptris; + for (int i = 0; i < mr->tri_len; i++) { + BMLoop **ltri = looptris[i]; + const int index = BM_elem_index_get(ltri[0]->f); + const float *cos[3] = { + bm_vert_co_get(mr, ltri[0]->v), + bm_vert_co_get(mr, ltri[1]->v), + bm_vert_co_get(mr, ltri[2]->v), + }; + float ray_co[3]; + float ray_no[3]; + + normal_tri_v3(ray_no, cos[2], cos[1], cos[0]); + + for (int j = 0; j < samples; j++) { + float dist = face_dists[index]; + interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]); + madd_v3_v3fl(ray_co, ray_no, eps_offset); + + BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, nullptr, nullptr); + if (f_hit && dist < face_dists[index]) { + float angle_fac = fabsf( + dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit))); + angle_fac = 1.0f - angle_fac; + angle_fac = angle_fac * angle_fac * angle_fac; + angle_fac = 1.0f - angle_fac; + dist /= angle_fac; + if (dist < face_dists[index]) { + face_dists[index] = dist; + } + } + } + } + BKE_bmbvh_free(bmtree); + + BMIter iter; + BMFace *f; + int l_index = 0; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + float fac = face_dists[BM_elem_index_get(f)]; + fac = thickness_remap(fac, min, max, minmax_irange); + for (int i = 0; i < f->len; i++, l_index++) { + r_thickness[l_index] = fac; + } + } + } + else { + BVHTreeFromMesh treeData = {nullptr}; + + BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4); + const MLoopTri *mlooptri = mr->mlooptri; + for (int i = 0; i < mr->tri_len; i++, mlooptri++) { + const int index = mlooptri->poly; + const float *cos[3] = {mr->mvert[mr->mloop[mlooptri->tri[0]].v].co, + mr->mvert[mr->mloop[mlooptri->tri[1]].v].co, + mr->mvert[mr->mloop[mlooptri->tri[2]].v].co}; + float ray_co[3]; + float ray_no[3]; + + normal_tri_v3(ray_no, cos[2], cos[1], cos[0]); + + for (int j = 0; j < samples; j++) { + interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]); + madd_v3_v3fl(ray_co, ray_no, eps_offset); + + BVHTreeRayHit hit; + hit.index = -1; + hit.dist = face_dists[index]; + if ((BLI_bvhtree_ray_cast( + tree, ray_co, ray_no, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) && + hit.dist < face_dists[index]) { + float angle_fac = fabsf(dot_v3v3(mr->poly_normals[index], hit.no)); + angle_fac = 1.0f - angle_fac; + angle_fac = angle_fac * angle_fac * angle_fac; + angle_fac = 1.0f - angle_fac; + hit.dist /= angle_fac; + if (hit.dist < face_dists[index]) { + face_dists[index] = hit.dist; + } + } + } + } + + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + float fac = face_dists[mp_index]; + fac = thickness_remap(fac, min, max, minmax_irange); + for (int i = 0; i < mp->totloop; i++, l_index++) { + r_thickness[l_index] = fac; + } + } + } +} + +struct BVHTree_OverlapData { + const Mesh *me; + const MLoopTri *mlooptri; + float epsilon; +}; + +static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread)) +{ + struct BVHTree_OverlapData *data = static_cast<struct BVHTree_OverlapData *>(userdata); + const Mesh *me = data->me; + + const MLoopTri *tri_a = &data->mlooptri[index_a]; + const MLoopTri *tri_b = &data->mlooptri[index_b]; + + if (UNLIKELY(tri_a->poly == tri_b->poly)) { + return false; + } + + const float *tri_a_co[3] = {me->mvert[me->mloop[tri_a->tri[0]].v].co, + me->mvert[me->mloop[tri_a->tri[1]].v].co, + me->mvert[me->mloop[tri_a->tri[2]].v].co}; + const float *tri_b_co[3] = {me->mvert[me->mloop[tri_b->tri[0]].v].co, + me->mvert[me->mloop[tri_b->tri[1]].v].co, + me->mvert[me->mloop[tri_b->tri[2]].v].co}; + float ix_pair[2][3]; + int verts_shared = 0; + + verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) + + ELEM(tri_a_co[2], UNPACK3(tri_b_co))); + + /* if 2 points are shared, bail out */ + if (verts_shared >= 2) { + return false; + } + + return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) && + /* if we share a vertex, check the intersection isn't a 'point' */ + ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon))); +} + +static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) +{ + BMEditMesh *em = mr->edit_bmesh; + + for (int l_index = 0; l_index < mr->loop_len; l_index++) { + r_intersect[l_index] = -1.0f; + } + + if (mr->extract_type == MR_EXTRACT_BMESH) { + uint overlap_len; + BMesh *bm = em->bm; + + BM_mesh_elem_index_ensure(bm, BM_FACE); + + struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false); + BVHTreeOverlap *overlap = BKE_bmbvh_overlap_self(bmtree, &overlap_len); + + if (overlap) { + for (int i = 0; i < overlap_len; i++) { + BMFace *f_hit_pair[2] = { + em->looptris[overlap[i].indexA][0]->f, + em->looptris[overlap[i].indexB][0]->f, + }; + for (int j = 0; j < 2; j++) { + BMFace *f_hit = f_hit_pair[j]; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit); + int l_index = BM_elem_index_get(l_first); + for (int k = 0; k < f_hit->len; k++, l_index++) { + r_intersect[l_index] = 1.0f; + } + } + } + MEM_freeN(overlap); + } + + BKE_bmbvh_free(bmtree); + } + else { + uint overlap_len; + BVHTreeFromMesh treeData = {nullptr}; + + BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4); + + struct BVHTree_OverlapData data = {nullptr}; + data.me = mr->me; + data.mlooptri = mr->mlooptri; + data.epsilon = BLI_bvhtree_get_epsilon(tree); + + BVHTreeOverlap *overlap = BLI_bvhtree_overlap(tree, tree, &overlap_len, bvh_overlap_cb, &data); + if (overlap) { + for (int i = 0; i < overlap_len; i++) { + const MPoly *f_hit_pair[2] = { + &mr->mpoly[mr->mlooptri[overlap[i].indexA].poly], + &mr->mpoly[mr->mlooptri[overlap[i].indexB].poly], + }; + for (int j = 0; j < 2; j++) { + const MPoly *f_hit = f_hit_pair[j]; + int l_index = f_hit->loopstart; + for (int k = 0; k < f_hit->totloop; k++, l_index++) { + r_intersect[l_index] = 1.0f; + } + } + } + MEM_freeN(overlap); + } + } +} + +BLI_INLINE float distort_remap(float fac, float min, float UNUSED(max), float minmax_irange) +{ + if (fac >= min) { + fac = (fac - min) * minmax_irange; + CLAMP(fac, 0.0f, 1.0f); + } + else { + /* fallback */ + fac = -1.0f; + } + return fac; +} + +static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) +{ + BMEditMesh *em = mr->edit_bmesh; + const MeshStatVis *statvis = &mr->toolsettings->statvis; + const float min = statvis->distort_min; + const float max = statvis->distort_max; + const float minmax_irange = 1.0f / (max - min); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMIter iter; + BMesh *bm = em->bm; + BMFace *f; + + if (mr->bm_vert_coords != nullptr) { + BKE_editmesh_cache_ensure_poly_normals(em, mr->edit_data); + + /* Most likely this is already valid, ensure just in case. + * Needed for #BM_loop_calc_face_normal_safe_vcos. */ + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + } + + int l_index = 0; + int f_index = 0; + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) { + float fac = -1.0f; + + if (f->len > 3) { + BMLoop *l_iter, *l_first; + + fac = 0.0f; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const float *no_face; + float no_corner[3]; + if (mr->bm_vert_coords != nullptr) { + no_face = mr->bm_poly_normals[f_index]; + BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner); + } + else { + no_face = f->no; + BM_loop_calc_face_normal_safe(l_iter, no_corner); + } + + /* simple way to detect (what is most likely) concave */ + if (dot_v3v3(no_face, no_corner) < 0.0f) { + negate_v3(no_corner); + } + fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner)); + + } while ((l_iter = l_iter->next) != l_first); + fac *= 2.0f; + } + + fac = distort_remap(fac, min, max, minmax_irange); + for (int i = 0; i < f->len; i++, l_index++) { + r_distort[l_index] = fac; + } + } + } + else { + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + float fac = -1.0f; + + if (mp->totloop > 3) { + float *f_no = mr->poly_normals[mp_index]; + fac = 0.0f; + + for (int i = 1; i <= mp->totloop; i++) { + const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop]; + const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop]; + const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop]; + float no_corner[3]; + normal_tri_v3(no_corner, + mr->mvert[l_prev->v].co, + mr->mvert[l_curr->v].co, + mr->mvert[l_next->v].co); + /* simple way to detect (what is most likely) concave */ + if (dot_v3v3(f_no, no_corner) < 0.0f) { + negate_v3(no_corner); + } + fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner)); + } + fac *= 2.0f; + } + + fac = distort_remap(fac, min, max, minmax_irange); + for (int i = 0; i < mp->totloop; i++, l_index++) { + r_distort[l_index] = fac; + } + } + } +} + +BLI_INLINE float sharp_remap(float fac, float min, float UNUSED(max), float minmax_irange) +{ + /* important not '>=' */ + if (fac > min) { + fac = (fac - min) * minmax_irange; + CLAMP(fac, 0.0f, 1.0f); + } + else { + /* fallback */ + fac = -1.0f; + } + return fac; +} + +static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) +{ + BMEditMesh *em = mr->edit_bmesh; + const MeshStatVis *statvis = &mr->toolsettings->statvis; + const float min = statvis->sharp_min; + const float max = statvis->sharp_max; + const float minmax_irange = 1.0f / (max - min); + + /* Can we avoid this extra allocation? */ + float *vert_angles = (float *)MEM_mallocN(sizeof(float) * mr->vert_len, __func__); + copy_vn_fl(vert_angles, mr->vert_len, -M_PI); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMIter iter; + BMesh *bm = em->bm; + BMFace *efa; + BMEdge *e; + /* first assign float values to verts */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + float angle = BM_edge_calc_face_angle_signed(e); + float *col1 = &vert_angles[BM_elem_index_get(e->v1)]; + float *col2 = &vert_angles[BM_elem_index_get(e->v2)]; + *col1 = max_ff(*col1, angle); + *col2 = max_ff(*col2, angle); + } + /* Copy vert value to loops. */ + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + int l_index = BM_elem_index_get(l_iter); + int v_index = BM_elem_index_get(l_iter->v); + r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange); + } while ((l_iter = l_iter->next) != l_first); + } + } + else { + /* first assign float values to verts */ + const MPoly *mp = mr->mpoly; + + EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len); + + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + for (int i = 0; i < mp->totloop; i++) { + const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop]; + const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop]; + const MVert *v_curr = &mr->mvert[l_curr->v]; + const MVert *v_next = &mr->mvert[l_next->v]; + float angle; + void **pval; + bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval); + if (!value_is_init) { + *pval = mr->poly_normals[mp_index]; + /* non-manifold edge, yet... */ + continue; + } + if (*pval != nullptr) { + const float *f1_no = mr->poly_normals[mp_index]; + const float *f2_no = static_cast<const float *>(*pval); + angle = angle_normalized_v3v3(f1_no, f2_no); + angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle; + /* Tag as manifold. */ + *pval = nullptr; + } + else { + /* non-manifold edge */ + angle = DEG2RADF(90.0f); + } + float *col1 = &vert_angles[l_curr->v]; + float *col2 = &vert_angles[l_next->v]; + *col1 = max_ff(*col1, angle); + *col2 = max_ff(*col2, angle); + } + } + /* Remaining non manifold edges. */ + EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh); + for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + if (BLI_edgehashIterator_getValue(ehi) != nullptr) { + uint v1, v2; + const float angle = DEG2RADF(90.0f); + BLI_edgehashIterator_getKey(ehi, &v1, &v2); + float *col1 = &vert_angles[v1]; + float *col2 = &vert_angles[v2]; + *col1 = max_ff(*col1, angle); + *col2 = max_ff(*col2, angle); + } + } + BLI_edgehashIterator_free(ehi); + BLI_edgehash_free(eh, nullptr); + + const MLoop *ml = mr->mloop; + for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) { + r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange); + } + } + + MEM_freeN(vert_angles); +} + +static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + BLI_assert(mr->edit_bmesh); + + float *l_weight = (float *)GPU_vertbuf_get_data(vbo); + + switch (mr->toolsettings->statvis.type) { + case SCE_STATVIS_OVERHANG: + statvis_calc_overhang(mr, l_weight); + break; + case SCE_STATVIS_THICKNESS: + statvis_calc_thickness(mr, l_weight); + break; + case SCE_STATVIS_INTERSECT: + statvis_calc_intersect(mr, l_weight); + break; + case SCE_STATVIS_DISTORT: + statvis_calc_distort(mr, l_weight); + break; + case SCE_STATVIS_SHARP: + statvis_calc_sharp(mr, l_weight); + break; + } +} + +constexpr MeshExtract create_extractor_mesh_analysis() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_mesh_analysis_init; + extractor.finish = extract_analysis_iter_finish_mesh; + /* This is not needed for all visualization types. + * Maybe split into different extract. */ + extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_mesh_analysis = blender::draw::create_extractor_mesh_analysis(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc new file mode 100644 index 00000000000..80b73cac678 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc @@ -0,0 +1,115 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Orco + * \{ */ + +struct MeshExtract_Orco_Data { + float (*vbo_data)[4]; + float (*orco)[3]; +}; + +static void extract_orco_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex + * attributes. This is a substantial waste of video-ram and should be done another way. + * Unfortunately, at the time of writing, I did not found any other "non disruptive" + * alternative. */ + GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + CustomData *cd_vdata = &mr->me->vdata; + + MeshExtract_Orco_Data *data = static_cast<MeshExtract_Orco_Data *>(tls_data); + data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo); + data->orco = static_cast<float(*)[3]>(CustomData_get_layer(cd_vdata, CD_ORCO)); + /* Make sure `orco` layer was requested only if needed! */ + BLI_assert(data->orco); +} + +static void extract_orco_iter_poly_bm(const MeshRenderData *UNUSED(mr), + const BMFace *f, + const int UNUSED(f_index), + void *data) +{ + MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + float *loop_orco = orco_data->vbo_data[l_index]; + copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(l_iter->v)]); + loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int UNUSED(mp_index), + void *data) +{ + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; + float *loop_orco = orco_data->vbo_data[ml_index]; + copy_v3_v3(loop_orco, orco_data->orco[ml->v]); + loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + } +} + +constexpr MeshExtract create_extractor_orco() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_orco_init; + extractor.iter_poly_bm = extract_orco_iter_poly_bm; + extractor.iter_poly_mesh = extract_orco_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_Orco_Data); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_orco = blender::draw::create_extractor_orco(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc new file mode 100644 index 00000000000..2ac926dd257 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -0,0 +1,415 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Position and Vertex Normal + * \{ */ + +struct PosNorLoop { + float pos[3]; + GPUPackedNormal nor; +}; + +struct MeshExtract_PosNor_Data { + PosNorLoop *vbo_data; + GPUNormal *normals; +}; + +static void extract_pos_nor_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* WARNING Adjust #PosNorLoop struct accordingly. */ + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_alias_add(&format, "vnor"); + } + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); + + /* Pack normals per vert, reduce amount of computation. */ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(tls_data); + data->vbo_data = static_cast<PosNorLoop *>(GPU_vertbuf_get_data(vbo)); + data->normals = (GPUNormal *)MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__); + + /* Quicker than doing it for each loop. */ + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMIter iter; + BMVert *eve; + int v; + BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) { + data->normals[v].low = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve)); + } + } + else { + const MVert *mv = mr->mvert; + for (int v = 0; v < mr->vert_len; v++, mv++) { + data->normals[v].low = GPU_normal_convert_i10_s3(mv->no); + } + } +} + +static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + PosNorLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v)); + vert->nor = data->normals[BM_elem_index_get(l_iter->v)].low; + vert->nor.w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int UNUSED(mp_index), + void *_data) +{ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + + PosNorLoop *vert = &data->vbo_data[ml_index]; + const MVert *mv = &mr->mvert[ml->v]; + copy_v3_v3(vert->pos, mv->co); + vert->nor = data->normals[ml->v].low; + /* Flag for paint mode overlay. */ + if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && + (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { + vert->nor.w = -1; + } + else if (mv->flag & SELECT) { + vert->nor.w = 1; + } + else { + vert->nor.w = 0; + } + } +} + +static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr, + const BMEdge *eed, + const int ledge_index, + void *_data) +{ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + + int l_index = mr->loop_len + ledge_index * 2; + PosNorLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); + copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); + vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low; + vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low; +} + +static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr, + const MEdge *med, + const int ledge_index, + void *_data) +{ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + const int ml_index = mr->loop_len + ledge_index * 2; + PosNorLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); + copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); + vert[0].nor = data->normals[med->v1].low; + vert[1].nor = data->normals[med->v2].low; +} + +static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr, + const BMVert *eve, + const int lvert_index, + void *_data) +{ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + + const int l_index = offset + lvert_index; + PosNorLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); + vert->nor = data->normals[BM_elem_index_get(eve)].low; +} + +static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, + const MVert *mv, + const int lvert_index, + void *_data) +{ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + + const int ml_index = offset + lvert_index; + const int v_index = mr->lverts[lvert_index]; + PosNorLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert->pos, mv->co); + vert->nor = data->normals[v_index].low; +} + +static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(buf), + void *_data) +{ + MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + MEM_freeN(data->normals); +} + +constexpr MeshExtract create_extractor_pos_nor() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_pos_nor_init; + extractor.iter_poly_bm = extract_pos_nor_iter_poly_bm; + extractor.iter_poly_mesh = extract_pos_nor_iter_poly_mesh; + extractor.iter_ledge_bm = extract_pos_nor_iter_ledge_bm; + extractor.iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh; + extractor.iter_lvert_bm = extract_pos_nor_iter_lvert_bm; + extractor.iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh; + extractor.finish = extract_pos_nor_finish; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_PosNor_Data); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor); + return extractor; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Extract Position and High Quality Vertex Normal + * \{ */ + +struct PosNorHQLoop { + float pos[3]; + short nor[4]; +}; + +struct MeshExtract_PosNorHQ_Data { + PosNorHQLoop *vbo_data; + GPUNormal *normals; +}; + +static void extract_pos_nor_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* WARNING Adjust #PosNorHQLoop struct accordingly. */ + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_alias_add(&format, "vnor"); + } + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); + + /* Pack normals per vert, reduce amount of computation. */ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(tls_data); + data->vbo_data = static_cast<PosNorHQLoop *>(GPU_vertbuf_get_data(vbo)); + data->normals = (GPUNormal *)MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__); + + /* Quicker than doing it for each loop. */ + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMIter iter; + BMVert *eve; + int v; + BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) { + normal_float_to_short_v3(data->normals[v].high, bm_vert_no_get(mr, eve)); + } + } + else { + const MVert *mv = mr->mvert; + for (int v = 0; v < mr->vert_len; v++, mv++) { + copy_v3_v3_short(data->normals[v].high, mv->no); + } + } +} + +static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + PosNorHQLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v)); + copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l_iter->v)].high); + + vert->nor[3] = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int UNUSED(mp_index), + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + + PosNorHQLoop *vert = &data->vbo_data[ml_index]; + const MVert *mv = &mr->mvert[ml->v]; + copy_v3_v3(vert->pos, mv->co); + copy_v3_v3_short(vert->nor, data->normals[ml->v].high); + + /* Flag for paint mode overlay. */ + if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && + (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { + vert->nor[3] = -1; + } + else if (mv->flag & SELECT) { + vert->nor[3] = 1; + } + else { + vert->nor[3] = 0; + } + } +} + +static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr, + const BMEdge *eed, + const int ledge_index, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + int l_index = mr->loop_len + ledge_index * 2; + PosNorHQLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); + copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); + copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high); + vert[0].nor[3] = 0; + copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high); + vert[1].nor[3] = 0; +} + +static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr, + const MEdge *med, + const int ledge_index, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + const int ml_index = mr->loop_len + ledge_index * 2; + PosNorHQLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); + copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); + copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high); + vert[0].nor[3] = 0; + copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high); + vert[1].nor[3] = 0; +} + +static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr, + const BMVert *eve, + const int lvert_index, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + + const int l_index = offset + lvert_index; + PosNorHQLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); + copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high); + vert->nor[3] = 0; +} + +static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr, + const MVert *mv, + const int lvert_index, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + + const int ml_index = offset + lvert_index; + const int v_index = mr->lverts[lvert_index]; + PosNorHQLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert->pos, mv->co); + copy_v3_v3_short(vert->nor, data->normals[v_index].high); + vert->nor[3] = 0; +} + +static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr), + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(buf), + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + MEM_freeN(data->normals); +} + +constexpr MeshExtract create_extractor_pos_nor_hq() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_pos_nor_hq_init; + extractor.iter_poly_bm = extract_pos_nor_hq_iter_poly_bm; + extractor.iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh; + extractor.iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm; + extractor.iter_ledge_mesh = extract_pos_nor_hq_iter_ledge_mesh; + extractor.iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm; + extractor.iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh; + extractor.finish = extract_pos_nor_hq_finish; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_PosNorHQ_Data); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_pos_nor = blender::draw::create_extractor_pos_nor(); +const MeshExtract extract_pos_nor_hq = blender::draw::create_extractor_pos_nor_hq(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc new file mode 100644 index 00000000000..7b36a009419 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc @@ -0,0 +1,141 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" + +#include "BKE_paint.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Sculpt Data + * \{ */ + +static void extract_sculpt_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + GPUVertFormat format = {0}; + + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; + CustomData *cd_pdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata; + + float *cd_mask = (float *)CustomData_get_layer(cd_vdata, CD_PAINT_MASK); + int *cd_face_set = (int *)CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS); + + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + struct gpuSculptData { + uint8_t face_set_color[4]; + float mask; + }; + + gpuSculptData *vbo_data = (gpuSculptData *)GPU_vertbuf_get_data(vbo); + MLoop *loops = (MLoop *)CustomData_get_layer(cd_ldata, CD_MLOOP); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_mask_ofs = CustomData_get_offset(cd_vdata, CD_PAINT_MASK); + int cd_face_set_ofs = CustomData_get_offset(cd_pdata, CD_SCULPT_FACE_SETS); + BMIter f_iter; + BMFace *efa; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + float v_mask = 0.0f; + if (cd_mask) { + v_mask = BM_ELEM_CD_GET_FLOAT(l_iter->v, cd_mask_ofs); + } + vbo_data->mask = v_mask; + uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; + if (cd_face_set) { + const int face_set_id = BM_ELEM_CD_GET_INT(l_iter->f, cd_face_set_ofs); + if (face_set_id != mr->me->face_sets_color_default) { + BKE_paint_face_set_overlay_color_get( + face_set_id, mr->me->face_sets_color_seed, face_set_color); + } + } + copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color); + vbo_data++; + } while ((l_iter = l_iter->next) != l_first); + } + } + else { + int mp_loop = 0; + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { + const MPoly *p = &mr->mpoly[mp_index]; + for (int l = 0; l < p->totloop; l++) { + float v_mask = 0.0f; + if (cd_mask) { + v_mask = cd_mask[loops[mp_loop].v]; + } + vbo_data->mask = v_mask; + + uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; + if (cd_face_set) { + const int face_set_id = cd_face_set[mp_index]; + /* Skip for the default color Face Set to render it white. */ + if (face_set_id != mr->me->face_sets_color_default) { + BKE_paint_face_set_overlay_color_get( + face_set_id, mr->me->face_sets_color_seed, face_set_color); + } + } + copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color); + mp_loop++; + vbo_data++; + } + } + } +} + +constexpr MeshExtract create_extractor_sculpt_data() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_sculpt_data_init; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_sculpt_data = blender::draw::create_extractor_sculpt_data(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc new file mode 100644 index 00000000000..ac44e97f229 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc @@ -0,0 +1,295 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Selection Index + * \{ */ + +static void extract_select_idx_init_impl(const MeshRenderData *UNUSED(mr), + const int len, + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* TODO: rename "color" to something more descriptive. */ + GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT); + } + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, len); + *(uint32_t **)tls_data = (uint32_t *)GPU_vertbuf_get_data(vbo); +} + +static void extract_select_idx_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + extract_select_idx_init_impl(mr, mr->loop_len + mr->loop_loose_len, buf, tls_data); +} + +/* TODO: Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the + * select element associated with this loop ID. This would remove the need for this separate + * index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the + * shader to output original index. */ + +static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), + const BMFace *f, + const int f_index, + void *data) +{ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + (*(uint32_t **)data)[l_index] = f_index; + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), + const BMFace *f, + const int UNUSED(f_index), + void *data) +{ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->e); + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), + const BMFace *f, + const int UNUSED(f_index), + void *data) +{ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->v); + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr, + const BMEdge *eed, + const int ledge_index, + void *data) +{ + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed); + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed); +} + +static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr, + const BMEdge *eed, + const int ledge_index, + void *data) +{ + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1); + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2); +} + +static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr, + const BMVert *eve, + const int lvert_index, + void *data) +{ + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + + (*(uint32_t **)data)[offset + lvert_index] = BM_elem_index_get(eve); +} + +static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *data) +{ + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + (*(uint32_t **)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index; + } +} + +static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int UNUSED(mp_index), + void *data) +{ + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + (*(uint32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e; + } +} + +static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int UNUSED(mp_index), + void *data) +{ + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + (*(uint32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v; + } +} + +static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr, + const MEdge *UNUSED(med), + const int ledge_index, + void *data) +{ + const int e_index = mr->ledges[ledge_index]; + const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig; +} + +static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr, + const MEdge *med, + const int ledge_index, + void *data) +{ + int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1; + int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig; +} + +static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr, + const MVert *UNUSED(mv), + const int lvert_index, + void *data) +{ + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + + const int v_index = mr->lverts[lvert_index]; + const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index; + (*(uint32_t **)data)[offset + lvert_index] = v_orig; +} + +constexpr MeshExtract create_extractor_poly_idx() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_select_idx_init; + extractor.iter_poly_bm = extract_poly_idx_iter_poly_bm; + extractor.iter_poly_mesh = extract_poly_idx_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(uint32_t *); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx); + return extractor; +} + +constexpr MeshExtract create_extractor_edge_idx() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_select_idx_init; + extractor.iter_poly_bm = extract_edge_idx_iter_poly_bm; + extractor.iter_poly_mesh = extract_edge_idx_iter_poly_mesh; + extractor.iter_ledge_bm = extract_edge_idx_iter_ledge_bm; + extractor.iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(uint32_t *); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx); + return extractor; +} + +constexpr MeshExtract create_extractor_vert_idx() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_select_idx_init; + extractor.iter_poly_bm = extract_vert_idx_iter_poly_bm; + extractor.iter_poly_mesh = extract_vert_idx_iter_poly_mesh; + extractor.iter_ledge_bm = extract_vert_idx_iter_ledge_bm; + extractor.iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh; + extractor.iter_lvert_bm = extract_vert_idx_iter_lvert_bm; + extractor.iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(uint32_t *); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx); + return extractor; +} + +static void extract_fdot_idx_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) +{ + extract_select_idx_init_impl(mr, mr->poly_len, buf, tls_data); +} + +static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), + const BMFace *UNUSED(f), + const int f_index, + void *data) +{ + (*(uint32_t **)data)[f_index] = f_index; +} + +static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *UNUSED(mp), + const int mp_index, + void *data) +{ + if (mr->p_origindex != nullptr) { + (*(uint32_t **)data)[mp_index] = mr->p_origindex[mp_index]; + } + else { + (*(uint32_t **)data)[mp_index] = mp_index; + } +} + +constexpr MeshExtract create_extractor_fdot_idx() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_fdot_idx_init; + extractor.iter_poly_bm = extract_fdot_idx_iter_poly_bm; + extractor.iter_poly_mesh = extract_fdot_idx_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(uint32_t *); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_poly_idx = blender::draw::create_extractor_poly_idx(); +const MeshExtract extract_edge_idx = blender::draw::create_extractor_edge_idx(); +const MeshExtract extract_vert_idx = blender::draw::create_extractor_vert_idx(); +const MeshExtract extract_fdot_idx = blender::draw::create_extractor_fdot_idx(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc new file mode 100644 index 00000000000..d7a01ee607f --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc @@ -0,0 +1,93 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Skin Modifier Roots + * \{ */ + +struct SkinRootData { + float size; + float local_pos[3]; +}; + +static void extract_skin_roots_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + /* Exclusively for edit mode. */ + BLI_assert(mr->bm); + + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "local_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->bm->totvert); + + SkinRootData *vbo_data = (SkinRootData *)GPU_vertbuf_get_data(vbo); + + int root_len = 0; + int cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MVERT_SKIN); + + BMIter iter; + BMVert *eve; + BM_ITER_MESH (eve, &iter, mr->bm, BM_VERTS_OF_MESH) { + const MVertSkin *vs = (const MVertSkin *)BM_ELEM_CD_GET_VOID_P(eve, cd_ofs); + if (vs->flag & MVERT_SKIN_ROOT) { + vbo_data->size = (vs->radius[0] + vs->radius[1]) * 0.5f; + copy_v3_v3(vbo_data->local_pos, bm_vert_co_get(mr, eve)); + vbo_data++; + root_len++; + } + } + + /* It's really unlikely that all verts will be roots. Resize to avoid losing VRAM. */ + GPU_vertbuf_data_len_set(vbo, root_len); +} + +constexpr MeshExtract create_extractor_skin_roots() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_skin_roots_init; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_skin_roots = blender::draw::create_extractor_skin_roots(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc new file mode 100644 index 00000000000..f251141c442 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc @@ -0,0 +1,266 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" + +#include "BKE_editmesh.h" +#include "BKE_editmesh_tangent.h" +#include "BKE_mesh.h" +#include "BKE_mesh_tangent.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Tangent layers + * \{ */ + +static void extract_tan_ex_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + GPUVertBuf *vbo, + const bool do_hq) +{ + GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10; + GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT; + + GPUVertFormat format = {0}; + GPU_vertformat_deinterleave(&format); + + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; + uint32_t tan_layers = cache->cd_used.tan; + float(*orco)[3] = (float(*)[3])CustomData_get_layer(cd_vdata, CD_ORCO); + bool orco_allocated = false; + const bool use_orco_tan = cache->cd_used.tan_orco != 0; + + int tan_len = 0; + char tangent_names[MAX_MTFACE][MAX_CUSTOMDATA_LAYER_NAME]; + + for (int i = 0; i < MAX_MTFACE; i++) { + if (tan_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + /* Tangent layer name. */ + BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode); + /* Active render layer name. */ + if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) { + GPU_vertformat_alias_add(&format, "t"); + } + /* Active display layer name. */ + if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) { + GPU_vertformat_alias_add(&format, "at"); + } + + BLI_strncpy(tangent_names[tan_len++], layer_name, MAX_CUSTOMDATA_LAYER_NAME); + } + } + if (use_orco_tan && orco == nullptr) { + /* If `orco` is not available compute it ourselves */ + orco_allocated = true; + orco = (float(*)[3])MEM_mallocN(sizeof(*orco) * mr->vert_len, __func__); + + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMesh *bm = mr->bm; + for (int v = 0; v < mr->vert_len; v++) { + const BMVert *eve = BM_vert_at_index(bm, v); + /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords. + * not the distorted ones. */ + copy_v3_v3(orco[v], eve->co); + } + } + else { + const MVert *mv = mr->mvert; + for (int v = 0; v < mr->vert_len; v++, mv++) { + copy_v3_v3(orco[v], mv->co); + } + } + BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0); + } + + /* Start Fresh */ + CustomData loop_data; + CustomData_reset(&loop_data); + if (tan_len != 0 || use_orco_tan) { + short tangent_mask = 0; + bool calc_active_tangent = false; + if (mr->extract_type == MR_EXTRACT_BMESH) { + BKE_editmesh_loop_tangent_calc(mr->edit_bmesh, + calc_active_tangent, + tangent_names, + tan_len, + mr->poly_normals, + mr->loop_normals, + orco, + &loop_data, + mr->loop_len, + &tangent_mask); + } + else { + BKE_mesh_calc_loop_tangent_ex(mr->mvert, + mr->mpoly, + mr->poly_len, + mr->mloop, + mr->mlooptri, + mr->tri_len, + cd_ldata, + calc_active_tangent, + tangent_names, + tan_len, + mr->poly_normals, + mr->loop_normals, + orco, + &loop_data, + mr->loop_len, + &tangent_mask); + } + } + + if (use_orco_tan) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(&loop_data, CD_TANGENT, 0); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode); + GPU_vertformat_alias_add(&format, "t"); + GPU_vertformat_alias_add(&format, "at"); + } + + if (orco_allocated) { + MEM_SAFE_FREE(orco); + } + + int v_len = mr->loop_len; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + /* VBO will not be used, only allocate minimum of memory. */ + v_len = 1; + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, v_len); + + if (do_hq) { + short(*tan_data)[4] = (short(*)[4])GPU_vertbuf_get_data(vbo); + for (int i = 0; i < tan_len; i++) { + const char *name = tangent_names[i]; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named( + &loop_data, CD_TANGENT, name); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + normal_float_to_short_v3(*tan_data, layer_data[ml_index]); + (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; + tan_data++; + } + } + if (use_orco_tan) { + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + normal_float_to_short_v3(*tan_data, layer_data[ml_index]); + (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; + tan_data++; + } + } + } + else { + GPUPackedNormal *tan_data = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo); + for (int i = 0; i < tan_len; i++) { + const char *name = tangent_names[i]; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named( + &loop_data, CD_TANGENT, name); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]); + tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2; + tan_data++; + } + } + if (use_orco_tan) { + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]); + tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2; + tan_data++; + } + } + } + + CustomData_free(&loop_data, mr->loop_len); +} + +static void extract_tan_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + extract_tan_ex_init(mr, cache, vbo, false); +} + +constexpr MeshExtract create_extractor_tan() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_tan_init; + extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan); + return extractor; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Extract HQ Tangent layers + * \{ */ + +static void extract_tan_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + extract_tan_ex_init(mr, cache, vbo, true); +} + +constexpr MeshExtract create_extractor_tan_hq() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_tan_hq_init; + extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_tan = blender::draw::create_extractor_tan(); +const MeshExtract extract_tan_hq = blender::draw::create_extractor_tan_hq(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc new file mode 100644 index 00000000000..0f3c2483296 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc @@ -0,0 +1,136 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "BLI_string.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract UV layers + * \{ */ + +static void extract_uv_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + GPUVertFormat format = {0}; + GPU_vertformat_deinterleave(&format); + + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + uint32_t uv_layers = cache->cd_used.uv; + /* HACK to fix T68857 */ + if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { + int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); + if (layer != -1) { + uv_layers |= (1 << layer); + } + } + + for (int i = 0; i < MAX_MTFACE; i++) { + if (uv_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); + + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + /* UV layer name. */ + BLI_snprintf(attr_name, sizeof(attr_name), "u%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + /* Auto layer name. */ + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); + GPU_vertformat_alias_add(&format, attr_name); + /* Active render layer name. */ + if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) { + GPU_vertformat_alias_add(&format, "u"); + } + /* Active display layer name. */ + if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) { + GPU_vertformat_alias_add(&format, "au"); + /* Alias to `pos` for edit uvs. */ + GPU_vertformat_alias_add(&format, "pos"); + } + /* Stencil mask uv layer name. */ + if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) { + GPU_vertformat_alias_add(&format, "mu"); + } + } + } + + int v_len = mr->loop_len; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + /* VBO will not be used, only allocate minimum of memory. */ + v_len = 1; + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, v_len); + + float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo); + for (int i = 0; i < MAX_MTFACE; i++) { + if (uv_layers & (1 << i)) { + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i); + BMIter f_iter; + BMFace *efa; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs); + memcpy(uv_data, luv->uv, sizeof(*uv_data)); + uv_data++; + } while ((l_iter = l_iter->next) != l_first); + } + } + else { + MLoopUV *layer_data = (MLoopUV *)CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) { + memcpy(uv_data, layer_data->uv, sizeof(*uv_data)); + } + } + } + } +} + +constexpr MeshExtract create_extractor_uv() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_uv_init; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_uv = blender::draw::create_extractor_uv(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc new file mode 100644 index 00000000000..2f1cff08796 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc @@ -0,0 +1,191 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract VCol + * \{ */ + +static void extract_vcol_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + GPUVertFormat format = {0}; + GPU_vertformat_deinterleave(&format); + + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; + uint32_t vcol_layers = cache->cd_used.vcol; + uint32_t svcol_layers = cache->cd_used.sculpt_vcol; + + for (int i = 0; i < MAX_MCOL; i++) { + if (vcol_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + + BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) { + GPU_vertformat_alias_add(&format, "c"); + } + if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) { + GPU_vertformat_alias_add(&format, "ac"); + } + + /* Gather number of auto layers. */ + /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 && + CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) { + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); + GPU_vertformat_alias_add(&format, attr_name); + } + } + } + + /* Sculpt Vertex Colors */ + if (U.experimental.use_sculpt_vertex_colors) { + for (int i = 0; i < 8; i++) { + if (svcol_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + + BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "c"); + } + if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "ac"); + } + /* Gather number of auto layers. */ + /* We only do `vcols` that are not overridden by `uvs`. */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); + GPU_vertformat_alias_add(&format, attr_name); + } + } + } + } + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + using gpuMeshVcol = struct gpuMeshVcol { + ushort r, g, b, a; + }; + + gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo); + MLoop *loops = (MLoop *)CustomData_get_layer(cd_ldata, CD_MLOOP); + + for (int i = 0; i < MAX_MCOL; i++) { + if (vcol_layers & (1 << i)) { + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i); + BMIter f_iter; + BMFace *efa; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const MLoopCol *mloopcol = (const MLoopCol *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs); + vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); + vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); + vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); + vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); + vcol_data++; + } while ((l_iter = l_iter->next) != l_first); + } + } + else { + const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) { + vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); + vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); + vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); + vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); + } + } + } + + if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) { + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i); + BMIter f_iter; + BMFace *efa; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const MPropCol *prop_col = (const MPropCol *)BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs); + vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]); + vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]); + vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]); + vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]); + vcol_data++; + } while ((l_iter = l_iter->next) != l_first); + } + } + else { + MPropCol *vcol = (MPropCol *)CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) { + vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]); + vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]); + vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]); + vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]); + } + } + } + } +} + +constexpr MeshExtract create_extractor_vcol() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_vcol_init; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = 0; + extractor.use_threading = false; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_vcol = blender::draw::create_extractor_vcol(); +} diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc new file mode 100644 index 00000000000..aae266eadce --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc @@ -0,0 +1,189 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BKE_deform.h" + +#include "draw_cache_extract_mesh_private.h" + +namespace blender::draw { + +/* ---------------------------------------------------------------------- */ +/** \name Extract Vertex Weight + * \{ */ + +struct MeshExtract_Weight_Data { + float *vbo_data; + const DRW_MeshWeightState *wstate; + const MDeformVert *dvert; /* For #Mesh. */ + int cd_ofs; /* For #BMesh. */ +}; + +static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate) +{ + /* Error state. */ + if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) { + return -2.0f; + } + if (dvert == nullptr) { + return (wstate->alert_mode != OB_DRAW_GROUPUSER_NONE) ? -1.0f : 0.0f; + } + + float input = 0.0f; + if (wstate->flags & DRW_MESH_WEIGHT_STATE_MULTIPAINT) { + /* Multi-Paint feature */ + bool is_normalized = (wstate->flags & (DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE | + DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE)); + input = BKE_defvert_multipaint_collective_weight(dvert, + wstate->defgroup_len, + wstate->defgroup_sel, + wstate->defgroup_sel_count, + is_normalized); + /* make it black if the selected groups have no weight on a vertex */ + if (input == 0.0f) { + return -1.0f; + } + } + else { + /* default, non tricky behavior */ + input = BKE_defvert_find_weight(dvert, wstate->defgroup_active); + + if (input == 0.0f) { + switch (wstate->alert_mode) { + case OB_DRAW_GROUPUSER_ACTIVE: + return -1.0f; + break; + case OB_DRAW_GROUPUSER_ALL: + if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) { + return -1.0f; + } + break; + } + } + } + + /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */ + if (wstate->flags & DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE) { + input = BKE_defvert_lock_relative_weight( + input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked); + } + + CLAMP(input, 0.0f, 1.0f); + return input; +} + +static void extract_weights_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *tls_data) +{ + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); + + MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(tls_data); + data->vbo_data = (float *)GPU_vertbuf_get_data(vbo); + data->wstate = &cache->weight_state; + + if (data->wstate->defgroup_active == -1) { + /* Nothing to show. */ + data->dvert = nullptr; + data->cd_ofs = -1; + } + else if (mr->extract_type == MR_EXTRACT_BMESH) { + data->dvert = nullptr; + data->cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MDEFORMVERT); + } + else { + data->dvert = (const MDeformVert *)CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT); + data->cd_ofs = -1; + } +} + +static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr), + const BMFace *f, + const int UNUSED(f_index), + void *_data) +{ + MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(_data); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + if (data->cd_ofs != -1) { + const MDeformVert *dvert = (const MDeformVert *)BM_ELEM_CD_GET_VOID_P(l_iter->v, + data->cd_ofs); + data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate); + } + else { + data->vbo_data[l_index] = evaluate_vertex_weight(nullptr, data->wstate); + } + } while ((l_iter = l_iter->next) != l_first); +} + +static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int UNUSED(mp_index), + void *_data) +{ + MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(_data); + const MLoop *mloop = mr->mloop; + const int ml_index_end = mp->loopstart + mp->totloop; + for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { + const MLoop *ml = &mloop[ml_index]; + if (data->dvert != nullptr) { + const MDeformVert *dvert = &data->dvert[ml->v]; + data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); + } + else { + const MDeformVert *dvert = nullptr; + data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); + } + } +} + +constexpr MeshExtract create_extractor_weights() +{ + MeshExtract extractor = {nullptr}; + extractor.init = extract_weights_init; + extractor.iter_poly_bm = extract_weights_iter_poly_bm; + extractor.iter_poly_mesh = extract_weights_iter_poly_mesh; + extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_Weight_Data); + extractor.use_threading = true; + extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights); + return extractor; +} + +/** \} */ + +} // namespace blender::draw + +extern "C" { +const MeshExtract extract_weights = blender::draw::create_extractor_weights(); +} diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index 4012de4f95b..a980b87821a 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -18,7 +18,7 @@ layout(std140) uniform viewBlock * Fourth components are near and far values. */ vec4 ViewVecs[2]; - /* TODO move it elsewhere. */ + /* TODO: move it elsewhere. */ vec4 CameraTexCoFactors; }; @@ -45,7 +45,7 @@ float mul_project_m4_v3_zfac(in vec3 co) #endif /* Not the right place but need to be common to all overlay's. - * TODO Split to an overlay lib. */ + * TODO: Split to an overlay lib. */ mat4 extract_matrix_packed_data(mat4 mat, out vec4 dataA, out vec4 dataB) { const float div = 1.0 / 255.0; @@ -61,7 +61,7 @@ mat4 extract_matrix_packed_data(mat4 mat, out vec4 dataA, out vec4 dataB) } /* Same here, Not the right place but need to be common to all overlay's. - * TODO Split to an overlay lib. */ + * TODO: Split to an overlay lib. */ /* edge_start and edge_pos needs to be in the range [0..sizeViewport]. */ vec4 pack_line_data(vec2 frag_co, vec2 edge_start, vec2 edge_pos) { diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index f69830fc015..87688ee343c 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -4025,7 +4025,7 @@ static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac), /* conditionally supported */ case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { - /* this should only appear in tweakmode */ + /* This should only appear in tweak-mode. */ return true; } else { @@ -5176,7 +5176,7 @@ void ANIM_channel_draw_widgets(const bContext *C, } /* step 3) draw special toggles ................................. - * - in Graph Editor, checkboxes for visibility in curves area + * - in Graph Editor, check-boxes for visibility in curves area * - in NLA Editor, glowing dots for solo/not solo... * - in Grease Pencil mode, color swatches for layer color */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 136cdefd2ec..8f8c1c067d4 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -747,7 +747,7 @@ static bool animedit_poll_channels_active(bContext *C) return 1; } -/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */ +/* Poll callback for Animation Editor channels list region + not in NLA-tweak-mode for NLA. */ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) { ScrArea *area = CTX_wm_area(C); @@ -763,7 +763,7 @@ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) return 0; } - /* NLA TweakMode test */ + /* NLA tweak-mode test. */ if (area->spacetype == SPACE_NLA) { if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) { return 0; @@ -1283,6 +1283,9 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp) else { group_fcurves_last->next->prev = group_fcurves_first->prev; } + + /* Clear links pointing outside the per-group list. */ + group_fcurves_first->prev = group_fcurves_last->next = NULL; } /* Initialize memory for temp-group */ @@ -1337,24 +1340,12 @@ static void join_groups_action_temp(bAction *act) if (agrp->flag & AGRP_TEMP) { LISTBASE_FOREACH (FCurve *, fcu, &agrp->channels) { fcu->grp = NULL; - if (fcu == agrp->channels.last) { - break; - } } BLI_remlink(&act->groups, agrp); break; } } - - /* BLI_movelisttolist() doesn't touch first->prev and last->next pointers in its "dst" list. - * Ensure that after the reshuffling the list is properly terminated. */ - if (!BLI_listbase_is_empty(&act->curves)) { - FCurve *act_fcurves_first = act->curves.first; - act_fcurves_first->prev = NULL; - FCurve *act_fcurves_last = act->curves.last; - act_fcurves_last->next = NULL; - } } /* Change the order of anim-channels within action diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 745b869228a..2fcd59a1bbe 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -89,7 +89,7 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag) /* *************************************************** */ /* PREVIEW RANGE 'CURTAINS' */ -/* Note: 'Preview Range' tools are defined in anim_ops.c */ +/* NOTE: 'Preview Range' tools are defined in `anim_ops.c`. */ /* Draw preview range 'curtains' for highlighting where the animation data is */ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f04fa556dad..b2d387ea898 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -32,7 +32,7 @@ * are being edited. Likewise, the NLA Editor also uses this for its channel list and in * its operators. * - * Note: much of the original system this was based on was built before the creation of the RNA + * NOTE: much of the original system this was based on was built before the creation of the RNA * system. In future, it would be interesting to replace some parts of this code with RNA queries, * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this * system, so if any such work does occur, it should only be used for the internals used here... @@ -131,7 +131,7 @@ static void animedit_get_yscale_factor(bAnimContext *ac) /* ----------- Private Stuff - Action Editor ------------- */ /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */ -/* Note: there's a similar function in key.c (BKE_key_from_object) */ +/* NOTE: there's a similar function in key.c #BKE_key_from_object. */ static Key *actedit_get_shapekeys(bAnimContext *ac) { ViewLayer *view_layer = ac->view_layer; @@ -222,9 +222,9 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return true; - case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */ + case SACTCONT_MASK: /* Mask */ /* XXX: review how this mode is handled. */ { - /* TODO, other methods to get the mask */ + /* TODO: other methods to get the mask. */ #if 0 Sequence *seq = SEQ_select_active_get(ac->scene); MovieClip *clip = ac->scene->clip; @@ -454,7 +454,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) * keep expander channels with no sub-data out, as those cases should get * dealt with by the recursive detection idiom in place. * - * Implementation Note: + * Implementation NOTE: * YES the _doSubChannels variable is NOT read anywhere. BUT, this is NOT an excuse * to go steamrolling the logic into a single-line expression as from experience, * those are notoriously difficult to read + debug when extending later on. The code diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 7adddf8f4ae..9d998326b4d 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -687,7 +687,7 @@ static int ed_marker_add_exec(bContext *C, wmOperator *UNUSED(op)) marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); marker->flag = SELECT; marker->frame = frame; - BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); /* XXX - temp code only */ + BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); /* XXX: temp code only. */ BLI_addtail(markers, marker); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); @@ -897,7 +897,7 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve return OPERATOR_CANCELLED; } -/* note, init has to be called successfully */ +/* NOTE: init has to be called successfully. */ static void ed_marker_move_apply(bContext *C, wmOperator *op) { #ifdef DURIAN_CAMERA_SWITCH diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index aac2465d43a..51a897600e1 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -355,7 +355,7 @@ static void motionpath_free_free_tree_data(ListBase *targets) /* Perform baking of the given object's and/or its bones' transforms to motion paths * - scene: current scene - * - ob: object whose flagged motionpaths should get calculated + * - ob: object whose flagged motion-paths should get calculated * - recalc: whether we need to */ /* TODO: include reports pointer? */ diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 72d9bff545a..6f3277397c5 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -51,8 +51,10 @@ #include "DEG_depsgraph.h" +#include "SEQ_iterator.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" +#include "SEQ_transform.h" #include "anim_intern.h" @@ -81,6 +83,49 @@ static bool change_frame_poll(bContext *C) return false; } +static int seq_snap_threshold_get_frame_distance(bContext *C) +{ + const int snap_distance = SEQ_tool_settings_snap_distance_get(CTX_data_scene(C)); + const ARegion *region = CTX_wm_region(C); + return round_fl_to_int(UI_view2d_region_to_view_x(®ion->v2d, snap_distance) - + UI_view2d_region_to_view_x(®ion->v2d, 0)); +} + +static void seq_frame_snap_update_best(const int position, + const int timeline_frame, + int *r_best_frame, + int *r_best_distance) +{ + if (abs(position - timeline_frame) < *r_best_distance) { + *r_best_distance = abs(position - timeline_frame); + *r_best_frame = position; + } +} + +static int seq_frame_apply_snap(bContext *C, Scene *scene, const int timeline_frame) +{ + + ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene, false)); + SeqCollection *strips = SEQ_query_all_strips(seqbase); + + int best_frame = 0; + int best_distance = MAXFRAME; + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, strips) { + seq_frame_snap_update_best( + SEQ_transform_get_left_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + seq_frame_snap_update_best( + SEQ_transform_get_right_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + } + SEQ_collection_free(strips); + + if (best_distance < seq_snap_threshold_get_frame_distance(C)) { + return best_frame; + } + + return timeline_frame; +} + /* Set the new frame number */ static void change_frame_apply(bContext *C, wmOperator *op) { @@ -90,7 +135,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) if (do_snap) { if (CTX_wm_space_seq(C)) { - frame = SEQ_time_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false); + frame = seq_frame_apply_snap(C, scene, frame); } else { frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame); @@ -181,6 +226,18 @@ static void change_frame_seq_preview_end(bContext *C) } } +static bool use_sequencer_snapping(bContext *C) +{ + if (!CTX_wm_space_seq(C)) { + return false; + } + + Scene *scene = CTX_data_scene(C); + short snap_flag = SEQ_tool_settings_snap_flag_get(scene); + return (scene->toolsettings->snap_flag & SCE_SNAP_SEQ) && + (snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS); +} + /* Modal Operator init */ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -190,6 +247,10 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event */ RNA_float_set(op->ptr, "frame", frame_from_event(C, event)); + if (use_sequencer_snapping(C)) { + RNA_boolean_set(op->ptr, "snap", true); + } + change_frame_seq_preview_begin(C, event); change_frame_apply(C, op); @@ -231,11 +292,22 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) case EVT_LEFTCTRLKEY: case EVT_RIGHTCTRLKEY: - if (event->val == KM_RELEASE) { - RNA_boolean_set(op->ptr, "snap", false); + /* Use Ctrl key to invert snapping in sequencer. */ + if (use_sequencer_snapping(C)) { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", true); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", false); + } } - else if (event->val == KM_PRESS) { - RNA_boolean_set(op->ptr, "snap", true); + else { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", false); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", true); + } } break; } @@ -465,7 +537,7 @@ static void ANIM_OT_previewrange_set(wmOperatorType *ot) /* rna */ /* used to define frame range. * - * note: border Y values are not used, + * NOTE: border Y values are not used, * but are needed by box_select gesture operator stuff */ WM_operator_properties_border(ot); } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index dae2138e481..bfaa76b3bf9 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -80,7 +80,7 @@ FCurve *verify_driver_fcurve(ID *id, /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if (adt == NULL && creation_mode != DRIVER_FCURVE_LOOKUP_ONLY) { - adt = BKE_animdata_add_id(id); + adt = BKE_animdata_ensure_id(id); } if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ @@ -581,7 +581,7 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports), } else { /* find the matching driver and remove it only - * Note: here is one of the places where we don't want new F-Curve + Driver added! + * NOTE: here is one of the places where we don't want new F-Curve + Driver added! * so 'add' var must be 0 */ fcu = verify_driver_fcurve(id, rna_path, array_index, DRIVER_FCURVE_LOOKUP_ONLY); diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index aeead9350e9..0923d490110 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -1024,7 +1024,7 @@ static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt) return 0; } -/* Note: for markers and 'value', the values to use must be supplied as the first float value */ +/* NOTE: for markers and 'value', the values to use must be supplied as the first float value. */ /* calchandles_fcurve */ KeyframeEditFunc ANIM_editkeyframes_mirror(short mode) { diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index aeddd03f3c1..eb91afa5c84 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -932,7 +932,7 @@ static tAnimCopybufItem *pastebuf_match_path_property(Main *bmain, int len_id = strlen(identifier); int len_path = strlen(fcu->rna_path); if (len_id <= len_path) { - /* note, paths which end with "] will fail with this test - Animated ID Props */ + /* NOTE: paths which end with "] will fail with this test - Animated ID Props. */ if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) { if ((from_single) || (aci->array_index == fcu->array_index)) { break; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 9364be41543..0a499232ba9 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -85,6 +85,8 @@ static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op, PropertyRNA *prop, Scene *scene); +static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks); + /* ************************************************** */ /* Keyframing Setting Wrangling */ @@ -140,7 +142,7 @@ bAction *ED_id_action_ensure(Main *bmain, ID *id) /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if (adt == NULL) { - adt = BKE_animdata_add_id(id); + adt = BKE_animdata_ensure_id(id); } if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ @@ -1672,7 +1674,7 @@ int delete_keyframe(Main *bmain, } /* get F-Curve - * Note: here is one of the places where we don't want new Action + F-Curve added! + * NOTE: here is one of the places where we don't want new Action + F-Curve added! * so 'add' var must be 0 */ if (act == NULL) { @@ -1779,7 +1781,7 @@ static int clear_keyframe(Main *bmain, } /* get F-Curve - * Note: here is one of the places where we don't want new Action + F-Curve added! + * NOTE: here is one of the places where we don't want new Action + F-Curve added! * so 'add' var must be 0 */ if (act == NULL) { @@ -2079,42 +2081,19 @@ void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot) static int delete_key_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */ - int num_channels; - KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene); if (ks == NULL) { return OPERATOR_CANCELLED; } - const int prop_type = RNA_property_type(op->type->prop); - if (prop_type == PROP_ENUM) { - int type = RNA_property_enum_get(op->ptr, op->type->prop); - ks = ANIM_keyingset_get_from_enum_type(scene, type); - if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); - return OPERATOR_CANCELLED; - } - } - else if (prop_type == PROP_STRING) { - char type_id[MAX_ID_NAME - 2]; - RNA_property_string_get(op->ptr, op->type->prop, type_id); - ks = ANIM_keyingset_get_from_idname(scene, type_id); - - if (ks == NULL) { - BKE_reportf(op->reports, RPT_ERROR, "Active Keying Set '%s' not found", type_id); - return OPERATOR_CANCELLED; - } - } - else { - BLI_assert(0); - } + return delete_key_using_keying_set(C, op, ks); +} - /* report failure */ - if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); - return OPERATOR_CANCELLED; - } +static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks) +{ + Scene *scene = CTX_data_scene(C); + float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */ + int num_channels; /* try to delete keyframes for the channels specified by KeyingSet */ num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); @@ -2130,7 +2109,8 @@ static int delete_key_exec(bContext *C, wmOperator *op) if (num_channels > 0) { /* if the appropriate properties have been set, make a note that we've inserted something */ - if (RNA_boolean_get(op->ptr, "confirm_success")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "confirm_success"); + if (prop != NULL && RNA_property_boolean_get(op->ptr, prop)) { BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d keyframes for keying set '%s'", @@ -2301,7 +2281,7 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int delete_key_v3d_exec(bContext *C, wmOperator *op) +static int delete_key_v3d_without_keying_set(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); float cfra = (float)CFRA; @@ -2408,6 +2388,18 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int delete_key_v3d_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + KeyingSet *ks = ANIM_scene_get_active_keyingset(scene); + + if (ks == NULL) { + return delete_key_v3d_without_keying_set(C, op); + } + + return delete_key_using_keying_set(C, op, ks); +} + void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot) { /* identifiers */ @@ -2931,7 +2923,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter) } /* 2. test for time */ - /* TODO... yet to be implemented (this feature may evolve before then anyway) */ + /* TODO: yet to be implemented (this feature may evolve before then anyway). */ } /* try materials */ @@ -3101,7 +3093,7 @@ bool ED_autokeyframe_property( ToolSettings *ts = scene->toolsettings; const eInsertKeyFlags flag = ANIM_get_keyframing_flags(scene, true); - /* Note: We use rnaindex instead of fcu->array_index, + /* NOTE: We use rnaindex instead of fcu->array_index, * because a button may control all items of an array at once. * E.g., color wheels (see T42567). */ BLI_assert((fcu->array_index == rnaindex) || (rnaindex == -1)); diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 034378399b9..6af033f3cf2 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -109,7 +109,7 @@ static void draw_current_frame(const Scene *scene, if (draw_line) { /* Draw vertical line to from the bottom of the current frame box to the bottom of the screen. */ - const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_frame_get(scene)); + const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_ctime_get(scene)); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt index 0030e78002b..e942bcf2902 100644 --- a/source/blender/editors/armature/CMakeLists.txt +++ b/source/blender/editors/armature/CMakeLists.txt @@ -20,6 +20,7 @@ set(INC ../../blenfont ../../blenkernel ../../blenlib + ../../blenloader ../../blentranslation ../../depsgraph ../../gpu @@ -43,9 +44,11 @@ set(SRC armature_utils.c editarmature_undo.c meshlaplacian.c + pose_backup.c pose_edit.c pose_group.c pose_lib.c + pose_lib_2.c pose_select.c pose_slide.c pose_transform.c diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 0ee11a6ef55..45bf18fe1bb 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -225,7 +225,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op)) static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - /* TODO most of this code is copied from set3dcursor_invoke, + /* TODO: most of this code is copied from set3dcursor_invoke, * it would be better to reuse code in set3dcursor_invoke */ /* temporarily change 3d cursor position */ @@ -438,17 +438,15 @@ static void updateDuplicateSubtarget(EditBone *dup_bone, } } -static void updateDuplicateActionConstraintSettings(EditBone *dup_bone, - EditBone *orig_bone, - Object *ob, - bConstraint *curcon) +static void updateDuplicateActionConstraintSettings( + EditBone *dup_bone, EditBone *orig_bone, Object *ob, bPoseChannel *pchan, bConstraint *curcon) { bActionConstraint *act_con = (bActionConstraint *)curcon->data; bAction *act = (bAction *)act_con->act; float mat[4][4]; - bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = NULL}; + bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan}; BKE_constraint_custom_object_space_get(cob.space_obj_world_matrix, curcon); unit_m4(mat); @@ -832,7 +830,7 @@ static void updateDuplicateConstraintSettings(EditBone *dup_bone, EditBone *orig for (curcon = conlist->first; curcon; curcon = curcon->next) { switch (curcon->type) { case CONSTRAINT_TYPE_ACTION: - updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, curcon); + updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, pchan, curcon); break; case CONSTRAINT_TYPE_KINEMATIC: updateDuplicateKinematicConstraintSettings(curcon); @@ -1603,7 +1601,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) ED_armature_edit_refresh_layer_used(obedit->data); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT); ED_outliner_select_sync_from_edit_bone_tag(C); @@ -1694,7 +1692,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT); ED_outliner_select_sync_from_edit_bone_tag(C); diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 48b487c29fd..ea6c71fd33f 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -228,7 +228,7 @@ float ED_armature_ebone_roll_to_vector(const EditBone *bone, return roll; } -/* note, ranges arithmetic is used below */ +/* NOTE: ranges arithmetic is used below. */ typedef enum eCalcRollTypes { /* pos */ CALC_ROLL_POS_X = 0, @@ -449,7 +449,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op) } if (changed) { - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); } @@ -519,7 +519,7 @@ static int armature_roll_clear_exec(bContext *C, wmOperator *op) } if (changed) { - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); } @@ -577,7 +577,7 @@ static void chains_find_tips(ListBase *edbo, ListBase *list) EditBone *curBone, *ebo; LinkData *ld; - /* note: this is potentially very slow ... there's got to be a better way */ + /* NOTE: this is potentially very slow ... there's got to be a better way. */ for (curBone = edbo->first; curBone; curBone = curBone->next) { short stop = 0; @@ -1000,7 +1000,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) armature_clear_swap_done_flags(arm); armature_tag_unselect(arm); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); } @@ -1151,7 +1151,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op) op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name); } - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index d429e51061b..f9950d27e97 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -203,6 +203,10 @@ void POSELIB_OT_pose_move(struct wmOperatorType *ot); void POSELIB_OT_browse_interactive(struct wmOperatorType *ot); void POSELIB_OT_apply_pose(struct wmOperatorType *ot); +/* pose_lib_2.c */ +void POSELIB_OT_apply_pose_asset(struct wmOperatorType *ot); +void POSELIB_OT_blend_pose_asset(struct wmOperatorType *ot); + /* ******************************************************* */ /* Pose Sliding Tools */ /* pose_slide.c */ diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 70154695dcd..35bd30377c8 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -69,7 +69,7 @@ /** \name Unique Bone Name Utility (Edit Mode) * \{ */ -/* note: there's a ed_armature_bone_unique_name() too! */ +/* NOTE: there's a ed_armature_bone_unique_name() too! */ static bool editbone_unique_check(void *arg, const char *name) { struct { @@ -589,7 +589,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op) /* Since we renamed stuff... */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); } MEM_freeN(objects); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index a0face26bae..fbd89106de5 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -131,6 +131,8 @@ void ED_operatortypes_armature(void) /* POSELIB */ WM_operatortype_append(POSELIB_OT_browse_interactive); WM_operatortype_append(POSELIB_OT_apply_pose); + WM_operatortype_append(POSELIB_OT_apply_pose_asset); + WM_operatortype_append(POSELIB_OT_blend_pose_asset); WM_operatortype_append(POSELIB_OT_pose_add); WM_operatortype_append(POSELIB_OT_pose_remove); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index c447138f00c..32fd1c9ad41 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -703,7 +703,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op) ok = true; - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob_old); } MEM_freeN(bases); @@ -893,7 +893,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op) } } - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); DEG_id_tag_update(&ob->id, ID_RECALC_SELECT); @@ -1004,7 +1004,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op) ED_armature_edit_sync_selection(arm->edbo); - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); } MEM_freeN(objects); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 65f30c3729f..bd799c00373 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -1426,7 +1426,7 @@ static void armature_select_more_less(Object *ob, bool more) bArmature *arm = (bArmature *)ob->data; EditBone *ebone; - /* XXX, eventually we shouldn't need this - campbell */ + /* XXX(campbell): eventually we shouldn't need this. */ ED_armature_edit_sync_selection(arm->edbo); /* count bones & store selection state */ diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index fc9191967f8..ec5c665402b 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -478,7 +478,7 @@ void ED_object_vgroup_calc_from_armature(ReportList *reports, bArmature *arm = par->data; if (mode == ARM_GROUPS_NAME) { - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const int defbase_tot = BKE_object_defgroup_count(ob); int defbase_add; /* Traverse the bone list, trying to create empty vertex * groups corresponding to the bone. diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index bc6d0687654..874f1b49451 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -391,7 +391,7 @@ void armature_tag_unselect(bArmature *arm) void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select) { - /* TODO When this function is called by property updates, + /* TODO: When this function is called by property updates, * canceling the value change will not restore mirrored bone correctly. */ /* Currently check_select==true when this function is called from a transform operator, diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index 725945f8edc..832e75b2a8b 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -206,7 +206,7 @@ static void armature_undosys_step_decode(struct bContext *C, } undoarm_to_editarm(&elem->data, arm); arm->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&arm->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/armature/pose_backup.c b/source/blender/editors/armature/pose_backup.c new file mode 100644 index 00000000000..dffcd9bdc5a --- /dev/null +++ b/source/blender/editors/armature/pose_backup.c @@ -0,0 +1,139 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edarmature + */ + +#include "ED_armature.h" + +#include <string.h> + +#include "BLI_listbase.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_object_types.h" + +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_idprop.h" + +/* simple struct for storing backup info for one pose channel */ +typedef struct PoseChannelBackup { + struct PoseChannelBackup *next, *prev; + + struct bPoseChannel *pchan; /* Pose channel this backup is for. */ + + struct bPoseChannel olddata; /* Backup of pose channel. */ + struct IDProperty *oldprops; /* Backup copy (needs freeing) of pose channel's ID properties. */ +} PoseChannelBackup; + +typedef struct PoseBackup { + bool is_bone_selection_relevant; + ListBase /* PoseChannelBackup* */ backups; +} PoseBackup; + +static PoseBackup *pose_backup_create(const Object *ob, + const bAction *action, + const bool is_bone_selection_relevant) +{ + ListBase backups = {NULL, NULL}; + const bArmature *armature = ob->data; + + /* TODO(Sybren): reuse same approach as in `armature_pose.cc` in this function, as that doesn't + * have the assumption that action group names are bone names. */ + LISTBASE_FOREACH (bActionGroup *, agrp, &action->groups) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); + if (pchan == NULL) { + continue; + } + + if (is_bone_selection_relevant && !PBONE_SELECTED(armature, pchan->bone)) { + continue; + } + + PoseChannelBackup *chan_bak = MEM_callocN(sizeof(*chan_bak), "PoseChannelBackup"); + chan_bak->pchan = pchan; + memcpy(&chan_bak->olddata, chan_bak->pchan, sizeof(chan_bak->olddata)); + + if (pchan->prop) { + chan_bak->oldprops = IDP_CopyProperty(pchan->prop); + } + + BLI_addtail(&backups, chan_bak); + } + + /* PoseBackup is constructed late, so that the above loop can use stack variables. */ + PoseBackup *pose_backup = MEM_callocN(sizeof(*pose_backup), __func__); + pose_backup->is_bone_selection_relevant = is_bone_selection_relevant; + pose_backup->backups = backups; + return pose_backup; +} + +PoseBackup *ED_pose_backup_create_all_bones(const Object *ob, const bAction *action) +{ + return pose_backup_create(ob, action, false); +} + +PoseBackup *ED_pose_backup_create_selected_bones(const Object *ob, const bAction *action) +{ + /* See if bone selection is relevant. */ + bool all_bones_selected = true; + bool no_bones_selected = true; + const bArmature *armature = ob->data; + LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + const bool is_selected = PBONE_SELECTED(armature, pchan->bone); + all_bones_selected &= is_selected; + no_bones_selected &= !is_selected; + } + + /* If no bones are selected, act as if all are. */ + const bool is_bone_selection_relevant = !all_bones_selected && !no_bones_selected; + return pose_backup_create(ob, action, is_bone_selection_relevant); +} + +bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup) +{ + return pose_backup->is_bone_selection_relevant; +} + +void ED_pose_backup_restore(const PoseBackup *pbd) +{ + LISTBASE_FOREACH (PoseChannelBackup *, chan_bak, &pbd->backups) { + memcpy(chan_bak->pchan, &chan_bak->olddata, sizeof(chan_bak->olddata)); + + if (chan_bak->oldprops) { + IDP_SyncGroupValues(chan_bak->pchan->prop, chan_bak->oldprops); + } + + /* TODO: constraints settings aren't restored yet, + * even though these could change (though not that likely) */ + } +} + +void ED_pose_backup_free(PoseBackup *pbd) +{ + LISTBASE_FOREACH_MUTABLE (PoseChannelBackup *, chan_bak, &pbd->backups) { + if (chan_bak->oldprops) { + IDP_FreeProperty(chan_bak->oldprops); + } + BLI_freelinkN(&pbd->backups, chan_bak); + } + MEM_freeN(pbd); +} diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index f86cc1159d5..20d7baa39ed 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -318,7 +318,7 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op) TIMEIT_START(recalc_pose_paths); #endif - /* calculate the bones that now have motionpaths... */ + /* Calculate the bones that now have motionpaths. */ /* TODO: only make for the selected bones? */ ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL); @@ -396,7 +396,7 @@ static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* calculate the bones that now have motionpaths... */ + /* Calculate the bones that now have motion-paths. */ /* TODO: only make for the selected bones? */ ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL); @@ -567,7 +567,7 @@ static int pose_flip_names_exec(bContext *C, wmOperator *op) /* since we renamed stuff... */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); } FOREACH_OBJECT_IN_MODE_END; @@ -618,7 +618,7 @@ static int pose_autoside_names_exec(bContext *C, wmOperator *op) /* since we renamed stuff... */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); ob_prev = ob; } @@ -760,7 +760,7 @@ static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op) RNA_boolean_set_array(&ptr, "layers", layers); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); @@ -833,7 +833,7 @@ static int armature_layers_exec(bContext *C, wmOperator *op) RNA_id_pointer_create((ID *)arm, &ptr); RNA_boolean_set_array(&ptr, "layers", layers); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); @@ -919,7 +919,7 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op) RNA_boolean_set_array(&ptr, "layers", layers); if (prev_ob != ob) { - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE); prev_ob = ob; @@ -998,7 +998,7 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op) ED_armature_edit_refresh_layer_used(ob->data); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/armature/pose_lib_2.c b/source/blender/editors/armature/pose_lib_2.c new file mode 100644 index 00000000000..eb091296282 --- /dev/null +++ b/source/blender/editors/armature/pose_lib_2.c @@ -0,0 +1,638 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021, Blender Foundation + */ + +/** \file + * \ingroup edarmature + */ + +#include <math.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" + +#include "BLT_translation.h" + +#include "DNA_armature_types.h" + +#include "BKE_action.h" +#include "BKE_anim_data.h" +#include "BKE_animsys.h" +#include "BKE_armature.h" +#include "BKE_context.h" +#include "BKE_lib_id.h" +#include "BKE_object.h" +#include "BKE_report.h" + +#include "DEG_depsgraph.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" + +#include "ED_armature.h" +#include "ED_asset.h" +#include "ED_keyframing.h" +#include "ED_screen.h" + +#include "armature_intern.h" + +typedef enum ePoseBlendState { + POSE_BLEND_INIT, + POSE_BLEND_BLENDING, + POSE_BLEND_ORIGINAL, + POSE_BLEND_CONFIRM, + POSE_BLEND_CANCEL, +} ePoseBlendState; + +typedef struct PoseBlendData { + ePoseBlendState state; + bool needs_redraw; + + struct { + bool use_release_confirm; + int drag_start_xy[2]; + int init_event_type; + + bool cursor_wrap_enabled; + } release_confirm_info; + + /* For temp-loading the Action from the pose library. */ + AssetTempIDConsumer *temp_id_consumer; + + /* Blend factor, interval [0, 1] for interpolating between current and given pose. */ + float blend_factor; + struct PoseBackup *pose_backup; + + Object *ob; /* Object to work on. */ + bAction *act; /* Pose to blend into the current pose. */ + bool free_action; + + Scene *scene; /* For auto-keying. */ + ScrArea *area; /* For drawing status text. */ + + /** Info-text to print in header. */ + char headerstr[UI_MAX_DRAW_STR]; +} PoseBlendData; + +/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */ +static void poselib_backup_posecopy(PoseBlendData *pbd) +{ + pbd->pose_backup = ED_pose_backup_create_selected_bones(pbd->ob, pbd->act); + + if (pbd->state == POSE_BLEND_INIT) { + /* Ready for blending now. */ + pbd->state = POSE_BLEND_BLENDING; + } +} + +/* ---------------------------- */ + +/* Auto-key/tag bones affected by the pose Action. */ +static void poselib_keytag_pose(bContext *C, Scene *scene, PoseBlendData *pbd) +{ + if (!autokeyframe_cfra_can_key(scene, &pbd->ob->id)) { + return; + } + + AnimData *adt = BKE_animdata_from_id(&pbd->ob->id); + if (adt != NULL && adt->action != NULL && ID_IS_LINKED(&adt->action->id)) { + /* Changes to linked-in Actions are not allowed. */ + return; + } + + bPose *pose = pbd->ob->pose; + bAction *act = pbd->act; + + KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID); + ListBase dsources = {NULL, NULL}; + + /* start tagging/keying */ + const bArmature *armature = pbd->ob->data; + LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) { + /* only for selected bones unless there aren't any selected, in which case all are included */ + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, agrp->name); + if (pchan == NULL) { + continue; + } + + if (ED_pose_backup_is_selection_relevant(pbd->pose_backup) && + !PBONE_SELECTED(armature, pchan->bone)) { + continue; + } + + /* Add data-source override for the PoseChannel, to be used later. */ + ANIM_relative_keyingset_add_source(&dsources, &pbd->ob->id, &RNA_PoseBone, pchan); + } + + /* Perform actual auto-keying. */ + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); + BLI_freelistN(&dsources); + + /* send notifiers for this */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); +} + +/* Apply the relevant changes to the pose */ +static void poselib_blend_apply(bContext *C, wmOperator *op) +{ + PoseBlendData *pbd = (PoseBlendData *)op->customdata; + + if (pbd->state == POSE_BLEND_BLENDING) { + BLI_snprintf(pbd->headerstr, + sizeof(pbd->headerstr), + TIP_("PoseLib blending: \"%s\" at %3.0f%%"), + pbd->act->id.name + 2, + pbd->blend_factor * 100); + ED_area_status_text(pbd->area, pbd->headerstr); + + ED_workspace_status_text( + C, TIP_("Tab: show original pose; Horizontal mouse movement: change blend percentage")); + } + else { + ED_area_status_text(pbd->area, TIP_("PoseLib showing original pose")); + ED_workspace_status_text(C, TIP_("Tab: show blended pose")); + } + + if (!pbd->needs_redraw) { + return; + } + pbd->needs_redraw = false; + + ED_pose_backup_restore(pbd->pose_backup); + + /* The pose needs updating, whether it's for restoring the original pose or for showing the + * result of the blend. */ + DEG_id_tag_update(&pbd->ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pbd->ob); + + if (pbd->state != POSE_BLEND_BLENDING) { + return; + } + + /* Perform the actual blending. */ + struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, 0.0f); + BKE_pose_apply_action_blend(pbd->ob, pbd->act, &anim_eval_context, pbd->blend_factor); +} + +/* ---------------------------- */ + +static void poselib_blend_set_factor(PoseBlendData *pbd, const float new_factor) +{ + pbd->blend_factor = CLAMPIS(new_factor, 0.0f, 1.0f); + pbd->needs_redraw = true; +} + +static void poselib_slide_mouse_update_blendfactor(PoseBlendData *pbd, const wmEvent *event) +{ + if (pbd->release_confirm_info.use_release_confirm) { + /* Release confirm calculates factor based on where the dragging was started from. */ + const float range = 300 * U.pixelsize; + const float new_factor = (event->x - pbd->release_confirm_info.drag_start_xy[0]) / range; + poselib_blend_set_factor(pbd, new_factor); + } + else { + const float new_factor = (event->x - pbd->area->v1->vec.x) / ((float)pbd->area->winx); + poselib_blend_set_factor(pbd, new_factor); + } +} + +/* Return operator return value. */ +static int poselib_blend_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event) +{ + PoseBlendData *pbd = op->customdata; + + if (event->type == MOUSEMOVE) { + poselib_slide_mouse_update_blendfactor(pbd, event); + return OPERATOR_RUNNING_MODAL; + } + + /* Handle the release confirm event directly, it has priority over others. */ + if (pbd->release_confirm_info.use_release_confirm && + (event->type == pbd->release_confirm_info.init_event_type) && (event->val == KM_RELEASE)) { + pbd->state = POSE_BLEND_CONFIRM; + return OPERATOR_RUNNING_MODAL; + } + + /* only accept 'press' event, and ignore 'release', so that we don't get double actions */ + if (ELEM(event->val, KM_PRESS, KM_NOTHING) == 0) { + return OPERATOR_RUNNING_MODAL; + } + + /* NORMAL EVENT HANDLING... */ + /* searching takes priority over normal activity */ + switch (event->type) { + /* Exit - cancel. */ + case EVT_ESCKEY: + case RIGHTMOUSE: + pbd->state = POSE_BLEND_CANCEL; + break; + + /* Exit - confirm. */ + case LEFTMOUSE: + case EVT_RETKEY: + case EVT_PADENTER: + case EVT_SPACEKEY: + pbd->state = POSE_BLEND_CONFIRM; + break; + + /* TODO(Sybren): toggle between original pose and poselib pose. */ + case EVT_TABKEY: + pbd->state = pbd->state == POSE_BLEND_BLENDING ? POSE_BLEND_ORIGINAL : POSE_BLEND_BLENDING; + pbd->needs_redraw = true; + break; + + /* TODO(Sybren): use better UI for slider. */ + } + + return OPERATOR_RUNNING_MODAL; +} + +static void poselib_blend_cursor_update(bContext *C, wmOperator *op) +{ + PoseBlendData *pbd = op->customdata; + + /* Ensure cursor-grab (continuous grabbing) is enabled when using release-confirm. */ + if (pbd->release_confirm_info.use_release_confirm && + !pbd->release_confirm_info.cursor_wrap_enabled) { + WM_cursor_grab_enable(CTX_wm_window(C), WM_CURSOR_WRAP_XY, true, NULL); + pbd->release_confirm_info.cursor_wrap_enabled = true; + } +} + +/* ---------------------------- */ + +static Object *get_poselib_object(bContext *C) +{ + if (C == NULL) { + return NULL; + } + return BKE_object_pose_armature_get(CTX_data_active_object(C)); +} + +static void poselib_tempload_exit(PoseBlendData *pbd) +{ + ED_asset_temp_id_consumer_free(&pbd->temp_id_consumer); +} + +static bAction *poselib_blend_init_get_action(bContext *C, wmOperator *op) +{ + bool asset_handle_valid; + const AssetLibraryReference *asset_library = CTX_wm_asset_library(C); + const AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid); + /* Poll callback should check. */ + BLI_assert((asset_library != NULL) && asset_handle_valid); + + PoseBlendData *pbd = op->customdata; + + pbd->temp_id_consumer = ED_asset_temp_id_consumer_create(&asset_handle); + return (bAction *)ED_asset_temp_id_consumer_ensure_local_id( + pbd->temp_id_consumer, C, asset_library, ID_AC, CTX_data_main(C), op->reports); +} + +static bAction *flip_pose(bContext *C, Object *ob, bAction *action) +{ + bAction *action_copy = (bAction *)BKE_id_copy_ex(NULL, &action->id, NULL, LIB_ID_COPY_LOCALIZE); + + /* Lock the window manager while flipping the pose. Flipping requires temporarily modifying the + * pose, which can cause unwanted visual glitches. */ + wmWindowManager *wm = CTX_wm_manager(C); + const bool interface_was_locked = CTX_wm_interface_locked(C); + WM_set_locked_interface(wm, true); + + BKE_action_flip_with_pose(action_copy, ob); + + WM_set_locked_interface(wm, interface_was_locked); + return action_copy; +} + +/* Return true on success, false if the context isn't suitable. */ +static bool poselib_blend_init_data(bContext *C, wmOperator *op, const wmEvent *event) +{ + op->customdata = NULL; + + /* check if valid poselib */ + Object *ob = get_poselib_object(C); + if (ELEM(NULL, ob, ob->pose, ob->data)) { + BKE_report(op->reports, RPT_ERROR, TIP_("Pose lib is only for armatures in pose mode")); + return false; + } + + /* Set up blend state info. */ + PoseBlendData *pbd; + op->customdata = pbd = MEM_callocN(sizeof(PoseBlendData), "PoseLib Preview Data"); + + bAction *action = poselib_blend_init_get_action(C, op); + if (action == NULL) { + return false; + } + + /* Maybe flip the Action. */ + const bool apply_flipped = RNA_boolean_get(op->ptr, "flipped"); + if (apply_flipped) { + action = flip_pose(C, ob, action); + pbd->free_action = true; + } + pbd->act = action; + + /* Get the basic data. */ + pbd->ob = ob; + pbd->ob->pose = ob->pose; + + pbd->scene = CTX_data_scene(C); + pbd->area = CTX_wm_area(C); + + pbd->state = POSE_BLEND_INIT; + pbd->needs_redraw = true; + pbd->blend_factor = RNA_float_get(op->ptr, "blend_factor"); + /* Just to avoid a clang-analyzer warning (false positive), it's set properly below. */ + pbd->release_confirm_info.use_release_confirm = false; + + /* Release confirm data. Only available if there's an event to work with. */ + if (event != NULL) { + PropertyRNA *release_confirm_prop = RNA_struct_find_property(op->ptr, "release_confirm"); + pbd->release_confirm_info.use_release_confirm = (release_confirm_prop != NULL) && + RNA_property_boolean_get(op->ptr, + release_confirm_prop); + } + + if (pbd->release_confirm_info.use_release_confirm) { + BLI_assert(event != NULL); + pbd->release_confirm_info.drag_start_xy[0] = event->x; + pbd->release_confirm_info.drag_start_xy[1] = event->y; + pbd->release_confirm_info.init_event_type = WM_userdef_event_type_from_keymap_type( + event->type); + } + + /* Make backups for blending and restoring the pose. */ + poselib_backup_posecopy(pbd); + + /* Set pose flags to ensure the depsgraph evaluation doesn't overwrite it. */ + pbd->ob->pose->flag &= ~POSE_DO_UNLOCK; + pbd->ob->pose->flag |= POSE_LOCKED; + + return true; +} + +static void poselib_blend_cleanup(bContext *C, wmOperator *op) +{ + PoseBlendData *pbd = op->customdata; + wmWindow *win = CTX_wm_window(C); + + /* Redraw the header so that it doesn't show any of our stuff anymore. */ + ED_area_status_text(pbd->area, NULL); + ED_workspace_status_text(C, NULL); + + /* This signals the depsgraph to unlock and reevaluate the pose on the next evaluation. */ + bPose *pose = pbd->ob->pose; + pose->flag |= POSE_DO_UNLOCK; + + switch (pbd->state) { + case POSE_BLEND_CONFIRM: { + Scene *scene = pbd->scene; + poselib_keytag_pose(C, scene, pbd); + + /* Ensure the redo panel has the actually-used value, instead of the initial value. */ + RNA_float_set(op->ptr, "blend_factor", pbd->blend_factor); + break; + } + + case POSE_BLEND_INIT: + case POSE_BLEND_BLENDING: + case POSE_BLEND_ORIGINAL: + /* Cleanup should not be called directly from these states. */ + BLI_assert(!"poselib_blend_cleanup: unexpected pose blend state"); + BKE_report(op->reports, RPT_ERROR, "Internal pose library error, cancelling operator"); + ATTR_FALLTHROUGH; + case POSE_BLEND_CANCEL: + ED_pose_backup_restore(pbd->pose_backup); + break; + } + + if (pbd->release_confirm_info.cursor_wrap_enabled) { + WM_cursor_grab_disable(win, pbd->release_confirm_info.drag_start_xy); + pbd->release_confirm_info.cursor_wrap_enabled = false; + } + + DEG_id_tag_update(&pbd->ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pbd->ob); + /* Update mouse-hover highlights. */ + WM_event_add_mousemove(win); +} + +static void poselib_blend_free(wmOperator *op) +{ + PoseBlendData *pbd = op->customdata; + if (pbd == NULL) { + return; + } + + if (pbd->free_action) { + /* Run before #poselib_tempload_exit to avoid any problems from indirectly + * referenced ID pointers. */ + BKE_id_free(NULL, pbd->act); + } + poselib_tempload_exit(pbd); + + /* Must have been dealt with before! */ + BLI_assert(pbd->release_confirm_info.cursor_wrap_enabled == false); + + /* Free temp data for operator */ + ED_pose_backup_free(pbd->pose_backup); + pbd->pose_backup = NULL; + + MEM_SAFE_FREE(op->customdata); +} + +static int poselib_blend_exit(bContext *C, wmOperator *op) +{ + PoseBlendData *pbd = op->customdata; + const ePoseBlendState exit_state = pbd->state; + + poselib_blend_cleanup(C, op); + poselib_blend_free(op); + + if (exit_state == POSE_BLEND_CANCEL) { + return OPERATOR_CANCELLED; + } + return OPERATOR_FINISHED; +} + +/* Cancel previewing operation (called when exiting Blender) */ +static void poselib_blend_cancel(bContext *C, wmOperator *op) +{ + PoseBlendData *pbd = op->customdata; + pbd->state = POSE_BLEND_CANCEL; + poselib_blend_exit(C, op); +} + +/* Main modal status check. */ +static int poselib_blend_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + const int operator_result = poselib_blend_handle_event(C, op, event); + + poselib_blend_cursor_update(C, op); + + const PoseBlendData *pbd = op->customdata; + if (ELEM(pbd->state, POSE_BLEND_CONFIRM, POSE_BLEND_CANCEL)) { + return poselib_blend_exit(C, op); + } + + if (pbd->needs_redraw) { + poselib_blend_apply(C, op); + } + + return operator_result; +} + +/* Modal Operator init. */ +static int poselib_blend_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + if (!poselib_blend_init_data(C, op, event)) { + poselib_blend_free(op); + return OPERATOR_CANCELLED; + } + + /* Do initial apply to have something to look at. */ + poselib_blend_apply(C, op); + + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; +} + +/* Single-shot apply. */ +static int poselib_blend_exec(bContext *C, wmOperator *op) +{ + if (!poselib_blend_init_data(C, op, NULL)) { + poselib_blend_free(op); + return OPERATOR_CANCELLED; + } + + poselib_blend_apply(C, op); + + PoseBlendData *pbd = op->customdata; + pbd->state = POSE_BLEND_CONFIRM; + return poselib_blend_exit(C, op); +} + +static bool poselib_asset_in_context(bContext *C) +{ + bool asset_handle_valid; + /* Check whether the context provides the asset data needed to add a pose. */ + const AssetLibraryReference *asset_library = CTX_wm_asset_library(C); + AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid); + + return (asset_library != NULL) && asset_handle_valid && + (asset_handle.file_data->blentype == ID_AC); +} + +/* Poll callback for operators that require existing PoseLib data (with poses) to work. */ +static bool poselib_blend_poll(bContext *C) +{ + Object *ob = get_poselib_object(C); + if (ELEM(NULL, ob, ob->pose, ob->data)) { + /* Pose lib is only for armatures in pose mode. */ + return false; + } + + return poselib_asset_in_context(C); +} + +void POSELIB_OT_apply_pose_asset(wmOperatorType *ot) +{ + /* Identifiers: */ + ot->name = "Apply Pose Library Pose"; + ot->idname = "POSELIB_OT_apply_pose_asset"; + ot->description = "Apply the given Pose Action to the rig"; + + /* Callbacks: */ + ot->exec = poselib_blend_exec; + ot->poll = poselib_blend_poll; + + /* Flags: */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties: */ + RNA_def_float_factor(ot->srna, + "blend_factor", + 1.0f, + 0.0f, + 1.0f, + "Blend Factor", + "Amount that the pose is applied on top of the existing poses", + 0.0f, + 1.0f); + RNA_def_boolean(ot->srna, + "flipped", + false, + "Apply Flipped", + "When enabled, applies the pose flipped over the X-axis"); +} + +void POSELIB_OT_blend_pose_asset(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* Identifiers: */ + ot->name = "Blend Pose Library Pose"; + ot->idname = "POSELIB_OT_blend_pose_asset"; + ot->description = "Blend the given Pose Action to the rig"; + + /* Callbacks: */ + ot->invoke = poselib_blend_invoke; + ot->modal = poselib_blend_modal; + ot->cancel = poselib_blend_cancel; + ot->exec = poselib_blend_exec; + ot->poll = poselib_blend_poll; + + /* Flags: */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* Properties: */ + prop = RNA_def_float_factor(ot->srna, + "blend_factor", + 0.0f, + 0.0f, + 1.0f, + "Blend Factor", + "Amount that the pose is applied on top of the existing poses", + 0.0f, + 1.0f); + /* Blending should always start at 0%, and not at whatever percentage was last used. This RNA + * property just exists for symmetry with the Apply operator (and thus simplicity of the rest of + * the code, which can assume this property exists). */ + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + RNA_def_boolean(ot->srna, + "flipped", + false, + "Apply Flipped", + "When enabled, applies the pose flipped over the X-axis"); + prop = RNA_def_boolean(ot->srna, + "release_confirm", + false, + "Confirm on Release", + "Always confirm operation when releasing button"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 8fc06a5f962..c39fcb790dd 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -69,7 +69,7 @@ /* ***************** Pose Select Utilities ********************* */ -/* Note: SEL_TOGGLE is assumed to have already been handled! */ +/* NOTE: SEL_TOGGLE is assumed to have already been handled! */ static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode) { /* select pchan only if selectable, but deselect works always */ @@ -161,9 +161,9 @@ void ED_armature_pose_select_pick_bone(ViewLayer *view_layer, /* Since we do unified select, we don't shift+select a bone if the * armature object was not active yet. - * Note, special exception for armature mode so we can do multi-select + * NOTE(campbell): special exception for armature mode so we can do multi-select * we could check for multi-select explicitly but think its fine to - * always give predictable behavior in weight paint mode - campbell */ + * always give predictable behavior in weight paint mode. */ if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) == 0)) { /* When we are entering into posemode via toggle-select, * from another active object - always select the bone. */ diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 9b1de742332..1a1685e4a01 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -833,7 +833,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) float prevFrameF, nextFrameF; if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) { - BLI_assert(!"Invalid pfl data"); + BLI_assert_msg(0, "Invalid pfl data"); return; } @@ -1005,14 +1005,14 @@ static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso) if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) { /* Bbone properties - they all start a "bbone_" prefix. */ - /* TODO Not implemented */ + /* TODO: Not implemented. */ // pose_slide_apply_props(pso, pfl, "bbone_"); } if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) { /* Not strictly a transform, but custom properties contribute * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */ - /* TODO Not implemented */ + /* TODO: Not implemented. */ // pose_slide_apply_props(pso, pfl, "[\""); } } diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index e597fd46106..1118e84ef4f 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -457,7 +457,7 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) /* For the affected bones, reset specific constraints that are now known to be invalid. */ applyarmature_reset_constraints(pose, use_selected); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); @@ -557,7 +557,7 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); } @@ -1228,7 +1228,7 @@ static int pose_clear_transform_generic_exec(bContext *C, DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY); - /* note, notifier might evolve */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter); } } diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt index 8c5f91561b7..a27975bc37b 100644 --- a/source/blender/editors/asset/CMakeLists.txt +++ b/source/blender/editors/asset/CMakeLists.txt @@ -19,6 +19,7 @@ set(INC ../include ../../blenkernel ../../blenlib + ../../blenloader ../../makesdna ../../makesrna ../../windowmanager @@ -30,10 +31,14 @@ set(INC_SYS set(SRC asset_edit.cc + asset_list.cc asset_ops.cc + asset_temp_id_consumer.cc ) set(LIB + bf_blenloader + bf_blenkernel ) blender_add_lib(bf_editor_asset "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/asset/asset_edit.cc b/source/blender/editors/asset/asset_edit.cc index d20de4141cb..f4860737193 100644 --- a/source/blender/editors/asset/asset_edit.cc +++ b/source/blender/editors/asset/asset_edit.cc @@ -18,11 +18,18 @@ * \ingroup edasset */ +#include <memory> +#include <string> + #include "BKE_asset.h" #include "BKE_context.h" #include "BKE_lib_id.h" +#include "BLO_readfile.h" + #include "DNA_ID.h" +#include "DNA_asset_types.h" +#include "DNA_space_types.h" #include "UI_interface_icons.h" @@ -30,6 +37,8 @@ #include "ED_asset.h" +using namespace blender; + bool ED_asset_mark_id(const bContext *C, ID *id) { if (id->asset_data) { @@ -45,6 +54,9 @@ bool ED_asset_mark_id(const bContext *C, ID *id) UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true); + /* Important for asset storage to update properly! */ + ED_assetlist_storage_tag_main_data_dirty(); + return true; } @@ -57,6 +69,9 @@ bool ED_asset_clear_id(ID *id) /* Don't clear fake user here, there's no guarantee that it was actually set by * #ED_asset_mark_id(), it might have been something/someone else. */ + /* Important for asset storage to update properly! */ + ED_assetlist_storage_tag_main_data_dirty(); + return true; } @@ -65,3 +80,76 @@ bool ED_asset_can_make_single_from_context(const bContext *C) /* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */ return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != nullptr; } + +/* TODO better place? */ +/* TODO What about the setter and the `itemf` callback? */ +#include "BKE_preferences.h" +#include "DNA_asset_types.h" +#include "DNA_userdef_types.h" +int ED_asset_library_reference_to_enum_value(const AssetLibraryReference *library) +{ + /* Simple case: Predefined repository, just set the value. */ + if (library->type < ASSET_LIBRARY_CUSTOM) { + return library->type; + } + + /* Note that the path isn't checked for validity here. If an invalid library path is used, the + * Asset Browser can give a nice hint on what's wrong. */ + const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( + &U, library->custom_library_index); + if (user_library) { + return ASSET_LIBRARY_CUSTOM + library->custom_library_index; + } + + BLI_assert(0); + return ASSET_LIBRARY_LOCAL; +} + +AssetLibraryReference ED_asset_library_reference_from_enum_value(int value) +{ + AssetLibraryReference library; + + /* Simple case: Predefined repository, just set the value. */ + if (value < ASSET_LIBRARY_CUSTOM) { + library.type = value; + library.custom_library_index = -1; + BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL)); + return library; + } + + const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( + &U, value - ASSET_LIBRARY_CUSTOM); + + /* Note that the path isn't checked for validity here. If an invalid library path is used, the + * Asset Browser can give a nice hint on what's wrong. */ + const bool is_valid = (user_library->name[0] && user_library->path[0]); + if (!user_library) { + library.type = ASSET_LIBRARY_LOCAL; + library.custom_library_index = -1; + } + else if (user_library && is_valid) { + library.custom_library_index = value - ASSET_LIBRARY_CUSTOM; + library.type = ASSET_LIBRARY_CUSTOM; + } + return library; +} + +const char *ED_asset_handle_get_name(const AssetHandle *asset) +{ + return asset->file_data->name; +} + +void ED_asset_handle_get_full_library_path(const bContext *C, + const AssetLibraryReference *asset_library, + const AssetHandle *asset, + char r_full_lib_path[FILE_MAX_LIBEXTRA]) +{ + *r_full_lib_path = '\0'; + + std::string asset_path = ED_assetlist_asset_filepath_get(C, *asset_library, *asset); + if (asset_path.empty()) { + return; + } + + BLO_library_path_explode(asset_path.c_str(), r_full_lib_path, nullptr, nullptr); +} diff --git a/source/blender/editors/asset/asset_list.cc b/source/blender/editors/asset/asset_list.cc new file mode 100644 index 00000000000..dd1c5f360a0 --- /dev/null +++ b/source/blender/editors/asset/asset_list.cc @@ -0,0 +1,637 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edasset + * + * Abstractions to manage runtime asset lists with a global cache for multiple UI elements to + * access. + * Internally this uses the #FileList API and structures from `filelist.c`. This is just because it + * contains most necessary logic already and there's not much time for a more long-term solution. + */ + +#include <optional> +#include <string> + +#include "BKE_asset.h" +#include "BKE_context.h" +#include "BKE_screen.h" + +#include "BLI_function_ref.hh" +#include "BLI_hash.hh" +#include "BLI_map.hh" +#include "BLI_path_util.h" +#include "BLI_utility_mixins.hh" + +#include "DNA_asset_types.h" +#include "DNA_space_types.h" + +#include "BKE_preferences.h" + +#include "ED_asset.h" +#include "ED_fileselect.h" +#include "ED_screen.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* XXX uses private header of file-space. */ +#include "../space_file/filelist.h" + +using namespace blender; + +/** + * Wrapper to add logic to the AssetLibraryReference DNA struct. + */ +class AssetLibraryReferenceWrapper { + const AssetLibraryReference reference_; + + public: + /* Intentionally not `explicit`, allow implicit conversion for convenience. Might have to be + * NOLINT */ + AssetLibraryReferenceWrapper(const AssetLibraryReference &reference); + ~AssetLibraryReferenceWrapper() = default; + + friend bool operator==(const AssetLibraryReferenceWrapper &a, + const AssetLibraryReferenceWrapper &b); + uint64_t hash() const; +}; + +AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryReference &reference) + : reference_(reference) +{ +} + +bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b) +{ + return (a.reference_.type == b.reference_.type) && (a.reference_.type == ASSET_LIBRARY_CUSTOM) ? + (a.reference_.custom_library_index == b.reference_.custom_library_index) : + true; +} + +uint64_t AssetLibraryReferenceWrapper::hash() const +{ + uint64_t hash1 = DefaultHash<decltype(reference_.type)>{}(reference_.type); + if (reference_.type != ASSET_LIBRARY_CUSTOM) { + return hash1; + } + + uint64_t hash2 = DefaultHash<decltype(reference_.custom_library_index)>{}( + reference_.custom_library_index); + return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */ +} + +/* -------------------------------------------------------------------- */ +/** \name Asset list API + * + * Internally re-uses #FileList from the File Browser. It does all the heavy lifting already. + * \{ */ + +/** + * RAII wrapper for `FileList` + */ +class FileListWrapper { + static void filelist_free_fn(FileList *list) + { + filelist_free(list); + MEM_freeN(list); + } + + std::unique_ptr<FileList, decltype(&filelist_free_fn)> file_list_; + + public: + explicit FileListWrapper(eFileSelectType filesel_type) + : file_list_(filelist_new(filesel_type), filelist_free_fn) + { + } + FileListWrapper(FileListWrapper &&other) = default; + FileListWrapper &operator=(FileListWrapper &&other) = default; + ~FileListWrapper() + { + /* Destructs the owned pointer. */ + file_list_ = nullptr; + } + + operator FileList *() const + { + return file_list_.get(); + } +}; + +class PreviewTimer { + /* Non-owning! The Window-Manager registers and owns this. */ + wmTimer *timer_ = nullptr; + + public: + void ensureRunning(const bContext *C) + { + if (!timer_) { + timer_ = WM_event_add_timer_notifier( + CTX_wm_manager(C), CTX_wm_window(C), NC_ASSET | ND_ASSET_LIST_PREVIEW, 0.01); + } + } + + void stop(const bContext *C) + { + if (timer_) { + WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), timer_); + timer_ = nullptr; + } + } +}; + +class AssetList : NonCopyable { + FileListWrapper filelist_; + AssetLibraryReference library_ref_; + PreviewTimer previews_timer_; + + public: + AssetList() = delete; + AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref); + AssetList(AssetList &&other) = default; + ~AssetList() = default; + + void setup(const AssetFilterSettings *filter_settings = nullptr); + void fetch(const bContext &C); + void ensurePreviewsJob(bContext *C); + void clear(bContext *C); + + bool needsRefetch() const; + void iterate(AssetListIterFn fn) const; + bool listen(const wmNotifier ¬ifier) const; + int size() const; + void tagMainDataDirty() const; + void remapID(ID *id_old, ID *id_new) const; + StringRef filepath() const; +}; + +AssetList::AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref) + : filelist_(filesel_type), library_ref_(asset_library_ref) +{ +} + +void AssetList::setup(const AssetFilterSettings *filter_settings) +{ + FileList *files = filelist_; + + /* TODO there should only be one (FileSelectAssetLibraryUID vs. AssetLibraryReference). */ + FileSelectAssetLibraryUID file_asset_lib_ref; + file_asset_lib_ref.type = library_ref_.type; + file_asset_lib_ref.custom_library_index = library_ref_.custom_library_index; + + bUserAssetLibrary *user_library = nullptr; + + /* Ensure valid repository, or fall-back to local one. */ + if (library_ref_.type == ASSET_LIBRARY_CUSTOM) { + BLI_assert(library_ref_.custom_library_index >= 0); + + user_library = BKE_preferences_asset_library_find_from_index( + &U, library_ref_.custom_library_index); + } + + /* Relevant bits from file_refresh(). */ + /* TODO pass options properly. */ + filelist_setrecursion(files, 1); + filelist_setsorting(files, FILE_SORT_ALPHA, false); + filelist_setlibrary(files, &file_asset_lib_ref); + /* TODO different filtering settings require the list to be reread. That's a no-go for when we + * want to allow showing the same asset library with different filter settings (as in, + * different ID types). The filelist needs to be made smarter somehow, maybe goes together with + * the plan to separate the view (preview caching, filtering, etc. ) from the data. */ + filelist_setfilter_options( + files, + filter_settings != nullptr, + true, + true, /* Just always hide parent, prefer to not add an extra user option for this. */ + FILE_TYPE_BLENDERLIB, + filter_settings ? filter_settings->id_types : FILTER_ID_ALL, + true, + "", + ""); + + char path[FILE_MAXDIR] = ""; + if (user_library) { + BLI_strncpy(path, user_library->path, sizeof(path)); + filelist_setdir(files, path); + } + else { + filelist_setdir(files, path); + } +} + +void AssetList::fetch(const bContext &C) +{ + FileList *files = filelist_; + + if (filelist_needs_force_reset(files)) { + filelist_readjob_stop(files, CTX_wm_manager(&C)); + filelist_clear(files); + } + + if (filelist_needs_reading(files)) { + if (!filelist_pending(files)) { + filelist_readjob_start(files, NC_ASSET | ND_ASSET_LIST_READING, &C); + } + } + filelist_sort(files); + filelist_filter(files); +} + +bool AssetList::needsRefetch() const +{ + return filelist_needs_force_reset(filelist_) || filelist_needs_reading(filelist_); +} + +void AssetList::iterate(AssetListIterFn fn) const +{ + FileList *files = filelist_; + int numfiles = filelist_files_ensure(files); + + for (int i = 0; i < numfiles; i++) { + FileDirEntry *file = filelist_file(files, i); + if (!fn(*file)) { + break; + } + } +} + +void AssetList::ensurePreviewsJob(bContext *C) +{ + FileList *files = filelist_; + int numfiles = filelist_files_ensure(files); + + filelist_cache_previews_set(files, true); + filelist_file_cache_slidingwindow_set(files, 256); + /* TODO fetch all previews for now. */ + filelist_file_cache_block(files, numfiles / 2); + filelist_cache_previews_update(files); + + { + const bool previews_running = filelist_cache_previews_running(files) && + !filelist_cache_previews_done(files); + if (previews_running) { + previews_timer_.ensureRunning(C); + } + else { + /* Preview is not running, no need to keep generating update events! */ + previews_timer_.stop(C); + } + } +} + +void AssetList::clear(bContext *C) +{ + /* Based on #ED_fileselect_clear() */ + + FileList *files = filelist_; + filelist_readjob_stop(files, CTX_wm_manager(C)); + filelist_freelib(files); + filelist_clear(files); + + WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr); +} + +/** + * \return True if the asset-list needs a UI redraw. + */ +bool AssetList::listen(const wmNotifier ¬ifier) const +{ + switch (notifier.category) { + case NC_ID: { + if (ELEM(notifier.action, NA_RENAME)) { + return true; + } + break; + } + case NC_ASSET: + if (ELEM(notifier.data, ND_ASSET_LIST, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) { + return true; + } + if (ELEM(notifier.action, NA_ADDED, NA_REMOVED, NA_EDITED)) { + return true; + } + break; + } + + return false; +} + +/** + * \return The number of assets in the list. + */ +int AssetList::size() const +{ + return filelist_files_ensure(filelist_); +} + +void AssetList::tagMainDataDirty() const +{ + if (filelist_needs_reset_on_main_changes(filelist_)) { + /* Full refresh of the file list if local asset data was changed. Refreshing this view + * is cheap and users expect this to be updated immediately. */ + filelist_tag_force_reset(filelist_); + } +} + +void AssetList::remapID(ID * /*id_old*/, ID * /*id_new*/) const +{ + /* Trigger full re-fetch of the file list if main data was changed, don't even attempt remap + * pointers. We could give file list types a id-remap callback, but it's probably not worth it. + * Refreshing local file lists is relatively cheap. */ + tagMainDataDirty(); +} + +StringRef AssetList::filepath() const +{ + return filelist_dir(filelist_); +} +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Runtime asset list cache + * \{ */ + +/** + * Class managing a global asset list map, each entry being a list for a specific asset library. + */ +class AssetListStorage { + using AssetListMap = Map<AssetLibraryReferenceWrapper, AssetList>; + + public: + /* Purely static class, can't instantiate this. */ + AssetListStorage() = delete; + + static void fetch_library(const AssetLibraryReference &library_reference, + const bContext &C, + const AssetFilterSettings *filter_settings = nullptr); + static void destruct(); + static AssetList *lookup_list(const AssetLibraryReference &library_ref); + static void tagMainDataDirty(); + static void remapID(ID *id_new, ID *id_old); + + private: + static std::optional<eFileSelectType> asset_library_reference_to_fileselect_type( + const AssetLibraryReference &library_reference); + + using is_new_t = bool; + static std::tuple<AssetList &, is_new_t> ensure_list_storage( + const AssetLibraryReference &library_reference, eFileSelectType filesel_type); + + static AssetListMap &global_storage(); +}; + +void AssetListStorage::fetch_library(const AssetLibraryReference &library_reference, + const bContext &C, + const AssetFilterSettings *filter_settings) +{ + std::optional filesel_type = asset_library_reference_to_fileselect_type(library_reference); + if (!filesel_type) { + return; + } + + auto [list, is_new] = ensure_list_storage(library_reference, *filesel_type); + if (is_new || list.needsRefetch()) { + list.setup(filter_settings); + list.fetch(C); + } +} + +void AssetListStorage::destruct() +{ + global_storage().~AssetListMap(); +} + +AssetList *AssetListStorage::lookup_list(const AssetLibraryReference &library_ref) +{ + return global_storage().lookup_ptr(library_ref); +} + +void AssetListStorage::tagMainDataDirty() +{ + for (AssetList &list : global_storage().values()) { + list.tagMainDataDirty(); + } +} + +void AssetListStorage::remapID(ID *id_new, ID *id_old) +{ + for (AssetList &list : global_storage().values()) { + list.remapID(id_new, id_old); + } +} + +std::optional<eFileSelectType> AssetListStorage::asset_library_reference_to_fileselect_type( + const AssetLibraryReference &library_reference) +{ + switch (library_reference.type) { + case ASSET_LIBRARY_CUSTOM: + return FILE_LOADLIB; + case ASSET_LIBRARY_LOCAL: + return FILE_MAIN_ASSET; + } + + return std::nullopt; +} + +std::tuple<AssetList &, AssetListStorage::is_new_t> AssetListStorage::ensure_list_storage( + const AssetLibraryReference &library_reference, eFileSelectType filesel_type) +{ + AssetListMap &storage = global_storage(); + + if (AssetList *list = storage.lookup_ptr(library_reference)) { + return {*list, false}; + } + storage.add(library_reference, AssetList(filesel_type, library_reference)); + return {storage.lookup(library_reference), true}; +} + +/** + * Wrapper for Construct on First Use idiom, to avoid the Static Initialization Fiasco. + */ +AssetListStorage::AssetListMap &AssetListStorage::global_storage() +{ + static AssetListMap global_storage_; + return global_storage_; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name C-API + * \{ */ + +/** + * Invoke asset list reading, potentially in a parallel job. Won't wait until the job is done, + * and may return earlier. + */ +void ED_assetlist_storage_fetch(const AssetLibraryReference *library_reference, + const AssetFilterSettings *filter_settings, + const bContext *C) +{ + AssetListStorage::fetch_library(*library_reference, *C, filter_settings); +} + +void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference, bContext *C) +{ + + AssetList *list = AssetListStorage::lookup_list(*library_reference); + if (list) { + list->ensurePreviewsJob(C); + } +} + +void ED_assetlist_clear(const AssetLibraryReference *library_reference, bContext *C) +{ + AssetList *list = AssetListStorage::lookup_list(*library_reference); + if (list) { + list->clear(C); + } +} + +bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *library_reference) +{ + return AssetListStorage::lookup_list(*library_reference) != nullptr; +} + +/* TODO expose AssetList with an iterator? */ +void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn) +{ + AssetList *list = AssetListStorage::lookup_list(*library_reference); + if (list) { + list->iterate(fn); + } +} + +/* TODO hack to use the File Browser path, so we can keep all the import logic handled by the asset + * API. Get rid of this once the File Browser is integrated better with the asset list. */ +static const char *assetlist_library_path_from_sfile_get_hack(const bContext *C) +{ + SpaceFile *sfile = CTX_wm_space_file(C); + if (!sfile || !ED_fileselect_is_asset_browser(sfile)) { + return nullptr; + } + + FileAssetSelectParams *asset_select_params = ED_fileselect_get_asset_params(sfile); + if (!asset_select_params) { + return nullptr; + } + + return filelist_dir(sfile->files); +} + +std::string ED_assetlist_asset_filepath_get(const bContext *C, + const AssetLibraryReference &library_reference, + const AssetHandle &asset_handle) +{ + if (asset_handle.file_data->id || !asset_handle.file_data->asset_data) { + return {}; + } + const char *library_path = ED_assetlist_library_path(&library_reference); + if (!library_path) { + library_path = assetlist_library_path_from_sfile_get_hack(C); + } + if (!library_path) { + return {}; + } + const char *asset_relpath = asset_handle.file_data->relpath; + + char path[FILE_MAX_LIBEXTRA]; + BLI_join_dirfile(path, sizeof(path), library_path, asset_relpath); + + return path; +} + +ID *ED_assetlist_asset_local_id_get(const AssetHandle *asset_handle) +{ + return asset_handle->file_data->asset_data ? asset_handle->file_data->id : nullptr; +} + +ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle) +{ + ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data); + if (imbuf) { + return imbuf; + } + + return filelist_geticon_image_ex(asset_handle->file_data); +} + +const char *ED_assetlist_library_path(const AssetLibraryReference *library_reference) +{ + AssetList *list = AssetListStorage::lookup_list(*library_reference); + if (list) { + return list->filepath().data(); + } + return nullptr; +} + +/** + * \return True if the region needs a UI redraw. + */ +bool ED_assetlist_listen(const AssetLibraryReference *library_reference, + const wmNotifier *notifier) +{ + AssetList *list = AssetListStorage::lookup_list(*library_reference); + if (list) { + return list->listen(*notifier); + } + return false; +} + +/** + * \return The number of assets stored in the asset list for \a library_reference, or -1 if there + * is no list fetched for it. + */ +int ED_assetlist_size(const AssetLibraryReference *library_reference) +{ + AssetList *list = AssetListStorage::lookup_list(*library_reference); + if (list) { + return list->size(); + } + return -1; +} + +/** + * Tag all asset lists in the storage that show main data as needing an update (re-fetch). + * + * This only tags the data. If the asset list is visible on screen, the space is still responsible + * for ensuring the necessary redraw. It can use #ED_assetlist_listen() to check if the asset-list + * needs a redraw for a given notifier. + */ +void ED_assetlist_storage_tag_main_data_dirty() +{ + AssetListStorage::tagMainDataDirty(); +} + +/** + * Remapping of ID pointers within the asset lists. Typically called when an ID is deleted to clear + * all references to it (\a id_new is null then). + */ +void ED_assetlist_storage_id_remap(ID *id_old, ID *id_new) +{ + AssetListStorage::remapID(id_old, id_new); +} + +/** + * Can't wait for static deallocation to run. There's nested data allocated with our guarded + * allocator, it will complain about unfreed memory on exit. + */ +void ED_assetlist_storage_exit() +{ + AssetListStorage::destruct(); +} + +/** \} */ diff --git a/source/blender/editors/asset/asset_ops.cc b/source/blender/editors/asset/asset_ops.cc index 8ca1b488a1d..79edd1f8a6a 100644 --- a/source/blender/editors/asset/asset_ops.cc +++ b/source/blender/editors/asset/asset_ops.cc @@ -252,8 +252,41 @@ static void ASSET_OT_clear(wmOperatorType *ot) /* -------------------------------------------------------------------- */ +static bool asset_list_refresh_poll(bContext *C) +{ + const AssetLibraryReference *library = CTX_wm_asset_library(C); + if (!library) { + return false; + } + + return ED_assetlist_storage_has_list_for_library(library); +} + +static int asset_list_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) +{ + const AssetLibraryReference *library = CTX_wm_asset_library(C); + ED_assetlist_clear(library, C); + return OPERATOR_FINISHED; +} + +static void ASSET_OT_list_refresh(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Refresh Asset List"; + ot->description = "Trigger a reread of the assets"; + ot->idname = "ASSET_OT_list_refresh"; + + /* api callbacks */ + ot->exec = asset_list_refresh_exec; + ot->poll = asset_list_refresh_poll; +} + +/* -------------------------------------------------------------------- */ + void ED_operatortypes_asset(void) { WM_operatortype_append(ASSET_OT_mark); WM_operatortype_append(ASSET_OT_clear); + + WM_operatortype_append(ASSET_OT_list_refresh); } diff --git a/source/blender/editors/asset/asset_temp_id_consumer.cc b/source/blender/editors/asset/asset_temp_id_consumer.cc new file mode 100644 index 00000000000..24e1fc86fef --- /dev/null +++ b/source/blender/editors/asset/asset_temp_id_consumer.cc @@ -0,0 +1,113 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edasset + * + * API for temporary loading of asset IDs. + * Uses the `BLO_library_temp_xxx()` API internally. + */ + +#include "DNA_asset_types.h" +#include "DNA_space_types.h" + +#include "BKE_report.h" + +#include "BLI_utility_mixins.hh" + +#include "BLO_readfile.h" + +#include "MEM_guardedalloc.h" + +#include "ED_asset.h" + +using namespace blender; + +class AssetTemporaryIDConsumer : NonCopyable, NonMovable { + const AssetHandle &handle_; + TempLibraryContext *temp_lib_context_ = nullptr; + + public: + AssetTemporaryIDConsumer(const AssetHandle &handle) : handle_(handle) + { + } + ~AssetTemporaryIDConsumer() + { + if (temp_lib_context_) { + BLO_library_temp_free(temp_lib_context_); + } + } + + ID *get_local_id() + { + return ED_assetlist_asset_local_id_get(&handle_); + } + + ID *import_id(const bContext *C, + const AssetLibraryReference &asset_library, + ID_Type id_type, + Main &bmain, + ReportList &reports) + { + const char *asset_name = ED_asset_handle_get_name(&handle_); + char blend_file_path[FILE_MAX_LIBEXTRA]; + ED_asset_handle_get_full_library_path(C, &asset_library, &handle_, blend_file_path); + + temp_lib_context_ = BLO_library_temp_load_id( + &bmain, blend_file_path, id_type, asset_name, &reports); + + if (temp_lib_context_ == nullptr || temp_lib_context_->temp_id == nullptr) { + BKE_reportf(&reports, RPT_ERROR, "Unable to load %s from %s", asset_name, blend_file_path); + return nullptr; + } + + BLI_assert(GS(temp_lib_context_->temp_id->name) == id_type); + return temp_lib_context_->temp_id; + } +}; + +AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle) +{ + if (!handle) { + return nullptr; + } + BLI_assert(handle->file_data->asset_data != nullptr); + return reinterpret_cast<AssetTempIDConsumer *>( + OBJECT_GUARDED_NEW(AssetTemporaryIDConsumer, *handle)); +} + +void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer) +{ + OBJECT_GUARDED_SAFE_DELETE(*consumer, AssetTemporaryIDConsumer); +} + +ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer_, + const bContext *C, + const AssetLibraryReference *asset_library, + ID_Type id_type, + Main *bmain, + ReportList *reports) +{ + if (!(consumer_ && asset_library && bmain && reports)) { + return nullptr; + } + AssetTemporaryIDConsumer *consumer = reinterpret_cast<AssetTemporaryIDConsumer *>(consumer_); + + if (ID *local_id = consumer->get_local_id()) { + return local_id; + } + return consumer->import_id(C, *asset_library, id_type, *bmain, *reports); +} diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 58cd69781a7..e7d97ce343c 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1929,7 +1929,7 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) } /* Never allow the order to exceed the number of points - * - note, this is ok but changes unselected nurbs, disable for now */ + * NOTE: this is ok but changes unselected nurbs, disable for now. */ #if 0 if ((nu != NULL) && (nu->type == CU_NURBS)) { clamp_nurb_order_u(nu); @@ -1988,7 +1988,7 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) nu->bp = bp1; /* Never allow the order to exceed the number of points - * - note, this is ok but changes unselected nurbs, disable for now */ + * NOTE: this is ok but changes unselected nurbs, disable for now. */ #if 0 if (nu->type == CU_NURBS) { clamp_nurb_order_u(nu); @@ -6877,7 +6877,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { Nurb *newnu = BKE_nurb_duplicate(nu); - if (ob_active->totcol) { /* TODO, merge material lists */ + if (ob_active->totcol) { /* TODO: merge material lists. */ CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1); } else { diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 065763764c1..2be55accd3a 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -485,7 +485,7 @@ Nurb *ED_curve_add_nurbs_primitive( break; default: /* should never happen */ - BLI_assert(!"invalid nurbs type"); + BLI_assert_msg(0, "invalid nurbs type"); return NULL; } diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index febcf83116b..26906b0ddcd 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -698,7 +698,7 @@ static void curve_draw_exec_precalc(wmOperator *op) } if ((cps->radius_taper_start != 0.0f) || (cps->radius_taper_end != 0.0f)) { - /* note, we could try to de-duplicate the length calculations above */ + /* NOTE: we could try to de-duplicate the length calculations above. */ const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); BLI_mempool_iter iter; diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index 88f6398567d..210411c6eb5 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -267,7 +267,7 @@ static void curve_undosys_step_decode(struct bContext *C, } undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr); cu->editnurb->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 95970cff4ef..e43e4194c51 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -656,7 +656,7 @@ static void txt_add_object(bContext *C, obedit = BKE_object_add(bmain, view_layer, OB_FONT, NULL); base = view_layer->basact; - /* seems to assume view align ? TODO - look into this, could be an operator option */ + /* seems to assume view align ? TODO: look into this, could be an operator option. */ ED_object_base_init_transform_on_add(base->object, NULL, rot); BKE_object_where_is_calc(depsgraph, scene, obedit); diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index a305a997d50..6eaf8971eb0 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -341,7 +341,7 @@ static Object *editfont_object_from_context(bContext *C) typedef struct FontUndoStep { UndoStep step; - /* note: will split out into list for multi-object-editmode. */ + /* NOTE: will split out into list for multi-object-editmode. */ UndoRefID_Object obedit_ref; UndoFont data; } FontUndoStep; @@ -379,7 +379,7 @@ static void font_undosys_step_decode(struct bContext *C, Curve *cu = obedit->data; undofont_to_editfont(&us->data, cu); - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); ED_undo_object_set_active_or_warn( CTX_data_scene(C), CTX_data_view_layer(C), obedit, us_p->name, &LOG); diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c index 2896aa25930..2ec287a62e9 100644 --- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c +++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c @@ -51,7 +51,7 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info, const bool UNUSED(select), const float color[4]) { - /* TODO store the Batches inside the GizmoGeomInfo and updated it when geom changes + /* TODO: store the Batches inside the GizmoGeomInfo and updated it when geom changes * So we don't need to re-created and discard it every time */ GPUVertBuf *vbo; diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c index 4e56ceb9fd4..f842c20b74f 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_presets.c +++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c @@ -41,7 +41,7 @@ #include "ED_gizmo_library.h" /* own include */ #include "gizmo_library_intern.h" /* own include */ -/* TODO, this is to be used by RNA. might move to ED_gizmo_library */ +/* TODO: this is to be used by RNA. might move to ED_gizmo_library. */ /** * Given a single axis, orient the matrix to a different direction. diff --git a/source/blender/editors/gizmo_library/gizmo_library_utils.c b/source/blender/editors/gizmo_library/gizmo_library_utils.c index 77c65cd1bb8..7d0ae5afb9b 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_utils.c +++ b/source/blender/editors/gizmo_library/gizmo_library_utils.c @@ -237,7 +237,7 @@ bool gizmo_window_project_3d( if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) { View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); - /* Note: we might want a custom reference point passed in, + /* NOTE: we might want a custom reference point passed in, * instead of the gizmo center. */ ED_view3d_win_to_3d(v3d, region, mat[3], mval, r_co); invert_m4(mat); diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c index d99ce25451c..f286d3930e2 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c @@ -82,7 +82,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz, GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - /* TODO, other draw styles */ + /* TODO: other draw styles. */ if (color[3] == 1.0 && fill_alpha == 1.0 && select == false) { immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(color); diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c index deb89319f4f..6fd06b47656 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c @@ -774,7 +774,7 @@ static int gizmo_cage2d_get_cursor(wmGizmo *gz) case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y: return WM_CURSOR_Y_MOVE; - /* TODO diagonal cursor */ + /* TODO: diagonal cursor. */ case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y: case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y: return WM_CURSOR_NSEW_SCROLL; diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index 3131ec70fb0..196fb88ea55 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -348,7 +348,7 @@ static void annotation_draw_stroke_3d( /* If there was a significant pressure change, stop the curve, * change the thickness of the stroke, and continue drawing again * (since line-width cannot change in middle of GL_LINE_STRIP) - * Note: we want more visible levels of pressures when thickness is bigger. + * NOTE: we want more visible levels of pressures when thickness is bigger. */ if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) { /* if the pressure changes before get at least 2 vertices, @@ -901,7 +901,7 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d) } /* draw annotations sketches to specified 3d-view assuming that matrices are already set - * correctly Note: this gets called twice - first time with only3d=true to draw 3d-strokes, + * correctly NOTE: this gets called twice - first time with only3d=true to draw 3d-strokes, * second time with only3d=false for screen-aligned strokes */ void ED_annotation_draw_view3d( Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d) diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 7b995c545ba..4b0c5ccd285 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -708,7 +708,7 @@ static void annotation_stroke_arrow_init_conv_point(bGPDspoint *pt, const float static void annotation_stroke_arrow_init_point( tGPsdata *p, tGPspoint *ptc, bGPDspoint *pt, const float co[8], const int co_idx) { - /* Note: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */ + /* NOTE: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */ const float real_co[2] = {co[co_idx], co[co_idx + 1]}; copy_v2_v2(&ptc->x, real_co); annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); @@ -1141,7 +1141,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p, /* Clear Tags * - * Note: It's better this way, as we are sure that + * NOTE: It's better this way, as we are sure that * we don't miss anything, though things will be * slightly slower as a result */ @@ -1172,7 +1172,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { if ((annotation_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || @@ -2478,18 +2478,15 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve /* default exit state - pass through to support MMB view nav, etc. */ int estate = OPERATOR_PASS_THROUGH; - /* if (event->type == NDOF_MOTION) - * return OPERATOR_PASS_THROUGH; - * ------------------------------- - * [mce] Not quite what I was looking - * for, but a good start! GP continues to - * draw on the screen while the 3D mouse - * moves the viewpoint. Problem is that - * the stroke is converted to 3D only after - * it is finished. This approach should work - * better in tools that immediately apply - * in 3D space. - */ + /* NOTE(mike erwin): Not quite what I was looking for, but a good start! + * grease-pencil continues to draw on the screen while the 3D mouse moves the viewpoint. + * Problem is that the stroke is converted to 3D only after it is finished. + * This approach should work better in tools that immediately apply in 3D space. */ +#if 0 + if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } +#endif if (p->status == GP_STATUS_IDLING) { ARegion *region = CTX_wm_region(C); diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 6e6d94a2909..fbdb7c8e520 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -513,7 +513,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) static bool gpencil_frame_snap_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene)) { -#if 0 /* note: gpf->framenum is already an int! */ +#if 0 /* NOTE: gpf->framenum is already an int! */ if (gpf->flag & GP_FRAME_SELECT) { gpf->framenum = (int)(floor(gpf->framenum + 0.5)); } diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index d8734c4ae6b..8d60ef3ed12 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -39,6 +39,32 @@ #include "ED_gpencil.h" +/** + * Populate stroke with point data from data buffers. + * \param gps: Grease pencil stroke + * \param array: Flat array of point data values. Each entry has #GP_PRIM_DATABUF_SIZE values. + * \param totpoints: Total of points + * \param mat: 4x4 transform matrix to transform points into the right coordinate space. + */ +void ED_gpencil_stroke_init_data(bGPDstroke *gps, + const float *array, + const int totpoints, + const float mat[4][4]) +{ + for (int i = 0; i < totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + const int x = GP_PRIM_DATABUF_SIZE * i; + + pt->x = array[x]; + pt->y = array[x + 1]; + pt->z = array[x + 2]; + mul_m4_v3(mat, &pt->x); + + pt->pressure = array[x + 3]; + pt->strength = array[x + 4]; + } +} + /* Definition of the most important info from a color */ typedef struct ColorTemplate { const char *name; @@ -847,115 +873,115 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4]) /* generate strokes */ gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false); - BKE_gpencil_stroke_add_points(gps, data0, 270, mat); + ED_gpencil_stroke_init_data(gps, data0, 270, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data1, 33, mat); + ED_gpencil_stroke_init_data(gps, data1, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 60, false); - BKE_gpencil_stroke_add_points(gps, data2, 18, mat); + ED_gpencil_stroke_init_data(gps, data2, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false); - BKE_gpencil_stroke_add_points(gps, data3, 64, mat); + ED_gpencil_stroke_init_data(gps, data3, 64, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data4, 33, mat); + ED_gpencil_stroke_init_data(gps, data4, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false); - BKE_gpencil_stroke_add_points(gps, data5, 64, mat); + ED_gpencil_stroke_init_data(gps, data5, 64, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data6, 33, mat); + ED_gpencil_stroke_init_data(gps, data6, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data7, 18, mat); + ED_gpencil_stroke_init_data(gps, data7, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false); - BKE_gpencil_stroke_add_points(gps, data8, 49, mat); + ED_gpencil_stroke_init_data(gps, data8, 49, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data9, 33, mat); + ED_gpencil_stroke_init_data(gps, data9, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false); - BKE_gpencil_stroke_add_points(gps, data10, 49, mat); + ED_gpencil_stroke_init_data(gps, data10, 49, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data11, 18, mat); + ED_gpencil_stroke_init_data(gps, data11, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data12, 18, mat); + ED_gpencil_stroke_init_data(gps, data12, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data13, 33, mat); + ED_gpencil_stroke_init_data(gps, data13, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data14, 33, mat); + ED_gpencil_stroke_init_data(gps, data14, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 65, 60, false); - BKE_gpencil_stroke_add_points(gps, data15, 65, mat); + ED_gpencil_stroke_init_data(gps, data15, 65, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 60, false); - BKE_gpencil_stroke_add_points(gps, data16, 34, mat); + ED_gpencil_stroke_init_data(gps, data16, 34, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data17, 33, mat); + ED_gpencil_stroke_init_data(gps, data17, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 40, false); - BKE_gpencil_stroke_add_points(gps, data18, 33, mat); + ED_gpencil_stroke_init_data(gps, data18, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 40, false); - BKE_gpencil_stroke_add_points(gps, data19, 34, mat); + ED_gpencil_stroke_init_data(gps, data19, 34, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data20, 33, mat); + ED_gpencil_stroke_init_data(gps, data20, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 64, 60, false); - BKE_gpencil_stroke_add_points(gps, data21, 64, mat); + ED_gpencil_stroke_init_data(gps, data21, 64, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false); - BKE_gpencil_stroke_add_points(gps, data22, 26, mat); + ED_gpencil_stroke_init_data(gps, data22, 26, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false); - BKE_gpencil_stroke_add_points(gps, data23, 26, mat); + ED_gpencil_stroke_init_data(gps, data23, 26, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data24, 33, mat); + ED_gpencil_stroke_init_data(gps, data24, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data25, 18, mat); + ED_gpencil_stroke_init_data(gps, data25, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false); - BKE_gpencil_stroke_add_points(gps, data26, 18, mat); + ED_gpencil_stroke_init_data(gps, data26, 18, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false); - BKE_gpencil_stroke_add_points(gps, data27, 33, mat); + ED_gpencil_stroke_init_data(gps, data27, 33, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); /* update depsgraph */ diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index e95496b51ee..73c4e64dd9a 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -235,7 +235,7 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]) /* generate stroke */ gps = BKE_gpencil_stroke_add(frame_lines, color_black, 175, 75, false); - BKE_gpencil_stroke_add_points(gps, data0, 175, mat); + ED_gpencil_stroke_init_data(gps, data0, 175, mat); BKE_gpencil_stroke_geometry_update(gpd, gps); /* update depsgraph */ diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index 24fb0873a86..c800851bb08 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -384,7 +384,7 @@ static void gpencil_add_verts_to_dgroups( /* loop groups and assign weight */ for (j = 0; j < numbones; j++) { - int def_nr = BLI_findindex(&ob->defbase, dgrouplist[j]); + int def_nr = BLI_findindex(&gpd->vertex_group_names, dgrouplist[j]); if (def_nr < 0) { continue; } @@ -454,7 +454,7 @@ static void gpencil_object_vgroup_calc_from_armature(const bContext *C, bArmature *arm = ob_arm->data; /* always create groups */ - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const int defbase_tot = BKE_object_defgroup_count(ob); int defbase_add; /* Traverse the bone list, trying to create empty vertex * groups corresponding to the bone. diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.c b/source/blender/editors/gpencil/gpencil_bake_animation.c index 1a5e2950e09..2d299230124 100644 --- a/source/blender/editors/gpencil/gpencil_bake_animation.c +++ b/source/blender/editors/gpencil/gpencil_bake_animation.c @@ -38,6 +38,7 @@ #include "BKE_duplilist.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" +#include "BKE_gpencil_modifier.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" @@ -303,8 +304,12 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op float matrix[4][4]; BKE_gpencil_layer_transform_matrix_get(depsgraph, elem->ob, gpl_src, matrix); + /* Apply time modifier. */ + int remap_cfra = BKE_gpencil_time_modifier_cfra( + depsgraph, scene, elem->ob, gpl_src, CFRA, false); /* Duplicate frame. */ - bGPDframe *gpf_src = BKE_gpencil_layer_frame_get(gpl_src, CFRA, GP_GETFRAME_USE_PREV); + bGPDframe *gpf_src = BKE_gpencil_layer_frame_get( + gpl_src, remap_cfra, GP_GETFRAME_USE_PREV); if (gpf_src == NULL) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 9bea1868895..ee3536c2f3f 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -230,7 +230,7 @@ typedef struct tGpTimingData { float tot_dist; /* Times */ - float *times; /* Note: Gap times will be negative! */ + float *times; /* NOTE: Gap times will be negative! */ float tot_time, gap_tot_time; double inittime; @@ -1409,7 +1409,7 @@ static void gpencil_layer_to_curve(bContext *C, gtd); break; default: - BLI_assert(!"invalid mode"); + BLI_assert_msg(0, "invalid mode"); break; } prev_gps = gps; @@ -1806,7 +1806,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot) 0, 100); - /* Note: Internal use, this one will always be hidden by UI code... */ + /* NOTE: Internal use, this one will always be hidden by UI code... */ prop = RNA_def_boolean( ot->srna, "use_timing_data", diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index e272f46d13d..b1e57079d28 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -2165,7 +2165,9 @@ static bool gpencil_vertex_group_poll(bContext *C) Object *ob = CTX_data_active_object(C); if ((ob) && (ob->type == OB_GPENCIL)) { - if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) { + const bGPdata *gpd = (const bGPdata *)ob->data; + if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && + !BLI_listbase_is_empty(&gpd->vertex_group_names)) { if (ELEM(ob->mode, OB_MODE_EDIT_GPENCIL, OB_MODE_SCULPT_GPENCIL)) { return true; } @@ -2180,7 +2182,9 @@ static bool gpencil_vertex_group_weight_poll(bContext *C) Object *ob = CTX_data_active_object(C); if ((ob) && (ob->type == OB_GPENCIL)) { - if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) { + const bGPdata *gpd = (const bGPdata *)ob->data; + if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && + !BLI_listbase_is_empty(&gpd->vertex_group_names)) { if (ob->mode == OB_MODE_WEIGHT_GPENCIL) { return true; } @@ -2333,6 +2337,7 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { @@ -2340,8 +2345,9 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op) } MDeformVert *dvert; - const int def_nr = ob->actdef - 1; - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + + bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr); if (defgroup == NULL) { return OPERATOR_CANCELLED; } @@ -2373,7 +2379,6 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2403,14 +2408,15 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { return OPERATOR_CANCELLED; } - const int def_nr = ob->actdef - 1; - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr); if (defgroup == NULL) { return OPERATOR_CANCELLED; } @@ -2470,7 +2476,6 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2500,6 +2505,7 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { @@ -2508,8 +2514,8 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op) MDeformVert *dvert = NULL; MDeformWeight *dw = NULL; - const int def_nr = ob->actdef - 1; - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr); if (defgroup == NULL) { return OPERATOR_CANCELLED; } @@ -2548,7 +2554,6 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2576,6 +2581,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); bool lock_active = RNA_boolean_get(op->ptr, "lock_active"); + bGPdata *gpd = ob->data; /* sanity checks */ if (ELEM(NULL, ts, ob, ob->data)) { @@ -2585,8 +2591,8 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) bDeformGroup *defgroup = NULL; MDeformVert *dvert = NULL; MDeformWeight *dw = NULL; - const int def_nr = ob->actdef - 1; - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const int def_nr = gpd->vertex_group_active_index - 1; + const int defbase_tot = BLI_listbase_count(&gpd->vertex_group_names); if (defbase_tot == 0) { return OPERATOR_CANCELLED; } @@ -2603,7 +2609,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) for (int i = 0; i < gps->totpoints; i++) { dvert = &gps->dvert[i]; for (int v = 0; v < defbase_tot; v++) { - defgroup = BLI_findlink(&ob->defbase, v); + defgroup = BLI_findlink(&gpd->vertex_group_names, v); /* skip NULL or locked groups */ if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) { continue; @@ -2629,7 +2635,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) dvert = &gps->dvert[i]; for (int v = 0; v < defbase_tot; v++) { - defgroup = BLI_findlink(&ob->defbase, v); + defgroup = BLI_findlink(&gpd->vertex_group_names, v); /* skip NULL or locked groups */ if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) { continue; @@ -2653,7 +2659,6 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* notifiers */ - bGPdata *gpd = ob->data; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); @@ -2769,7 +2774,6 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *ob_active = CTX_data_active_object(C); - bGPdata *gpd_dst = NULL; bool ok = false; /* Ensure we're in right mode and that the active object is correct */ @@ -2807,7 +2811,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - gpd_dst = ob_active->data; + bGPdata *gpd_dst = ob_active->data; Object *ob_dst = ob_active; /* loop and join all data */ @@ -2828,11 +2832,11 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) /* copy vertex groups to the base one's */ int old_idx = 0; - LISTBASE_FOREACH (bDeformGroup *, dg, &ob_iter->defbase) { + LISTBASE_FOREACH (bDeformGroup *, dg, &gpd_src->vertex_group_names) { bDeformGroup *vgroup = MEM_dupallocN(dg); - int idx = BLI_listbase_count(&ob_active->defbase); + int idx = BLI_listbase_count(&gpd_dst->vertex_group_names); BKE_object_defgroup_unique_name(vgroup, ob_active); - BLI_addtail(&ob_active->defbase, vgroup); + BLI_addtail(&gpd_dst->vertex_group_names, vgroup); /* update vertex groups in strokes in original data */ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) { LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) { @@ -2852,8 +2856,9 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) } old_idx++; } - if (ob_active->defbase.first && ob_active->actdef == 0) { - ob_active->actdef = 1; + if (!BLI_listbase_is_empty(&gpd_dst->vertex_group_names) && + gpd_dst->vertex_group_active_index == 0) { + gpd_dst->vertex_group_active_index = 1; } /* add missing materials reading source materials and checking in destination object */ diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 4419833a99c..67e1bd5294b 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1522,8 +1522,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) pt = gps->points; point2D = (tGPspoint *)tgpf->sbuffer; - const int def_nr = tgpf->ob->actdef - 1; - const bool have_weight = (bool)BLI_findlink(&tgpf->ob->defbase, def_nr); + const int def_nr = tgpf->gpd->vertex_group_active_index - 1; + const bool have_weight = (bool)BLI_findlink(&tgpf->gpd->vertex_group_names, def_nr); if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) { BKE_gpencil_dvert_ensure(gps); @@ -1625,7 +1625,7 @@ static void gpencil_draw_boundary_lines(const bContext *UNUSED(C), tGPDfill *tgp static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), void *arg) { tGPDfill *tgpf = (tGPDfill *)arg; - /* draw only in the region that originated operator. This is required for multiwindow */ + /* Draw only in the region that originated operator. This is required for multi-window. */ ARegion *region = CTX_wm_region(C); if (region != tgpf->region) { return; diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 0062e363cdf..8640ffa67cf 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -278,7 +278,7 @@ static void gpencil_stroke_pair_table(bContext *C, tGPDinterpolate_layer *tgpil) { bGPdata *gpd = tgpi->gpd; - const bool only_selected = ((GPENCIL_EDIT_MODE(gpd)) && + const bool only_selected = (GPENCIL_EDIT_MODE(gpd) && ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) != 0)); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); @@ -291,8 +291,7 @@ static void gpencil_stroke_pair_table(bContext *C, LISTBASE_FOREACH (bGPDstroke *, gps_from, &tgpil->prevFrame->strokes) { bGPDstroke *gps_to = NULL; /* only selected */ - if ((GPENCIL_EDIT_MODE(gpd)) && (only_selected) && - ((gps_from->flag & GP_STROKE_SELECT) == 0)) { + if (GPENCIL_EDIT_MODE(gpd) && (only_selected) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } /* skip strokes that are invalid for current view */ @@ -712,7 +711,7 @@ static bool gpencil_interpolate_set_init_values(bContext *C, wmOperator *op, tGP tgpi->flag, (RNA_enum_get(op->ptr, "layers") == 1), GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS); SET_FLAG_FROM_TEST( tgpi->flag, - ((GPENCIL_EDIT_MODE(tgpi->gpd)) && (RNA_boolean_get(op->ptr, "interpolate_selected_only"))), + (GPENCIL_EDIT_MODE(tgpi->gpd) && (RNA_boolean_get(op->ptr, "interpolate_selected_only"))), GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED); tgpi->flipmode = RNA_enum_get(op->ptr, "flip"); @@ -1249,7 +1248,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) const int step = RNA_int_get(op->ptr, "step"); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); const bool all_layers = (bool)(RNA_enum_get(op->ptr, "layers") == 1); - const bool only_selected = ((GPENCIL_EDIT_MODE(gpd)) && + const bool only_selected = (GPENCIL_EDIT_MODE(gpd) && (RNA_boolean_get(op->ptr, "interpolate_selected_only") != 0)); eGP_InterpolateFlipMode flipmode = RNA_enum_get(op->ptr, "flip"); @@ -1309,7 +1308,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (bGPDstroke *, gps_from, &prevFrame->strokes) { bGPDstroke *gps_to = NULL; /* Only selected. */ - if ((GPENCIL_EDIT_MODE(gpd)) && (only_selected) && + if (GPENCIL_EDIT_MODE(gpd) && (only_selected) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 409d10996d0..d6f6dbb2b10 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -938,8 +938,8 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) Depsgraph *depsgraph = p->depsgraph; Object *obact = (Object *)p->ownerPtr.data; RegionView3D *rv3d = p->region->regiondata; - const int def_nr = obact->actdef - 1; - const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr); + const int def_nr = gpd->vertex_group_active_index - 1; + const bool have_weight = (bool)BLI_findlink(&gpd->vertex_group_names, def_nr); const char align_flag = ts->gpencil_v3d_align; const bool is_depth = (bool)(align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)); const bool is_lock_axis_view = (bool)(ts->gp_sculpt.lock_axis == 0); @@ -1526,7 +1526,7 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, /* Clear Tags * - * Note: It's better this way, as we are sure that + * NOTE: It's better this way, as we are sure that * we don't miss anything, though things will be * slightly slower as a result */ @@ -1579,7 +1579,7 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { @@ -2174,7 +2174,7 @@ static void gpencil_paint_initstroke(tGPsdata *p, /* Add a new frame if needed (and based off the active frame, * as we need some existing strokes to erase) * - * Note: We don't add a new frame if there's nothing there now, so + * NOTE: We don't add a new frame if there's nothing there now, so * -> If there are no frames at all, don't add one * -> If there are no strokes in that frame, don't add a new empty frame */ @@ -3602,18 +3602,15 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* default exit state - pass through to support MMB view nav, etc. */ int estate = OPERATOR_PASS_THROUGH; - /* if (event->type == NDOF_MOTION) - * return OPERATOR_PASS_THROUGH; - * ------------------------------- - * [mce] Not quite what I was looking - * for, but a good start! GP continues to - * draw on the screen while the 3D mouse - * moves the viewpoint. Problem is that - * the stroke is converted to 3D only after - * it is finished. This approach should work - * better in tools that immediately apply - * in 3D space. - */ + /* NOTE(mike erwin): Not quite what I was looking for, but a good start! + * grease-pencil continues to draw on the screen while the 3D mouse moves the viewpoint. + * Problem is that the stroke is converted to 3D only after it is finished. + * This approach should work better in tools that immediately apply in 3D space. */ +#if 0 + if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } +#endif if (p->status == GP_STATUS_IDLING) { ARegion *region = CTX_wm_region(C); diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index a2b4e5dee64..cf49aefe2ea 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -1315,8 +1315,8 @@ static void gpencil_primitive_interaction_end(bContext *C, Brush *brush = tgpi->brush; BrushGpencilSettings *brush_settings = brush->gpencil_settings; - const int def_nr = tgpi->ob->actdef - 1; - const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr); + const int def_nr = tgpi->gpd->vertex_group_active_index - 1; + const bool have_weight = BLI_findlink(&tgpi->gpd->vertex_group_names, def_nr) != NULL; /* return to normal cursor and header status */ ED_workspace_status_text(C, NULL); diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 0226558b4a0..14caf0c08a7 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1096,7 +1096,7 @@ static void gpencil_brush_clone_adjust(tGP_BrushEditData *gso) } } -/* Entrypoint for applying "clone" brush */ +/* Entry-point for applying "clone" brush. */ static bool gpencil_sculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) { /* Which "mode" are we operating in? */ @@ -1177,8 +1177,8 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op) gso->object = ob; if (ob) { invert_m4_m4(gso->inv_mat, ob->obmat); - gso->vrgroup = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, gso->vrgroup)) { + gso->vrgroup = gso->gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup)) { gso->vrgroup = -1; } /* Check if some modifier can transform the stroke. */ @@ -1352,7 +1352,7 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso * - This is useful when animating as it saves that "uh-oh" moment when you realize you've * spent too much time editing the wrong frame. */ - if ((IS_AUTOKEY_ON(scene)) && (gpf->framenum != cfra)) { + if (IS_AUTOKEY_ON(scene) && (gpf->framenum != cfra)) { BKE_gpencil_frame_addcopy(gpl, cfra); /* Need tag to recalculate evaluated data to avoid crashes. */ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); @@ -1377,7 +1377,7 @@ static float gpencil_sculpt_rotation_eval_get(tGP_BrushEditData *gso, int idx_eval) { /* If multiframe or no modifiers, return 0. */ - if ((GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd)) || (!gso->is_transformed)) { + if (GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd) || (!gso->is_transformed)) { return 0.0f; } @@ -1500,7 +1500,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* Apply operation to these points */ @@ -1513,8 +1513,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, } pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* If masked and the point is not selected, skip it. */ - if ((GPENCIL_ANY_SCULPT_MASK(gso->mask)) && - ((pt_active->flag & GP_SPOINT_SELECT) == 0)) { + if (GPENCIL_ANY_SCULPT_MASK(gso->mask) && ((pt_active->flag & GP_SPOINT_SELECT) == 0)) { continue; } index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index c33b43247fd..69734fa1ba8 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -689,7 +689,7 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op) break; default: - BLI_assert(!"unhandled select grouped gpencil mode"); + BLI_assert_msg(0, "unhandled select grouped gpencil mode"); break; } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 54672743439..ba3d3b584d7 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1227,7 +1227,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, float xy[2]; /* 3D to Screen-space */ - /* Note: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space + /* NOTE: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space * coordinates, resulting in lost precision, which in turn causes stair-stepping * artifacts in the final points. */ @@ -1600,8 +1600,8 @@ void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } @@ -1654,8 +1654,8 @@ void ED_gpencil_vgroup_remove(bContext *C, Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } @@ -1707,8 +1707,8 @@ void ED_gpencil_vgroup_select(bContext *C, Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } @@ -1762,8 +1762,8 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const int def_nr = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) { return; } diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 7ec64b2afd6..633e371cbd1 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -910,7 +910,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { @@ -919,7 +919,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, pt_active = pt->runtime.pt_orig; if (pt_active != NULL) { /* If masked and the point is not selected, skip it. */ - if ((GPENCIL_ANY_VERTEX_MASK(gso->mask)) && + if (GPENCIL_ANY_VERTEX_MASK(gso->mask) && ((pt_active->flag & GP_SPOINT_SELECT) == 0)) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 56eed187d87..d14322e12b5 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -252,7 +252,7 @@ static bool brush_draw_apply(tGP_BrushWeightpaintData *gso, } } else { - bDeformGroup *defgroup = BLI_findlink(&gso->object->defbase, gso->vrgroup); + bDeformGroup *defgroup = BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup); if (defgroup->flag & DG_LOCK_WEIGHT) { return false; } @@ -308,8 +308,8 @@ static bool gpencil_weightpaint_brush_init(bContext *C, wmOperator *op) gso->scene = scene; gso->object = ob; if (ob) { - gso->vrgroup = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, gso->vrgroup)) { + gso->vrgroup = gso->gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup)) { gso->vrgroup = -1; } } @@ -448,7 +448,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) { /* Check if point segment of stroke had anything to do with * brush region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant + * - this assumes that line-width is irrelevant. */ if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4b440aa7367..50e53acb376 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -34,9 +34,9 @@ struct ListBase; struct ARegion; struct ARegionType; +struct FModifier; struct Main; struct NlaStrip; -struct FModifier; struct PanelType; struct ReportList; struct ScrArea; @@ -177,9 +177,9 @@ typedef struct bAnimListElem { * action's ID. But if this is a f-curve which is a driver, then the owner * is set to, for example, object. * - * Note, that this is different from id above. The id above will be set to - * an object if the f-curve is coming from action associated with that - * object. */ + * NOTE: this is different from id above. The id above will be set to + * an object if the f-curve is coming from action associated with that object. + */ struct ID *fcurve_owner_id; /** diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 85563b76f38..868235c36e5 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -23,6 +23,10 @@ #pragma once +#include <stdbool.h> + +#include "BLI_listbase.h" + #ifdef __cplusplus extern "C" { #endif @@ -41,6 +45,7 @@ struct Scene; struct UndoType; struct View3D; struct ViewLayer; +struct bAction; struct bArmature; struct bContext; struct bPoseChannel; @@ -242,6 +247,17 @@ void ED_mesh_deform_bind_callback(struct MeshDeformModifierData *mmd, int totvert, float cagemat[4][4]); +/* Pose backups, pose_backup.c */ +struct PoseBackup; +/* Create a backup of those bones that are animated in the given action. */ +struct PoseBackup *ED_pose_backup_create_selected_bones( + const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT; +struct PoseBackup *ED_pose_backup_create_all_bones( + const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT; +bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup); +void ED_pose_backup_restore(const struct PoseBackup *pbd); +void ED_pose_backup_free(struct PoseBackup *pbd); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h index dd505167fe5..0058c0615c3 100644 --- a/source/blender/editors/include/ED_asset.h +++ b/source/blender/editors/include/ED_asset.h @@ -20,17 +20,80 @@ #pragma once +#include "DNA_ID_enums.h" + #ifdef __cplusplus extern "C" { #endif +struct AssetFilterSettings; +struct AssetLibraryReference; +struct Main; +struct ReportList; +struct bContext; +struct wmNotifier; + +typedef struct AssetTempIDConsumer AssetTempIDConsumer; + bool ED_asset_mark_id(const struct bContext *C, struct ID *id); bool ED_asset_clear_id(struct ID *id); bool ED_asset_can_make_single_from_context(const struct bContext *C); +int ED_asset_library_reference_to_enum_value(const struct AssetLibraryReference *library); +struct AssetLibraryReference ED_asset_library_reference_from_enum_value(int value); + +const char *ED_asset_handle_get_name(const AssetHandle *asset); +void ED_asset_handle_get_full_library_path(const struct bContext *C, + const AssetLibraryReference *asset_library, + const AssetHandle *asset, + char r_full_lib_path[]); + +AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle); +void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer); +struct ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer, + const struct bContext *C, + const AssetLibraryReference *asset_library, + ID_Type id_type, + struct Main *bmain, + struct ReportList *reports); + +void ED_assetlist_storage_fetch(const struct AssetLibraryReference *library_reference, + const struct AssetFilterSettings *filter_settings, + const struct bContext *C); +void ED_assetlist_ensure_previews_job(const struct AssetLibraryReference *library_reference, + struct bContext *C); +void ED_assetlist_clear(const struct AssetLibraryReference *library_reference, struct bContext *C); +bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *library_reference); +void ED_assetlist_storage_tag_main_data_dirty(void); +void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new); +void ED_assetlist_storage_exit(void); + +ID *ED_assetlist_asset_local_id_get(const AssetHandle *asset_handle); +struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle); +const char *ED_assetlist_library_path(const struct AssetLibraryReference *library_reference); + +bool ED_assetlist_listen(const struct AssetLibraryReference *library_reference, + const struct wmNotifier *notifier); +int ED_assetlist_size(const struct AssetLibraryReference *library_reference); + void ED_operatortypes_asset(void); #ifdef __cplusplus } #endif + +/* TODO move to C++ asset-list header? */ +#ifdef __cplusplus + +# include <string> + +std::string ED_assetlist_asset_filepath_get(const bContext *C, + const AssetLibraryReference &library_reference, + const AssetHandle &asset_handle); + +# include "BLI_function_ref.hh" +/* Can return false to stop iterating. */ +using AssetListIterFn = blender::FunctionRef<bool(FileDirEntry &)>; +void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn); +#endif diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 8118e3c6c69..e57e2316d93 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -66,7 +66,7 @@ typedef struct FileAttributeColumn { } FileAttributeColumn; typedef struct FileLayout { - /* view settings - XXX - move into own struct */ + /* view settings - XXX: move into own struct. */ int offset_top; /* Height of the header for the different FileAttributeColumn's. */ int attribute_column_header_h; @@ -136,13 +136,9 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y); void ED_operatormacros_file(void); -void ED_fileselect_clear(struct wmWindowManager *wm, - struct Scene *owner_scene, - struct SpaceFile *sfile); +void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile); -void ED_fileselect_exit(struct wmWindowManager *wm, - struct Scene *owner_scene, - struct SpaceFile *sfile); +void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile); bool ED_fileselect_is_asset_browser(const struct SpaceFile *sfile); struct ID *ED_fileselect_active_asset_get(const struct SpaceFile *sfile); @@ -166,7 +162,7 @@ int ED_file_icon(const struct FileDirEntry *file); void ED_file_read_bookmarks(void); -void ED_file_change_dir_ex(struct bContext *C, struct bScreen *screen, struct ScrArea *area); +void ED_file_change_dir_ex(struct bContext *C, struct ScrArea *area); void ED_file_change_dir(struct bContext *C); void ED_file_path_button(struct bScreen *screen, diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 59b5a1abaa6..8a8d91a570c 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -251,6 +251,13 @@ void ED_gpencil_brush_draw_eraser(struct Brush *brush, int x, int y); /* ----------- Add Primitive Utilities -------------- */ +/* Number of values defining each point in the built-in data buffers for primitives. */ +#define GP_PRIM_DATABUF_SIZE 5 +void ED_gpencil_stroke_init_data(struct bGPDstroke *gps, + const float *array, + const int totpoints, + const float mat[4][4]); + void ED_gpencil_create_blank(struct bContext *C, struct Object *ob, float mat[4][4]); void ED_gpencil_create_monkey(struct bContext *C, struct Object *ob, float mat[4][4]); void ED_gpencil_create_stroke(struct bContext *C, struct Object *ob, float mat[4][4]); diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 0493832c06f..673f629d6ef 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -468,7 +468,7 @@ bool fcurve_is_changed(struct PointerRNA ptr, * Checks whether a keyframe exists for the given ID-block one the given frame. * - It is recommended to call this method over the other keyframe-checkers directly, * in case some detail of the implementation changes... - * - frame: the value of this is quite often result of #BKE_scene_frame_get() + * - frame: the value of this is quite often result of #BKE_scene_ctime_get() */ bool id_frame_has_keyframe(struct ID *id, float frame, short filter); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 7fcae2349db..2b73194afb2 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -27,6 +27,8 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct ARegion; struct BMBVHTree; struct BMEdge; @@ -84,7 +86,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); -void EDBM_mesh_free(struct BMEditMesh *em); +void EDBM_mesh_free_data(struct BMEditMesh *em); void EDBM_mesh_load_ex(struct Main *bmain, struct Object *ob, bool free_data); void EDBM_mesh_load(struct Main *bmain, struct Object *ob); @@ -455,12 +457,14 @@ typedef struct BMBackup { struct BMesh *bmcopy; } BMBackup; -/* save a copy of the bmesh for restoring later */ struct BMBackup EDBM_redo_state_store(struct BMEditMesh *em); /* restore a bmesh from backup */ -void EDBM_redo_state_restore(struct BMBackup, struct BMEditMesh *em, int recalctess); -/* delete the backup, optionally flushing it to an editmesh */ -void EDBM_redo_state_free(struct BMBackup *, struct BMEditMesh *em, int recalctess); +void EDBM_redo_state_restore(struct BMBackup *backup, struct BMEditMesh *em, bool recalc_looptri) + ATTR_NONNULL(1, 2); +void EDBM_redo_state_restore_and_free(struct BMBackup *backup, + struct BMEditMesh *em, + bool recalc_looptri) ATTR_NONNULL(1, 2); +void EDBM_redo_state_free(struct BMBackup *backup) ATTR_NONNULL(1); /* *** meshtools.c *** */ int ED_mesh_join_objects_exec(struct bContext *C, struct wmOperator *op); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 9d36a2c7fc1..66e08ed1cb7 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -31,6 +31,7 @@ struct ID; struct Main; struct Scene; struct ScrArea; +struct SpaceNode; struct Tex; struct View2D; struct bContext; @@ -115,6 +116,7 @@ bool ED_node_select_check(const ListBase *lb); void ED_node_select_all(ListBase *lb, int action); void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree); void ED_node_set_active(struct Main *bmain, + struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bool *r_active_texture_changed); diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index 6d0172e724a..5318c653b6d 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -34,9 +34,9 @@ struct ParticleSystem; struct Scene; struct UndoType; struct ViewLayer; -struct wmGenericUserData; struct bContext; struct rcti; +struct wmGenericUserData; /* particle edit mode */ void PE_free_ptcache_edit(struct PTCacheEdit *edit); diff --git a/source/blender/editors/include/ED_spreadsheet.h b/source/blender/editors/include/ED_spreadsheet.h index 88bc4738c0b..dfa8aa7bfbc 100644 --- a/source/blender/editors/include/ED_spreadsheet.h +++ b/source/blender/editors/include/ED_spreadsheet.h @@ -16,10 +16,13 @@ #pragma once -struct SpreadsheetContext; -struct SpaceSpreadsheet; -struct SpaceNode; struct ID; +struct Main; +struct Object; +struct SpaceNode; +struct SpaceSpreadsheet; +struct SpreadsheetContext; +struct bContext; struct bNode; #ifdef __cplusplus @@ -29,14 +32,25 @@ extern "C" { struct SpreadsheetContext *ED_spreadsheet_context_new(int type); void ED_spreadsheet_context_free(struct SpreadsheetContext *context); void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet); -void ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet); +bool ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet); uint64_t ED_spreadsheet_context_path_hash(const struct SpaceSpreadsheet *sspreadsheet); struct ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet); -void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet, - struct SpaceNode *snode, - struct bNode *node); +void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet, + struct SpaceNode *snode, + struct bNode *node); +void ED_spreadsheet_context_paths_set_geometry_node(struct Main *bmain, + struct SpaceNode *snode, + struct bNode *node); +void ED_spreadsheet_context_path_set_evaluated_object(struct SpaceSpreadsheet *sspreadsheet, + struct Object *object); + +void ED_spreadsheet_context_path_guess(const struct bContext *C, + struct SpaceSpreadsheet *sspreadsheet); +bool ED_spreadsheet_context_path_is_active(const struct bContext *C, + struct SpaceSpreadsheet *sspreadsheet); +bool ED_spreadsheet_context_path_exists(struct Main *bmain, struct SpaceSpreadsheet *sspreadsheet); #ifdef __cplusplus } diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 484e083c111..7ccdc49d291 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -21,7 +21,7 @@ * \ingroup editorui */ -/* Note: this is included multiple times with different #defines for DEF_ICON. */ +/* NOTE: this is included multiple times with different #defines for DEF_ICON. */ /* Auto define more specific types for places that do not need the distinction. */ #ifndef DEF_ICON_SCENE diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 47e3dc84503..a25aac5803c 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -25,6 +25,7 @@ #include "BLI_compiler_attrs.h" #include "BLI_sys_types.h" /* size_t */ +#include "BLI_utildefines.h" #include "UI_interface_icons.h" #ifdef __cplusplus @@ -34,6 +35,7 @@ extern "C" { /* Struct Declarations */ struct ARegion; +struct AssetFilterSettings; struct AutoComplete; struct EnumPropertyItem; struct FileSelectParams; @@ -58,6 +60,7 @@ struct bNodeTree; struct bScreen; struct rctf; struct rcti; +struct uiBlockInteraction_Handle; struct uiButSearch; struct uiFontStyle; struct uiList; @@ -129,12 +132,6 @@ enum { UI_DIR_ALL = UI_DIR_UP | UI_DIR_DOWN | UI_DIR_LEFT | UI_DIR_RIGHT, }; -#if 0 -/* uiBlock->autofill (not yet used) */ -# define UI_BLOCK_COLLUMNS 1 -# define UI_BLOCK_ROWS 2 -#endif - /** #uiBlock.flag (controls) */ enum { UI_BLOCK_LOOP = 1 << 0, @@ -251,7 +248,7 @@ enum { #define UI_PANEL_BOX_STYLE_MARGIN (U.widget_unit * 0.2f) /* but->drawflag - these flags should only affect how the button is drawn. */ -/* Note: currently, these flags _are not passed_ to the widget's state() or draw() functions +/* NOTE: currently, these flags *are not passed* to the widget's state() or draw() functions * (except for the 'align' ones)! */ enum { @@ -371,6 +368,9 @@ typedef enum { /** Buttons with value >= #UI_BTYPE_SEARCH_MENU don't get undo pushes. */ UI_BTYPE_SEARCH_MENU = 41 << 9, UI_BTYPE_EXTRA = 42 << 9, + /** A preview image (#PreviewImage), with text under it. Typically bigger than normal buttons and + * laid out in a grid, e.g. like the File Browser in thumbnail display mode. */ + UI_BTYPE_PREVIEW_TILE = 43 << 9, UI_BTYPE_HOTKEY_EVENT = 46 << 9, /** Non-interactive image, used for splash screen */ UI_BTYPE_IMAGE = 47 << 9, @@ -520,6 +520,54 @@ typedef int (*uiButPushedStateFunc)(struct uiBut *but, const void *arg); typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); +/* -------------------------------------------------------------------- */ +/** \name Custom Interaction + * + * Sometimes it's useful to create data that remains available + * while the user interacts with a button. + * + * A common case is dragging a number button or slider + * however this could be used in other cases too. + * \{ */ + +struct uiBlockInteraction_Params { + /** + * When true, this interaction is not modal + * (user clicking on a number button arrows or pasting a value for example). + */ + bool is_click; + /** + * Array of unique event ID's (values from #uiBut.retval). + * There may be more than one for multi-button editing (see #UI_BUT_DRAG_MULTI). + */ + int *unique_retval_ids; + uint unique_retval_ids_len; +}; + +/** Returns 'user_data', freed by #uiBlockInteractionEndFn. */ +typedef void *(*uiBlockInteractionBeginFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1); +typedef void (*uiBlockInteractionEndFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1, + void *user_data); +typedef void (*uiBlockInteractionUpdateFn)(struct bContext *C, + const struct uiBlockInteraction_Params *params, + void *arg1, + void *user_data); + +typedef struct uiBlockInteraction_CallbackData { + uiBlockInteractionBeginFn begin_fn; + uiBlockInteractionEndFn end_fn; + uiBlockInteractionUpdateFn update_fn; + void *arg1; +} uiBlockInteraction_CallbackData; + +void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks); + +/** \} */ + /* Menu Callbacks */ typedef void (*uiMenuCreateFunc)(struct bContext *C, struct uiLayout *layout, void *arg1); @@ -544,6 +592,8 @@ bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title); bool UI_block_is_empty(const uiBlock *block); bool UI_block_can_add_separator(const uiBlock *block); +struct uiList *UI_list_find_mouse_over(const struct ARegion *region, const struct wmEvent *event); + /* interface_region_menu_popup.c */ /** * Popup Menus @@ -661,6 +711,7 @@ void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2], void UI_block_end(const struct bContext *C, uiBlock *block); void UI_block_draw(const struct bContext *C, struct uiBlock *block); void UI_blocklist_update_window_matrix(const struct bContext *C, const struct ListBase *lb); +void UI_blocklist_update_view_for_buttons(const struct bContext *C, const struct ListBase *lb); void UI_blocklist_draw(const struct bContext *C, const struct ListBase *lb); void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block); @@ -669,7 +720,7 @@ enum { UI_BLOCK_THEME_STYLE_POPUP = 1, }; void UI_block_theme_style_set(uiBlock *block, char theme_style); -char UI_block_emboss_get(uiBlock *block); +eUIEmbossType UI_block_emboss_get(uiBlock *block); void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss); bool UI_block_is_search_only(const uiBlock *block); void UI_block_set_search_only(uiBlock *block, bool search_only); @@ -684,7 +735,7 @@ void UI_block_region_set(uiBlock *block, struct ARegion *region); void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr); void UI_block_lock_clear(uiBlock *block); -/* automatic aligning, horiz or verical */ +/* Automatic aligning, horizontal or vertical. */ void UI_block_align_begin(uiBlock *block); void UI_block_align_end(uiBlock *block); @@ -1370,7 +1421,7 @@ typedef struct uiStringInfo { char *strinfo; } uiStringInfo; -/* Note: Expects pointers to uiStringInfo structs as parameters. +/* NOTE: Expects pointers to uiStringInfo structs as parameters. * Will fill them with translated strings, when possible. * Strings in uiStringInfo must be MEM_freeN'ed by caller. */ void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0); @@ -2151,6 +2202,17 @@ void uiTemplateCacheFile(uiLayout *layout, /* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */ #define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list" +enum uiTemplateListFlags { + UI_TEMPLATE_LIST_FLAG_NONE = 0, + UI_TEMPLATE_LIST_SORT_REVERSE = (1 << 0), + UI_TEMPLATE_LIST_SORT_LOCK = (1 << 1), + /* Don't allow resizing the list, i.e. don't add the grip button. */ + UI_TEMPLATE_LIST_NO_GRIP = (1 << 2), + + UI_TEMPLATE_LIST_FLAGS_LAST +}; +ENUM_OPERATORS(enum uiTemplateListFlags, UI_TEMPLATE_LIST_FLAGS_LAST); + void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, @@ -2164,8 +2226,23 @@ void uiTemplateList(uiLayout *layout, int maxrows, int layout_type, int columns, - bool sort_reverse, - bool sort_lock); + enum uiTemplateListFlags flags); +struct uiList *uiTemplateList_ex(uiLayout *layout, + struct bContext *C, + const char *listtype_name, + const char *list_id, + struct PointerRNA *dataptr, + const char *propname, + struct PointerRNA *active_dataptr, + const char *active_propname, + const char *item_dyntip_propname, + int rows, + int maxrows, + int layout_type, + int columns, + enum uiTemplateListFlags flags, + void *customdata); + void uiTemplateNodeLink(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, @@ -2211,6 +2288,27 @@ int uiTemplateRecentFiles(struct uiLayout *layout, int rows); void uiTemplateFileSelectPath(uiLayout *layout, struct bContext *C, struct FileSelectParams *params); +void uiTemplateAssetView(struct uiLayout *layout, + struct bContext *C, + const char *list_id, + struct PointerRNA *asset_library_dataptr, + const char *asset_library_propname, + struct PointerRNA *assets_dataptr, + const char *assets_propname, + struct PointerRNA *active_dataptr, + const char *active_propname, + const struct AssetFilterSettings *filter_settings, + const char *activate_opname, + struct PointerRNA *r_activate_op_properties, + const char *drag_opname, + struct PointerRNA *r_drag_op_properties); + +struct PointerRNA *UI_list_custom_activate_operator_set(struct uiList *ui_list, + const char *opname, + bool create_properties); +struct PointerRNA *UI_list_custom_drag_operator_set(struct uiList *ui_list, + const char *opname, + bool create_properties); /* items */ void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname); @@ -2475,6 +2573,7 @@ typedef struct uiDragColorHandle { void ED_operatortypes_ui(void); void ED_keymap_ui(struct wmKeyConfig *keyconf); +void ED_uilisttypes_ui(void); void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop); bool UI_drop_color_poll(struct bContext *C, @@ -2575,6 +2674,8 @@ bool UI_editsource_enable_check(void); void UI_editsource_active_but_test(uiBut *but); void UI_editsource_but_replace(const uiBut *old_but, uiBut *new_but); +void UI_but_ensure_in_view(const struct bContext *C, struct ARegion *region, const uiBut *but); + /* UI_butstore_ helpers */ typedef struct uiButStore uiButStore; typedef struct uiButStoreElem uiButStoreElem; diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 266a538b6c3..37cf7229ffb 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -105,7 +105,10 @@ int UI_iconfile_get_index(const char *filename); struct PreviewImage *UI_icon_to_preview(int icon_id); -int UI_icon_from_rnaptr(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big); +int UI_icon_from_rnaptr(const struct bContext *C, + struct PointerRNA *ptr, + int rnaicon, + const bool big); int UI_icon_from_idcode(const int idcode); int UI_icon_from_library(const struct ID *id); int UI_icon_from_object_mode(const int mode); diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 16729873b4e..8191a9a9062 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -51,7 +51,7 @@ enum eView2D_CommonViewTypes { V2D_COMMONVIEW_STANDARD, /* listview (i.e. Outliner) */ V2D_COMMONVIEW_LIST, - /* stackview (this is basically a list where new items are added at the top) */ + /* Stack-view (this is basically a list where new items are added at the top). */ V2D_COMMONVIEW_STACK, /* headers (this is basically the same as listview, but no y-panning) */ V2D_COMMONVIEW_HEADER, diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 5011a50ed73..39dd6143eb9 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -66,6 +66,8 @@ set(SRC interface_region_tooltip.c interface_regions.c interface_style.c + interface_template_asset_view.cc + interface_template_list.cc interface_template_search_menu.c interface_template_search_operator.c interface_templates.c @@ -102,7 +104,7 @@ if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() -if(WIN32) +if(WIN32 OR APPLE) if(WITH_INPUT_IME) add_definitions(-DWITH_INPUT_IME) endif() diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 6f341edf11b..ddde4f5a9dc 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -131,12 +131,10 @@ static bool ui_but_is_unit_radians(const uiBut *but) /* ************* window matrix ************** */ -void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y) +void ui_block_to_region_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y) { const int getsizex = BLI_rcti_size_x(®ion->winrct) + 1; const int getsizey = BLI_rcti_size_y(®ion->winrct) + 1; - const int sx = region->winrct.xmin; - const int sy = region->winrct.ymin; float gx = *r_x; float gy = *r_y; @@ -146,14 +144,19 @@ void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, fl gy += block->panel->ofsy; } - *r_x = ((float)sx) + - ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] + + *r_x = ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] + block->winmat[3][0])); - *r_y = ((float)sy) + - ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] + + *r_y = ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] + block->winmat[3][1])); } +void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y) +{ + ui_block_to_region_fl(region, block, r_x, r_y); + *r_x += region->winrct.xmin; + *r_y += region->winrct.ymin; +} + void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_y) { float fx = *r_x; @@ -165,6 +168,16 @@ void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_ *r_y = (int)(fy + 0.5f); } +void ui_block_to_region_rctf(const ARegion *region, + uiBlock *block, + rctf *rct_dst, + const rctf *rct_src) +{ + *rct_dst = *rct_src; + ui_block_to_region_fl(region, block, &rct_dst->xmin, &rct_dst->ymin); + ui_block_to_region_fl(region, block, &rct_dst->xmax, &rct_dst->ymax); +} + void ui_block_to_window_rctf(const ARegion *region, uiBlock *block, rctf *rct_dst, @@ -249,6 +262,14 @@ void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti rect_dst->ymax = rct_src->ymax - region->winrct.ymin; } +void ui_window_to_region_rctf(const ARegion *region, rctf *rect_dst, const rctf *rct_src) +{ + rect_dst->xmin = rct_src->xmin - region->winrct.xmin; + rect_dst->xmax = rct_src->xmax - region->winrct.xmin; + rect_dst->ymin = rct_src->ymin - region->winrct.ymin; + rect_dst->ymax = rct_src->ymax - region->winrct.ymin; +} + void ui_region_to_window(const ARegion *region, int *r_x, int *r_y) { *r_x += region->winrct.xmin; @@ -476,7 +497,7 @@ void ui_block_bounds_calc(uiBlock *block) static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block) { - /* note: this is used for the splash where window bounds event has not been + /* NOTE: this is used for the splash where window bounds event has not been * updated by ghost, get the window bounds from ghost directly */ const int xmax = WM_window_pixels_x(window); @@ -587,7 +608,7 @@ void UI_block_bounds_set_normal(uiBlock *block, int addval) block->bounds_type = UI_BLOCK_BOUNDS; } -/* used for pulldowns */ +/* Used for pull-downs. */ void UI_block_bounds_set_text(uiBlock *block, int addval) { block->bounds = addval; @@ -862,7 +883,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but) SWAP(void *, but->dragpoin, oldbut->dragpoin); } - /* note: if layout hasn't been applied yet, it uses old button pointers... */ + /* NOTE: if layout hasn't been applied yet, it uses old button pointers... */ } /** @@ -1382,11 +1403,11 @@ static bool ui_but_event_property_operator_string(const bContext *C, else { /* special exceptions for common nested data in editors... */ if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) { - /* dopesheet filtering options... */ + /* Dope-sheet filtering options. */ data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop)); } else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) { - /* Filebrowser options... */ + /* File-browser options. */ data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop)); } } @@ -1945,8 +1966,8 @@ void ui_fontscale(short *points, float aspect) if (aspect < 0.9f || aspect > 1.1f) { float pointsf = *points; - /* for some reason scaling fonts goes too fast compared to widget size */ - /* XXX not true anymore? (ton) */ + /* For some reason scaling fonts goes too fast compared to widget size. */ + /* XXX(ton): not true anymore? */ // aspect = sqrt(aspect); pointsf /= aspect; @@ -2432,7 +2453,7 @@ bool ui_but_is_rna_valid(uiBut *but) */ bool ui_but_supports_cycling(const uiBut *but) { - return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) || + return (ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX) || (but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) || (but->type == UI_BTYPE_COLOR && ((uiButColor *)but)->is_pallete_color) || (but->menu_step_func != NULL)); @@ -3140,7 +3161,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) return true; } else if (str[0] == '#') { - /* shortcut to create new driver expression (versus immediate Py-execution) */ + /* Shortcut to create new driver expression (versus immediate Python-execution). */ return ui_but_anim_expression_create(but, str + 1); } else { @@ -3223,7 +3244,7 @@ void ui_but_range_set_hard(uiBut *but) } } -/* note: this could be split up into functions which handle arrays and not */ +/* NOTE: this could be split up into functions which handle arrays and not. */ void ui_but_range_set_soft(uiBut *but) { /* Ideally we would not limit this, but practically it's more than @@ -3440,6 +3461,15 @@ void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb) } } +void UI_blocklist_update_view_for_buttons(const bContext *C, const ListBase *lb) +{ + LISTBASE_FOREACH (uiBlock *, block, lb) { + if (block->active) { + ui_but_update_view_for_active(C, block); + } + } +} + void UI_blocklist_draw(const bContext *C, const ListBase *lb) { LISTBASE_FOREACH (uiBlock *, block, lb) { @@ -3542,7 +3572,7 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eU return block; } -char UI_block_emboss_get(uiBlock *block) +eUIEmbossType UI_block_emboss_get(uiBlock *block) { return block->emboss; } @@ -4106,7 +4136,6 @@ static uiBut *ui_def_but(uiBlock *block, UI_BTYPE_BLOCK, UI_BTYPE_BUT_MENU, UI_BTYPE_SEARCH_MENU, - UI_BTYPE_PROGRESS_BAR, UI_BTYPE_DATASETROW, UI_BTYPE_POPOVER)) { but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT); @@ -4247,7 +4276,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu uiItemS(layout); } - /* note, item_array[...] is reversed on access */ + /* NOTE: `item_array[...]` is reversed on access. */ /* create items */ uiLayout *split = uiLayoutSplit(layout, 0.0f, false); @@ -4550,7 +4579,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, else if (proptype == PROP_STRING) { min = 0; max = RNA_property_string_maxlength(prop); - /* note, 'max' may be zero (code for dynamically resized array) */ + /* NOTE: 'max' may be zero (code for dynamically resized array). */ } } @@ -6757,7 +6786,7 @@ static void operator_enum_search_update_fn(const struct bContext *C, for (int i = 0; i < filtered_amount; i++) { const EnumPropertyItem *item = filtered_items[i]; - /* note: need to give the index rather than the + /* NOTE: need to give the index rather than the * identifier because the enum can be freed */ if (!UI_search_item_add( items, item->name, POINTER_FROM_INT(item->value), item->icon, 0, 0)) { diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 775e3923edc..3049e2bd7b8 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -417,7 +417,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) &um->items, drawstr, but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext); } else if (but->rnaprop) { - /* Note: 'member_id' may be a path. */ + /* NOTE: 'member_id' may be a path. */ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin); const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin); const char *member_id_data_path = member_id; @@ -425,7 +425,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path); } const char *prop_id = RNA_property_identifier(but->rnaprop); - /* Note, ignore 'drawstr', use property idname always. */ + /* NOTE: ignore 'drawstr', use property idname always. */ ED_screen_user_menu_item_add_prop(&um->items, "", member_id_data_path, prop_id, but->rnaindex); if (data_path) { MEM_freeN((void *)data_path); @@ -494,7 +494,7 @@ static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, Pr RNA_string_set(&props_ptr, "filepath", dir); } -bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) +bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *event) { /* ui_but_is_interactive() may let some buttons through that should not get a context menu - it * doesn't make sense for them. */ @@ -560,7 +560,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; /* Set the (button_pointer, button_prop) - * and pointer data for Python access to the hovered ui element. */ + * and pointer data for Python access to the hovered UI element. */ uiLayoutSetContextFromBut(layout, but); /* Keyframes */ @@ -1226,6 +1226,20 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } } + /* UI List item context menu. Scripts can add items to it, by default there's nothing shown. */ + ARegion *region = CTX_wm_region(C); + const bool is_inside_listbox = ui_list_find_mouse_over(region, event) != NULL; + const bool is_inside_listrow = is_inside_listbox ? + ui_list_row_find_mouse_over(region, event->x, event->y) != + NULL : + false; + if (is_inside_listrow) { + MenuType *mt = WM_menutype_find("UI_MT_list_item_context_menu", true); + if (mt) { + UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); + } + } + MenuType *mt = WM_menutype_find("WM_MT_button_context", true); if (mt) { UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 05b6fcdded1..655fdda3069 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -229,7 +229,7 @@ void ui_draw_but_TAB_outline(const rcti *rect, {0.98, 0.805}, }; - /* mult */ + /* Multiply. */ for (a = 0; a < 4; a++) { mul_v2_fl(vec[a], rad); } @@ -592,7 +592,7 @@ static void waveform_draw_one(float *waveform, int nbr, const float col[3]) GPU_vertbuf_attr_fill(vbo, pos_id, waveform); - /* TODO store the GPUBatch inside the scope */ + /* TODO: store the #GPUBatch inside the scope. */ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f); @@ -2223,9 +2223,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), /* ****************************************************** */ -/* TODO: high quality UI drop shadows using GLSL shader and single draw call - * would replace / modify the following 3 functions - merwin - */ +/* TODO(merwin): high quality UI drop shadows using GLSL shader and single draw call + * would replace / modify the following 3 functions. */ static void ui_shadowbox(const rctf *rect, uint pos, uint color, float shadsize, uchar alpha) { @@ -2350,7 +2349,7 @@ void ui_draw_dropshadow( true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color); #endif /* Compute final visibility to match old method result. */ - /* TODO we could just find a better fit function inside the shader instead of this. */ + /* TODO: we could just find a better fit function inside the shader instead of this. */ visibility = visibility * (1.0f - calpha); calpha += dalpha; } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 45609d96840..4f8bb6342f7 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -35,10 +35,12 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BLI_array_utils.h" #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_sort_utils.h" #include "BLI_string.h" #include "BLI_string_cursor_utf8.h" #include "BLI_string_utf8.h" @@ -170,6 +172,20 @@ static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str); static void button_tooltip_timer_reset(bContext *C, uiBut *but); +static void ui_block_interaction_begin_ensure(bContext *C, + uiBlock *block, + struct uiHandleButtonData *data, + const bool is_click); +static struct uiBlockInteraction_Handle *ui_block_interaction_begin(struct bContext *C, + uiBlock *block, + const bool is_click); +static void ui_block_interaction_end(struct bContext *C, + uiBlockInteraction_CallbackData *callbacks, + struct uiBlockInteraction_Handle *interaction); +static void ui_block_interaction_update(struct bContext *C, + uiBlockInteraction_CallbackData *callbacks, + struct uiBlockInteraction_Handle *interaction); + #ifdef USE_KEYNAV_LIMIT static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event); static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEvent *event); @@ -225,6 +241,19 @@ typedef enum uiMenuScrollType { MENU_SCROLL_BOTTOM, } uiMenuScrollType; +typedef struct uiBlockInteraction_Handle { + struct uiBlockInteraction_Params params; + void *user_data; + /** + * This is shared between #uiHandleButtonData and #uiAfterFunc, + * the last user runs the end callback and frees the data. + * + * This is needed as the order of freeing changes depending on + * accepting/canceling the operation. + */ + int user_count; +} uiBlockInteraction_Handle; + #ifdef USE_ALLSELECT /* Unfortunately there's no good way handle more generally: @@ -273,7 +302,7 @@ static void ui_selectcontext_apply(bContext *C, /** * how far to drag before we check for gesture direction (in pixels), - * note: half the height of a button is about right... */ + * NOTE: half the height of a button is about right... */ # define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4) /** @@ -430,6 +459,8 @@ typedef struct uiHandleButtonData { uiSelectContextStore select_others; #endif + struct uiBlockInteraction_Handle *custom_interaction_handle; + /* Text field undo. */ struct uiUndoStack_Text *undo_stack_text; @@ -471,6 +502,9 @@ typedef struct uiAfterFunc { void *search_arg; uiFreeArgFunc search_arg_free_fn; + uiBlockInteraction_CallbackData custom_interaction_callbacks; + uiBlockInteraction_Handle *custom_interaction_handle; + bContextStore *context; char undostr[BKE_UNDO_STR_MAX]; @@ -733,23 +767,34 @@ static uiAfterFunc *ui_afterfunc_new(void) * For executing operators after the button is pressed. * (some non operator buttons need to trigger operators), see: T37795. * + * \param context_but: A button from which to get the context from (`uiBut.context`) for the + * operator execution. + * + * \note Ownership over \a properties is moved here. The #uiAfterFunc owns it now. * \note Can only call while handling buttons. */ -PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext, bool create_props) +static void ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot, + PointerRNA **properties, + int opcontext, + const uiBut *context_but) { - PointerRNA *ptr = NULL; uiAfterFunc *after = ui_afterfunc_new(); after->optype = ot; after->opcontext = opcontext; + if (properties) { + after->opptr = *properties; + *properties = NULL; + } - if (create_props) { - ptr = MEM_callocN(sizeof(PointerRNA), __func__); - WM_operator_properties_create_ptr(ptr, ot); - after->opptr = ptr; + if (context_but && context_but->context) { + after->context = CTX_store_copy(context_but->context); } +} - return ptr; +void ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext) +{ + ui_handle_afterfunc_add_operator_ex(ot, NULL, opcontext, NULL); } static void popup_check(bContext *C, wmOperator *op) @@ -769,72 +814,95 @@ static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but) (block->handle && block->handle->popup_op)); } +/** + * These functions are postponed and only executed after all other + * handling is done, i.e. menus are closed, in order to avoid conflicts + * with these functions removing the buttons we are working with. + */ static void ui_apply_but_func(bContext *C, uiBut *but) { uiBlock *block = but->block; + if (!ui_afterfunc_check(block, but)) { + return; + } - /* these functions are postponed and only executed after all other - * handling is done, i.e. menus are closed, in order to avoid conflicts - * with these functions removing the buttons we are working with */ - - if (ui_afterfunc_check(block, but)) { - uiAfterFunc *after = ui_afterfunc_new(); + uiAfterFunc *after = ui_afterfunc_new(); - if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) { - /* exception, this will crash due to removed button otherwise */ - but->func(C, but->func_arg1, but->func_arg2); - } - else { - after->func = but->func; - } + if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) { + /* exception, this will crash due to removed button otherwise */ + but->func(C, but->func_arg1, but->func_arg2); + } + else { + after->func = but->func; + } - after->func_arg1 = but->func_arg1; - after->func_arg2 = but->func_arg2; + after->func_arg1 = but->func_arg1; + after->func_arg2 = but->func_arg2; - after->funcN = but->funcN; - after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL; + after->funcN = but->funcN; + after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL; - after->rename_func = but->rename_func; - after->rename_arg1 = but->rename_arg1; - after->rename_orig = but->rename_orig; /* needs free! */ + after->rename_func = but->rename_func; + after->rename_arg1 = but->rename_arg1; + after->rename_orig = but->rename_orig; /* needs free! */ - after->handle_func = block->handle_func; - after->handle_func_arg = block->handle_func_arg; - after->retval = but->retval; + after->handle_func = block->handle_func; + after->handle_func_arg = block->handle_func_arg; + after->retval = but->retval; - if (but->type == UI_BTYPE_BUT_MENU) { - after->butm_func = block->butm_func; - after->butm_func_arg = block->butm_func_arg; - after->a2 = but->a2; - } + if (but->type == UI_BTYPE_BUT_MENU) { + after->butm_func = block->butm_func; + after->butm_func_arg = block->butm_func_arg; + after->a2 = but->a2; + } - if (block->handle) { - after->popup_op = block->handle->popup_op; - } + if (block->handle) { + after->popup_op = block->handle->popup_op; + } - after->optype = but->optype; - after->opcontext = but->opcontext; - after->opptr = but->opptr; + after->optype = but->optype; + after->opcontext = but->opcontext; + after->opptr = but->opptr; - after->rnapoin = but->rnapoin; - after->rnaprop = but->rnaprop; + after->rnapoin = but->rnapoin; + after->rnaprop = but->rnaprop; - if (but->type == UI_BTYPE_SEARCH_MENU) { - uiButSearch *search_but = (uiButSearch *)but; - after->search_arg_free_fn = search_but->arg_free_fn; - after->search_arg = search_but->arg; - search_but->arg_free_fn = NULL; - search_but->arg = NULL; - } + if (but->type == UI_BTYPE_SEARCH_MENU) { + uiButSearch *search_but = (uiButSearch *)but; + after->search_arg_free_fn = search_but->arg_free_fn; + after->search_arg = search_but->arg; + search_but->arg_free_fn = NULL; + search_but->arg = NULL; + } - if (but->context) { - after->context = CTX_store_copy(but->context); + if (but->active != NULL) { + uiHandleButtonData *data = but->active; + if (data->custom_interaction_handle != NULL) { + after->custom_interaction_callbacks = block->custom_interaction_callbacks; + after->custom_interaction_handle = data->custom_interaction_handle; + + /* Ensure this callback runs once and last. */ + uiAfterFunc *after_prev = after->prev; + if (after_prev && + (after_prev->custom_interaction_handle == data->custom_interaction_handle)) { + after_prev->custom_interaction_handle = NULL; + memset(&after_prev->custom_interaction_callbacks, + 0x0, + sizeof(after_prev->custom_interaction_callbacks)); + } + else { + after->custom_interaction_handle->user_count++; + } } + } - but->optype = NULL; - but->opcontext = 0; - but->opptr = NULL; + if (but->context) { + after->context = CTX_store_copy(but->context); } + + but->optype = NULL; + but->opcontext = 0; + but->opptr = NULL; } /* typically call ui_apply_but_undo(), ui_apply_but_autokey() */ @@ -997,6 +1065,18 @@ static void ui_apply_but_funcs_after(bContext *C) after.search_arg_free_fn(after.search_arg); } + if (after.custom_interaction_handle != NULL) { + after.custom_interaction_handle->user_count--; + BLI_assert(after.custom_interaction_handle->user_count >= 0); + if (after.custom_interaction_handle->user_count == 0) { + ui_block_interaction_update( + C, &after.custom_interaction_callbacks, after.custom_interaction_handle); + ui_block_interaction_end( + C, &after.custom_interaction_callbacks, after.custom_interaction_handle); + } + after.custom_interaction_handle = NULL; + } + ui_afterfunc_update_preferences_dirty(&after); if (after.undostr[0]) { @@ -1076,6 +1156,42 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu data->applied = true; } +/** + * \note Ownership of \a properties is moved here. The #uiAfterFunc owns it now. + * + * \param context_but: The button to use context from when calling or polling the operator. + * + * \returns true if the operator was executed, otherwise false. + */ +static bool ui_list_invoke_item_operator(bContext *C, + const uiBut *context_but, + wmOperatorType *ot, + PointerRNA **properties) +{ + if (!ui_but_context_poll_operator(C, ot, context_but)) { + return false; + } + + /* Allow the context to be set from the hovered button, so the list item draw callback can set + * context for the operators. */ + ui_handle_afterfunc_add_operator_ex(ot, properties, WM_OP_INVOKE_DEFAULT, context_but); + return true; +} + +static void ui_apply_but_LISTROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data) +{ + uiBut *listbox = ui_list_find_from_row(data->region, but); + if (listbox) { + uiList *list = listbox->custom_data; + if (list && list->dyn_data->custom_activate_optype) { + ui_list_invoke_item_operator( + C, but, list->dyn_data->custom_activate_optype, &list->dyn_data->custom_activate_opptr); + } + } + + ui_apply_but_ROW(C, block, but, data); +} + static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data) { if (!data->str) { @@ -1350,7 +1466,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat } /* edit buttons proportionally to eachother - * note: if we mix buttons which are proportional and others which are not, + * NOTE: if we mix buttons which are proportional and others which are not, * this may work a bit strangely */ if ((but_active->rnaprop && (RNA_property_flag(but_active->rnaprop) & PROP_PROPORTIONAL)) || ELEM(but_active->unit_type, RNA_SUBTYPE_UNIT_VALUE(PROP_UNIT_LENGTH))) { @@ -1502,7 +1618,7 @@ static bool ui_drag_toggle_set_xy_xy( ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]); LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - /* Note: ctrl is always true here because (at least for now) + /* NOTE: ctrl is always true here because (at least for now) * we always want to consider text control in this case, even when not embossed. */ if (ui_but_is_interactive(but, true)) { if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) { @@ -1548,7 +1664,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const */ if (drag_info->is_xy_lock_init == false) { /* first store the buttons original coords */ - uiBut *but = ui_but_find_mouse_over_ex(region, xy_input[0], xy_input[1], true); + uiBut *but = ui_but_find_mouse_over_ex(region, xy_input[0], xy_input[1], true, NULL, NULL); if (but) { if (but->flag & UI_BUT_DRAG_LOCK) { @@ -1619,7 +1735,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void wmWindow *win = CTX_wm_window(C); const ARegion *region = CTX_wm_region(C); uiBut *but = ui_but_find_mouse_over_ex( - region, drag_info->xy_init[0], drag_info->xy_init[1], true); + region, drag_info->xy_init[0], drag_info->xy_init[1], true, NULL, NULL); if (but) { ui_apply_but_undo(but); @@ -1686,7 +1802,7 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore break; } uiSelectContextElem *other = &selctx_data->elems[i]; - /* TODO,. de-duplicate copy_to_selected_button */ + /* TODO: de-duplicate copy_to_selected_button. */ if (link->ptr.data != ptr.data) { if (use_path_from_id) { /* Path relative to ID. */ @@ -1987,7 +2103,7 @@ static bool ui_but_drag_init(bContext *C, bool valid = false; uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__); - /* TODO support more button pointer types */ + /* TODO: support more button pointer types. */ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { ui_but_v3_get(but, drag_info->color); drag_info->gamma_corrected = true; @@ -2181,9 +2297,11 @@ static void ui_apply_but( ui_apply_but_TOG(C, but, data); break; case UI_BTYPE_ROW: - case UI_BTYPE_LISTROW: ui_apply_but_ROW(C, block, but, data); break; + case UI_BTYPE_LISTROW: + ui_apply_but_LISTROW(C, block, but, data); + break; case UI_BTYPE_DATASETROW: ui_apply_but_ROW(C, block, but, data); break; @@ -2283,6 +2401,11 @@ static void ui_apply_but( uiButCurveProfile *but_profile = (uiButCurveProfile *)but; but_profile->edit_profile = editprofile; } + + if (data->custom_interaction_handle != NULL) { + ui_block_interaction_update( + C, &block->custom_interaction_callbacks, data->custom_interaction_handle); + } } /** \} */ @@ -2297,7 +2420,7 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */ LISTBASE_FOREACH (wmDrag *, wmd, drags) { - /* TODO asset dropping. */ + /* TODO: asset dropping. */ if (wmd->type == WM_DRAG_ID) { /* align these types with UI_but_active_drop_name */ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { @@ -2428,7 +2551,7 @@ static void ui_but_paste_numeric_array(bContext *C, static void ui_but_copy_numeric_value(uiBut *but, char *output, int output_len_max) { /* Get many decimal places, then strip trailing zeros. - * note: too high values start to give strange results */ + * NOTE: too high values start to give strange results. */ ui_but_string_get_ex(but, output, output_len_max, UI_PRECISION_FLOAT_MAX, false, NULL); BLI_str_rstrip_float_zero(output, '\0'); } @@ -3268,7 +3391,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in } #ifdef WITH_INPUT_IME -/* enable ime, and set up uibut ime data */ +/* Enable IME, and setup #uiBut IME data. */ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) { /* XXX Is this really needed? */ @@ -3284,7 +3407,7 @@ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) wm_window_IME_begin(win, x, y, 0, 0, true); } -/* disable ime, and clear uibut ime data */ +/* Disable IME, and clear #uiBut IME data. */ static void ui_textedit_ime_end(wmWindow *win, uiBut *UNUSED(but)) { wm_window_IME_end(win); @@ -3396,6 +3519,11 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) ui_but_update(but); + /* Popup blocks don't support moving after creation, so don't change the view for them. */ + if (!data->searchbox) { + UI_but_ensure_in_view(C, data->region, but); + } + WM_cursor_modal_set(win, WM_CURSOR_TEXT_EDIT); #ifdef WITH_INPUT_IME @@ -4210,7 +4338,7 @@ static uiBut *ui_but_list_row_text_activate(bContext *C, uiButtonActivateType activate_type) { ARegion *region = CTX_wm_region(C); - uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->x, event->y, true); + uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->x, event->y, true, NULL, NULL); if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) { /* exit listrow */ @@ -4284,7 +4412,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C, button_tooltip_timer_reset(C, but); ui_but_extra_operator_icon_apply(C, but, op_icon); - /* Note: 'but', 'data' may now be freed, don't access. */ + /* NOTE: 'but', 'data' may now be freed, don't access. */ return true; } @@ -4334,7 +4462,7 @@ static bool ui_do_but_ANY_drag_toggle( } } else if (data->state == BUTTON_STATE_WAIT_DRAG) { - /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into + /* NOTE: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into * its own function */ data->applied = false; *r_retval = ui_do_but_EXIT(C, but, data, event); @@ -4677,7 +4805,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con { if (data->state == BUTTON_STATE_HIGHLIGHT) { - /* first handle click on icondrag type button */ + /* First handle click on icon-drag type button. */ if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) && but->dragpoin) { if (ui_but_contains_point_px_icon(but, data->region, event)) { @@ -4700,10 +4828,19 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) { int ret = WM_UI_HANDLER_BREAK; - /* XXX (a bit ugly) Special case handling for filebrowser drag button */ + /* XXX: (a bit ugly) Special case handling for file-browser drag button. */ if (but->dragpoin && but->imb && ui_but_contains_point_px_icon(but, data->region, event)) { ret = WM_UI_HANDLER_CONTINUE; } + /* Same special case handling for UI lists. Return CONTINUE so that a tweak or CLICK event + * will be sent for the list to work with. */ + const uiBut *listbox = ui_list_find_mouse_over(data->region, event); + if (listbox) { + const uiList *ui_list = listbox->custom_data; + if (ui_list && ui_list->dyn_data->custom_drag_optype) { + ret = WM_UI_HANDLER_CONTINUE; + } + } button_activate_state(C, but, BUTTON_STATE_EXIT); return ret; } @@ -4852,6 +4989,8 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but, return changed; } + ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false); + if (ui_but_is_cursor_warp(but)) { const float softmin = but->softmin; const float softmax = but->softmax; @@ -5362,6 +5501,8 @@ static bool ui_numedit_but_SLI(uiBut *but, return changed; } + ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false); + const PropertyScaleType scale_type = ui_but_scale_type(but); softmin = but->softmin; @@ -5763,7 +5904,7 @@ static int ui_do_but_GRIP( int retval = WM_UI_HANDLER_CONTINUE; const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect)); - /* Note: Having to store org point in window space and recompute it to block "space" each time + /* NOTE: Having to store org point in window space and recompute it to block "space" each time * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which * returns different results when the block is inside a panel or not... * See T37739. @@ -5836,7 +5977,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co { if (data->state == BUTTON_STATE_HIGHLIGHT) { - /* first handle click on icondrag type button */ + /* First handle click on icon-drag type button. */ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) { if (ui_but_contains_point_px_icon(but, data->region, event)) { button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); @@ -6021,7 +6162,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co uiButColor *color_but = (uiButColor *)but; if (data->state == BUTTON_STATE_HIGHLIGHT) { - /* first handle click on icondrag type button */ + /* First handle click on icon-drag type button. */ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) { ui_palette_set_active(color_but); if (ui_but_contains_point_px_icon(but, data->region, event)) { @@ -6435,7 +6576,7 @@ static void ui_ndofedit_but_HSVCUBE(uiButHSVCube *hsv_but, CLAMP(hsv[2], hsv_but->but.softmin, hsv_but->but.softmax); break; default: - BLI_assert(!"invalid hsv type"); + BLI_assert_msg(0, "invalid hsv type"); break; } @@ -6951,8 +7092,8 @@ static bool ui_numedit_but_CURVE(uiBlock *block, CurveMapPoint *cmp = cuma->curve; bool changed = false; - /* evtx evty and drag coords are absolute mousecoords, - * prevents errors when editing when layout changes */ + /* evtx evty and drag coords are absolute mouse-coords, + * prevents errors when editing when layout changes. */ int mx = evtx; int my = evty; ui_window_to_block(data->region, block, &mx, &my); @@ -7010,7 +7151,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block, changed = true; #ifdef USE_CONT_MOUSE_CORRECT - /* note: using 'cmp_last' is weak since there may be multiple points selected, + /* NOTE: using 'cmp_last' is weak since there may be multiple points selected, * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ @@ -7219,8 +7360,8 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, CurveProfilePoint *pts = profile->path; bool changed = false; - /* evtx evty and drag coords are absolute mousecoords, - * prevents errors when editing when layout changes */ + /* evtx evty and drag coords are absolute mouse-coords, + * prevents errors when editing when layout changes. */ int mx = evtx; int my = evty; ui_window_to_block(data->region, block, &mx, &my); @@ -7281,7 +7422,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, data->draglasty = evty; changed = true; #ifdef USE_CONT_MOUSE_CORRECT - /* note: using 'cmp_last' is weak since there may be multiple points selected, + /* NOTE: using 'cmp_last' is weak since there may be multiple points selected, * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ @@ -7773,7 +7914,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * if ((event->type == RIGHTMOUSE) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) && (event->val == KM_PRESS)) { /* RMB has two options now */ - if (ui_popup_context_menu_for_button(C, but)) { + if (ui_popup_context_menu_for_button(C, but, event)) { return WM_UI_HANDLER_BREAK; } } @@ -7853,6 +7994,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case UI_BTYPE_IMAGE: case UI_BTYPE_PROGRESS_BAR: case UI_BTYPE_NODE_SOCKET: + case UI_BTYPE_PREVIEW_TILE: retval = ui_do_but_EXIT(C, but, data, event); break; case UI_BTYPE_HISTOGRAM: @@ -8239,6 +8381,16 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s but->flag &= ~UI_SELECT; } + if (state == BUTTON_STATE_TEXT_EDITING) { + ui_block_interaction_begin_ensure(C, but->block, data, true); + } + else if (state == BUTTON_STATE_EXIT) { + if (data->state == BUTTON_STATE_NUM_EDITING) { + /* This happens on pasting values for example. */ + ui_block_interaction_begin_ensure(C, but->block, data, true); + } + } + data->state = state; if (state != BUTTON_STATE_EXIT) { @@ -8467,6 +8619,21 @@ static void button_activate_exit( ED_region_tag_redraw_no_rebuild(data->region); ED_region_tag_refresh_ui(data->region); + if ((but->flag & UI_BUT_DRAG_MULTI) == 0) { + if (data->custom_interaction_handle != NULL) { + /* Should only set when the button is modal. */ + BLI_assert(but->active != NULL); + data->custom_interaction_handle->user_count--; + + BLI_assert(data->custom_interaction_handle->user_count >= 0); + if (data->custom_interaction_handle->user_count == 0) { + ui_block_interaction_end( + C, &but->block->custom_interaction_callbacks, data->custom_interaction_handle); + } + data->custom_interaction_handle = NULL; + } + } + /* clean up button */ if (but->active) { MEM_freeN(but->active); @@ -8614,9 +8781,9 @@ void UI_context_active_but_prop_handle(bContext *C) { uiBut *activebut = ui_context_rna_button_active(C); if (activebut) { - /* TODO, look into a better way to handle the button change + /* TODO(campbell): look into a better way to handle the button change * currently this is mainly so reset defaults works for the - * operator redo panel - campbell */ + * operator redo panel. */ uiBlock *block = activebut->block; if (block->handle_func) { block->handle_func(C, block->handle_func_arg, activebut->retval); @@ -8722,6 +8889,26 @@ void UI_context_update_anim_flag(const bContext *C) } } +/** + * In some cases we may want to update the view (#View2D) in-between layout definition and drawing. + * E.g. to make sure a button is visible while editing. + */ +void ui_but_update_view_for_active(const bContext *C, const uiBlock *block) +{ + uiBut *active_but = ui_block_active_but_get(block); + if (!active_but || !active_but->active || !active_but->changed || active_but->block != block) { + return; + } + /* If there is a search popup attached to the button, don't change the view. The popups don't + * support updating the position to the button position nicely. */ + uiHandleButtonData *data = active_but->active; + if (data->searchbox) { + return; + } + + UI_but_ensure_in_view(C, active_but->active->region, active_but); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -8805,7 +8992,7 @@ void ui_but_execute_begin(struct bContext *UNUSED(C), { BLI_assert(region != NULL); BLI_assert(BLI_findindex(®ion->uiblocks, but->block) != -1); - /* note: ideally we would not have to change 'but->active' however + /* NOTE: ideally we would not have to change 'but->active' however * some functions we call don't use data (as they should be doing) */ uiHandleButtonData *data; *active_back = but->active; @@ -9174,7 +9361,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) * * This is needed to make sure if a button was active, * it stays active while the mouse is over it. - * This avoids adding mousemoves, see: T33466. */ + * This avoids adding mouse-moves, see: T33466. */ if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT, BUTTON_STATE_WAIT_DRAG)) { if (ui_but_find_mouse_over(region, event) == but) { button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER); @@ -9186,6 +9373,149 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) return retval; } +/** + * Activate the underlying list-row button, so the row is highlighted. + * Early exits if \a activate_dragging is true, but the custom drag operator fails to execute. + * Gives the wanted behavior where the item is activated on a tweak event when the custom drag + * operator is executed. + */ +static int ui_list_activate_hovered_row(bContext *C, + ARegion *region, + const uiList *ui_list, + const wmEvent *event, + bool activate_dragging) +{ + const bool do_drag = activate_dragging && ui_list->dyn_data->custom_drag_optype; + + if (do_drag) { + const uiBut *hovered_but = ui_but_find_mouse_over(region, event); + if (!ui_list_invoke_item_operator(C, + hovered_but, + ui_list->dyn_data->custom_drag_optype, + &ui_list->dyn_data->custom_drag_opptr)) { + return WM_UI_HANDLER_CONTINUE; + } + } + + const int *mouse_xy = ISTWEAK(event->type) ? &event->prevclickx : &event->x; + uiBut *listrow = ui_list_row_find_mouse_over(region, mouse_xy[0], mouse_xy[1]); + if (listrow) { + wmOperatorType *custom_activate_optype = ui_list->dyn_data->custom_activate_optype; + + /* Hacky: Ensure the custom activate operator is not called when the custom drag operator + * was. Only one should run! */ + if (activate_dragging && do_drag) { + ((uiList *)ui_list)->dyn_data->custom_activate_optype = NULL; + } + + /* Simulate click on listrow button itself (which may be overlapped by another button). Also + * calls the custom activate operator (ui_list->custom_activate_opname). */ + UI_but_execute(C, region, listrow); + + ((uiList *)ui_list)->dyn_data->custom_activate_optype = custom_activate_optype; + } + + return WM_UI_HANDLER_BREAK; +} + +static bool ui_list_is_hovering_draggable_but(bContext *C, + const uiList *list, + const ARegion *region, + const wmEvent *event) +{ + /* On a tweak event, uses the coordinates from where tweaking was started. */ + const int *mouse_xy = ISTWEAK(event->type) ? &event->prevclickx : &event->x; + const uiBut *hovered_but = ui_but_find_mouse_over_ex( + region, mouse_xy[0], mouse_xy[1], false, NULL, NULL); + + if (list->dyn_data->custom_drag_optype) { + if (ui_but_context_poll_operator(C, list->dyn_data->custom_drag_optype, hovered_but)) { + return true; + } + } + + return (hovered_but && hovered_but->dragpoin); +} + +static int ui_list_handle_click_drag(bContext *C, + const uiList *ui_list, + ARegion *region, + const wmEvent *event) +{ + if (!ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) { + return WM_HANDLER_CONTINUE; + } + + int retval = WM_HANDLER_CONTINUE; + + const bool is_draggable = ui_list_is_hovering_draggable_but(C, ui_list, region, event); + bool activate = false; + bool activate_dragging = false; + + if (event->type == EVT_TWEAK_L) { + if (is_draggable) { + activate_dragging = true; + activate = true; + } + } + /* #KM_CLICK is only sent after an uncaught release event, so the foreground button gets all + * regular events (including mouse presses to start dragging) and this part only kicks in if it + * hasn't handled the release event. Note that if there's no overlaid button, the row selects + * on the press event already via regular #UI_BTYPE_LISTROW handling. */ + else if ((event->type == LEFTMOUSE) && (event->val == KM_CLICK)) { + activate = true; + } + + if (activate) { + retval = ui_list_activate_hovered_row(C, region, ui_list, event, activate_dragging); + } + + return retval; +} + +static void ui_list_activate_row_from_index( + bContext *C, ARegion *region, uiBut *listbox, uiList *ui_list, int index) +{ + uiBut *new_active_row = ui_list_row_find_from_index(region, index, listbox); + if (new_active_row) { + /* Preferred way to update the active item, also calls the custom activate operator + * (#uiList.custom_activate_opname). */ + UI_but_execute(C, region, new_active_row); + } + else { + /* A bit ugly, set the active index in RNA directly. That's because a button that's + * scrolled away in the list box isn't created at all. + * The custom activate operator (#uiList.custom_activate_opname) is not called in this case + * (which may need the row button context).*/ + RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, index); + RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop); + ui_apply_but_undo(listbox); + } + + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; +} + +static int ui_list_get_increment(const uiList *ui_list, const int type, const int columns) +{ + int increment = 0; + + /* Handle column offsets for grid layouts. */ + if (ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY) && + ELEM(ui_list->layout_type, UILST_LAYOUT_GRID, UILST_LAYOUT_BIG_PREVIEW_GRID)) { + increment = (type == EVT_UPARROWKEY) ? -columns : columns; + } + else { + /* Left or right in grid layouts or any direction in single column layouts increments by 1. */ + increment = ELEM(type, EVT_UPARROWKEY, EVT_LEFTARROWKEY, WHEELUPMOUSE) ? -1 : 1; + } + + if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) { + increment *= -1; + } + + return increment; +} + static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *region, uiBut *listbox) { int retval = WM_UI_HANDLER_CONTINUE; @@ -9219,22 +9549,19 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi } } - if (val == KM_PRESS) { - if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY) && + if (ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) { + retval = ui_list_handle_click_drag(C, ui_list, region, event); + } + else if (val == KM_PRESS) { + if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY, EVT_LEFTARROWKEY, EVT_RIGHTARROWKEY) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) || ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)))) { const int value_orig = RNA_property_int_get(&listbox->rnapoin, listbox->rnaprop); - int value, min, max, inc; + int value, min, max; - /* activate up/down the list */ value = value_orig; - if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) { - inc = ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE) ? 1 : -1; - } - else { - inc = ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE) ? -1 : 1; - } + const int inc = ui_list_get_increment(ui_list, type, dyn_data->columns); if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) { /* If we have a display order different from @@ -9281,12 +9608,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi CLAMP(value, min, max); if (value != value_orig) { - RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, value); - RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop); - - ui_apply_but_undo(listbox); - - ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ui_list_activate_row_from_index(C, region, listbox, ui_list, value); redraw = true; } retval = WM_UI_HANDLER_BREAK; @@ -10255,7 +10577,7 @@ static int ui_handle_menu_event(bContext *C, /* For buttons that use a hold function, * exit when mouse-up outside the menu. */ if (block->flag & UI_BLOCK_POPUP_HOLD) { - /* Note, we could check the cursor is over the parent button. */ + /* NOTE: we could check the cursor is over the parent button. */ menu->menuretval = UI_RETURN_CANCEL; retval = WM_UI_HANDLER_CONTINUE; } @@ -11314,3 +11636,100 @@ bool UI_but_active_drop_color(bContext *C) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UI Block Interaction API + * \{ */ + +void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks) +{ + block->custom_interaction_callbacks = *callbacks; +} + +static uiBlockInteraction_Handle *ui_block_interaction_begin(bContext *C, + uiBlock *block, + const bool is_click) +{ + BLI_assert(block->custom_interaction_callbacks.begin_fn != NULL); + uiBlockInteraction_Handle *interaction = MEM_callocN(sizeof(*interaction), __func__); + + int unique_retval_ids_len = 0; + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) { + unique_retval_ids_len++; + } + } + + int *unique_retval_ids = MEM_mallocN(sizeof(*unique_retval_ids) * unique_retval_ids_len, + __func__); + unique_retval_ids_len = 0; + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) { + unique_retval_ids[unique_retval_ids_len++] = but->retval; + } + } + + if (unique_retval_ids_len > 1) { + qsort(unique_retval_ids, unique_retval_ids_len, sizeof(int), BLI_sortutil_cmp_int); + unique_retval_ids_len = BLI_array_deduplicate_ordered(unique_retval_ids, + unique_retval_ids_len); + unique_retval_ids = MEM_reallocN(unique_retval_ids, + sizeof(*unique_retval_ids) * unique_retval_ids_len); + } + + interaction->params.is_click = is_click; + interaction->params.unique_retval_ids = unique_retval_ids; + interaction->params.unique_retval_ids_len = unique_retval_ids_len; + + interaction->user_data = block->custom_interaction_callbacks.begin_fn( + C, &interaction->params, block->custom_interaction_callbacks.arg1); + return interaction; +} + +static void ui_block_interaction_end(bContext *C, + uiBlockInteraction_CallbackData *callbacks, + uiBlockInteraction_Handle *interaction) +{ + BLI_assert(callbacks->end_fn != NULL); + callbacks->end_fn(C, &interaction->params, callbacks->arg1, interaction->user_data); + MEM_freeN(interaction->params.unique_retval_ids); + MEM_freeN(interaction); +} + +static void ui_block_interaction_update(bContext *C, + uiBlockInteraction_CallbackData *callbacks, + uiBlockInteraction_Handle *interaction) +{ + BLI_assert(callbacks->update_fn != NULL); + callbacks->update_fn(C, &interaction->params, callbacks->arg1, interaction->user_data); +} + +/** + * \note #ui_block_interaction_begin cannot be called when setting the button state + * (e.g. #BUTTON_STATE_NUM_EDITING) for the following reasons. + * + * - Other buttons may still be activated using #UI_BUT_DRAG_MULTI + * which is necessary before gathering all the #uiBut.retval values to initialize + * #uiBlockInteraction_Params.unique_retval_ids. + * - When clicking on a number button it's not known if the event is a click or a drag. + * + * Instead, it must be called immediately before the drag action begins. + */ +static void ui_block_interaction_begin_ensure(bContext *C, + uiBlock *block, + uiHandleButtonData *data, + const bool is_click) +{ + if (data->custom_interaction_handle) { + return; + } + if (block->custom_interaction_callbacks.begin_fn == NULL) { + return; + } + + uiBlockInteraction_Handle *interaction = ui_block_interaction_begin(C, block, is_click); + interaction->user_count = 1; + data->custom_interaction_handle = interaction; +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 4defbed940e..43ac646f053 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1180,7 +1180,7 @@ static DrawInfo *icon_ensure_drawinfo(Icon *icon) return di; } -/* note!, returns unscaled by DPI */ +/* NOTE:, returns unscaled by DPI. */ int UI_icon_get_width(int icon_id) { Icon *icon = BKE_icon_get(icon_id); @@ -1500,7 +1500,7 @@ static void icon_draw_rect(float x, /* sanity check */ if (w <= 0 || h <= 0 || w > 2000 || h > 2000) { printf("%s: icons are %i x %i pixels?\n", __func__, w, h); - BLI_assert(!"invalid icon size"); + BLI_assert_msg(0, "invalid icon size"); return; } /* modulate color */ @@ -1519,7 +1519,7 @@ static void icon_draw_rect(float x, draw_h = h; draw_x += (w - draw_w) / 2; } - /* if the image is squared, the draw_ initialization values are good */ + /* If the image is squared, the `draw_*` initialization values are good. */ /* first allocate imbuf for scaling and copy preview into it */ ima = IMB_allocImBuf(rw, rh, 32, IB_rect); @@ -2201,7 +2201,7 @@ int UI_icon_from_library(const ID *id) return ICON_NONE; } -int UI_icon_from_rnaptr(bContext *C, PointerRNA *ptr, int rnaicon, const bool big) +int UI_icon_from_rnaptr(const bContext *C, PointerRNA *ptr, int rnaicon, const bool big) { ID *id = NULL; @@ -2294,7 +2294,7 @@ int UI_icon_from_idcode(const int idcode) case ID_ME: return ICON_MESH_DATA; case ID_MSK: - return ICON_MOD_MASK; /* TODO! this would need its own icon! */ + return ICON_MOD_MASK; /* TODO: this would need its own icon! */ case ID_NT: return ICON_NODETREE; case ID_OB: @@ -2302,9 +2302,9 @@ int UI_icon_from_idcode(const int idcode) case ID_PA: return ICON_PARTICLE_DATA; case ID_PAL: - return ICON_COLOR; /* TODO! this would need its own icon! */ + return ICON_COLOR; /* TODO: this would need its own icon! */ case ID_PC: - return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */ + return ICON_CURVE_BEZCURVE; /* TODO: this would need its own icon! */ case ID_LP: return ICON_OUTLINER_DATA_LIGHTPROBE; case ID_SCE: diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index b9a44b5bce9..a07f924e65b 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -262,7 +262,7 @@ struct uiBut { ListBase extra_op_icons; /** #uiButExtraOpIcon */ - /* Draggable data, type is WM_DRAG_... */ + /* Drag-able data, type is WM_DRAG_... */ char dragtype; short dragflag; void *dragpoin; @@ -511,6 +511,9 @@ struct uiBlock { uiBlockHandleFunc handle_func; void *handle_func_arg; + /** Custom interaction data. */ + uiBlockInteraction_CallbackData custom_interaction_callbacks; + /** Custom extra event handling. */ int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *); @@ -594,11 +597,19 @@ typedef struct uiSafetyRct { void ui_fontscale(short *points, float aspect); +extern void ui_block_to_region_fl(const struct ARegion *region, + uiBlock *block, + float *r_x, + float *r_y); extern void ui_block_to_window_fl(const struct ARegion *region, uiBlock *block, float *x, float *y); extern void ui_block_to_window(const struct ARegion *region, uiBlock *block, int *x, int *y); +extern void ui_block_to_region_rctf(const struct ARegion *region, + uiBlock *block, + rctf *rct_dst, + const rctf *rct_src); extern void ui_block_to_window_rctf(const struct ARegion *region, uiBlock *block, rctf *rct_dst, @@ -617,6 +628,9 @@ extern void ui_window_to_region(const struct ARegion *region, int *x, int *y); extern void ui_window_to_region_rcti(const struct ARegion *region, rcti *rect_dst, const rcti *rct_src); +extern void ui_window_to_region_rctf(const struct ARegion *region, + rctf *rect_dst, + const rctf *rct_src); extern void ui_region_to_window(const struct ARegion *region, int *x, int *y); extern void ui_region_winrct_get_no_margin(const struct ARegion *region, struct rcti *r_rect); @@ -928,9 +942,7 @@ const char *ui_textedit_undo(struct uiUndoStack_Text *undo_stack, int *r_cursor_index); /* interface_handlers.c */ -PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, - int opcontext, - bool create_props); +extern void ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext); extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val); extern void ui_but_activate_event(struct bContext *C, struct ARegion *region, uiBut *but); extern void ui_but_activate_over(struct bContext *C, struct ARegion *region, uiBut *but); @@ -943,6 +955,7 @@ extern void ui_but_execute_end(struct bContext *C, uiBut *but, void *active_back); extern void ui_but_active_free(const struct bContext *C, uiBut *but); +extern void ui_but_update_view_for_active(const struct bContext *C, const uiBlock *block); extern int ui_but_menu_direction(uiBut *but); extern void ui_but_text_password_hide(char password_str[128], uiBut *but, const bool restore); extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction); @@ -1042,8 +1055,18 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle, int state, uiMenuItemSeparatorType separator_type, int *r_xmax); -void ui_draw_preview_item( - const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); +void ui_draw_preview_item(const struct uiFontStyle *fstyle, + rcti *rect, + const char *name, + int iconid, + int state, + eFontStyle_Align text_align); +void ui_draw_preview_item_stateless(const struct uiFontStyle *fstyle, + rcti *rect, + const char *name, + int iconid, + const uchar text_col[4], + eFontStyle_Align text_align); #define UI_TEXT_MARGIN_X 0.4f #define UI_POPUP_MARGIN (UI_DPI_FAC * 12) @@ -1125,19 +1148,32 @@ bool ui_but_contains_point_px_icon(const uiBut *but, bool ui_but_contains_point_px(const uiBut *but, const struct ARegion *region, int x, int y) ATTR_WARN_UNUSED_RESULT; -uiBut *ui_list_find_mouse_over(struct ARegion *region, +uiBut *ui_list_find_mouse_over(const struct ARegion *region, const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT; - +uiBut *ui_list_find_from_row(const struct ARegion *region, + const uiBut *row_but) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_list_row_find_mouse_over(const struct ARegion *region, + int x, + int y) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_list_row_find_from_index(const struct ARegion *region, + const int index, + uiBut *listbox) ATTR_WARN_UNUSED_RESULT; + +typedef bool (*uiButFindPollFn)(const uiBut *but, const void *customdata); uiBut *ui_but_find_mouse_over_ex(const struct ARegion *region, const int x, const int y, - const bool labeledit) ATTR_WARN_UNUSED_RESULT; + const bool labeledit, + const uiButFindPollFn find_poll, + const void *find_custom_data) ATTR_WARN_UNUSED_RESULT; uiBut *ui_but_find_mouse_over(const struct ARegion *region, const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT; uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) ATTR_WARN_UNUSED_RESULT; -uiBut *ui_list_find_mouse_over_ex(struct ARegion *region, int x, int y) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_list_find_mouse_over_ex(const struct ARegion *region, + int x, + int y) ATTR_WARN_UNUSED_RESULT; bool ui_but_contains_password(const uiBut *but) ATTR_WARN_UNUSED_RESULT; @@ -1149,6 +1185,7 @@ uiBut *ui_but_next(uiBut *but) ATTR_WARN_UNUSED_RESULT; uiBut *ui_but_first(uiBlock *block) ATTR_WARN_UNUSED_RESULT; uiBut *ui_but_last(uiBlock *block) ATTR_WARN_UNUSED_RESULT; +uiBut *ui_block_active_but_get(const uiBlock *block); bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; bool ui_block_is_popover(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; @@ -1176,7 +1213,7 @@ struct ARegion *ui_screen_region_find_mouse_over(struct bScreen *screen, const struct wmEvent *event); /* interface_context_menu.c */ -bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but); +bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but, const struct wmEvent *event); void ui_popup_context_menu_for_panel(struct bContext *C, struct ARegion *region, struct Panel *panel); @@ -1204,6 +1241,9 @@ void UI_OT_eyedropper_driver(struct wmOperatorType *ot); /* interface_eyedropper_gpencil_color.c */ void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot); +/* interface_template_asset_view.cc */ +struct uiListType *UI_UL_asset_view(void); + /** * For use with #ui_rna_collection_search_update_fn. */ diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index a17a527c868..8b9539f1d33 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -169,7 +169,7 @@ struct uiLayout { bool enabled; bool redalert; bool keepaspect; - /** For layouts inside gridflow, they and their items shall never have a fixed maximal size. */ + /** For layouts inside grid-flow, they and their items shall never have a fixed maximal size. */ bool variable_size; char alignment; eUIEmbossType emboss; @@ -643,7 +643,7 @@ static void ui_item_array(uiLayout *layout, NULL); } else { - /* note, this block of code is a bit arbitrary and has just been made + /* NOTE: this block of code is a bit arbitrary and has just been made * to work with common cases, but may need to be re-worked */ /* special case, boolean array in a menu, this could be used in a more generic way too */ @@ -662,7 +662,7 @@ static void ui_item_array(uiLayout *layout, } } - /* show checkboxes for rna on a non-emboss block (menu for eg) */ + /* Show check-boxes for rna on a non-emboss block (menu for eg). */ bool *boolarr = NULL; if (type == PROP_BOOLEAN && ELEM(layout->root->block->emboss, UI_EMBOSS_NONE, UI_EMBOSS_PULLDOWN)) { @@ -1411,7 +1411,7 @@ BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout) } /** - * Create ui items for enum items in \a item_array. + * Create UI items for enum items in \a item_array. * * A version of #uiItemsFullEnumO that takes pre-calculated item array. */ @@ -1818,7 +1818,7 @@ static void ui_item_rna_size(uiLayout *layout, } else if (type == PROP_BOOLEAN) { if (icon == ICON_NONE) { - /* Exception for checkboxes, they need a little less space to align nicely. */ + /* Exception for check-boxes, they need a little less space to align nicely. */ is_checkbox_only = true; } icon = ICON_DOT; @@ -1984,7 +1984,7 @@ void uiItemFullR(uiLayout *layout, * a label to display in the first column, the heading is inserted there. Otherwise it's inserted * as a new row before the first item. */ uiLayout *heading_layout = ui_layout_heading_find(layout); - /* Although checkboxes use the split layout, they are an exception and should only place their + /* Although check-boxes use the split layout, they are an exception and should only place their * label in the second column, to not make that almost empty. * * Keep using 'use_prop_sep' instead of disabling it entirely because @@ -2062,7 +2062,7 @@ void uiItemFullR(uiLayout *layout, /* Menus and pie-menus don't show checkbox without this. */ if ((layout->root->type == UI_LAYOUT_MENU) || - /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */ + /* Use check-boxes only as a fallback in pie-menu's, when no icon is defined. */ ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) { const int prop_flag = RNA_property_flag(prop); if (type == PROP_BOOLEAN) { @@ -2353,7 +2353,7 @@ void uiItemFullR(uiLayout *layout, } } - /* Mark non-embossed textfields inside a listbox. */ + /* Mark non-embossed text-fields inside a list-box. */ if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) && ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) { UI_but_flag_enable(but, UI_BUT_LIST_ITEM); @@ -2831,7 +2831,7 @@ void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt) PanelType *pt = (PanelType *)arg_pt; UI_paneltype_draw(C, pt, layout); - /* panels are created flipped (from event handling pov) */ + /* Panels are created flipped (from event handling POV). */ layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } @@ -3147,7 +3147,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) but->drawflag |= UI_BUT_TEXT_RIGHT; } - /* Mark as a label inside a listbox. */ + /* Mark as a label inside a list-box. */ if (block->flag & UI_BLOCK_LIST_ITEM) { but->flag |= UI_BUT_LIST_ITEM; } @@ -4639,7 +4639,7 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali { litem->root = layout->root; litem->align = align; - /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */ + /* Children of grid-flow layout shall never have "ideal big size" returned as estimated size. */ litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW; litem->active = true; litem->enabled = true; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index ce5c17a0718..376a41ff9bb 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -75,6 +75,32 @@ #include "ED_text.h" /* -------------------------------------------------------------------- */ +/** \name Immediate redraw helper + * + * Generally handlers shouldn't do any redrawing, that includes the layout/button definitions. That + * violates the Model-View-Controller pattern. + * + * But there are some operators which really need to re-run the layout definitions for various + * reasons. For example, "Edit Source" does it to find out which exact Python code added a button. + * Other operators may need to access buttons that aren't currently visible. In Blender's UI code + * design that typically means just not adding the button in the first place, for a particular + * redraw. So the operator needs to change context and re-create the layout, so the button becomes + * available to act on. + * + * \{ */ + +static void ui_region_redraw_immediately(bContext *C, ARegion *region) +{ + ED_region_do_layout(C, region); + WM_draw_region_viewport_bind(region); + ED_region_do_draw(C, region); + WM_draw_region_viewport_unbind(region); + region->do_draw = false; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Copy Data Path Operator * \{ */ @@ -1215,7 +1241,7 @@ static void UI_OT_jump_to_target_button(wmOperatorType *ot) /* ------------------------------------------------------------------------- */ /* EditSource Utility funcs and operator, - * note, this includes utility functions and button matching checks */ + * NOTE: this includes utility functions and button matching checks. */ typedef struct uiEditSourceStore { uiBut but_orig; @@ -1340,7 +1366,7 @@ static int editsource_text_edit(bContext *C, txt_move_toline(text, line - 1, false); /* naughty!, find text area to set, not good behavior - * but since this is a dev tool lets allow it - campbell */ + * but since this is a developer tool lets allow it - campbell */ ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0); if (area) { SpaceText *st = area->spacedata.first; @@ -1379,11 +1405,7 @@ static int editsource_exec(bContext *C, wmOperator *op) ui_editsource_active_but_set(but); /* redraw and get active button python info */ - ED_region_do_layout(C, region); - WM_draw_region_viewport_bind(region); - ED_region_do_draw(C, region); - WM_draw_region_viewport_unbind(region); - region->do_draw = false; + ui_region_redraw_immediately(C, region); for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash); BLI_ghashIterator_done(&ghi) == false; @@ -1836,6 +1858,64 @@ static void UI_OT_drop_color(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name UI List Search Operator + * \{ */ + +static bool ui_list_focused_poll(bContext *C) +{ + const ARegion *region = CTX_wm_region(C); + const wmWindow *win = CTX_wm_window(C); + const uiList *list = UI_list_find_mouse_over(region, win->eventstate); + + return list != NULL; +} + +/** + * Ensure the filter options are set to be visible in the UI list. + * \return if the visibility changed, requiring a redraw. + */ +static bool ui_list_unhide_filter_options(uiList *list) +{ + if (list->filter_flag & UILST_FLT_SHOW) { + /* Nothing to be done. */ + return false; + } + + list->filter_flag |= UILST_FLT_SHOW; + return true; +} + +static int ui_list_start_filter_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ARegion *region = CTX_wm_region(C); + uiList *list = UI_list_find_mouse_over(region, event); + /* Poll should check. */ + BLI_assert(list != NULL); + + if (ui_list_unhide_filter_options(list)) { + ui_region_redraw_immediately(C, region); + } + + if (!UI_textbutton_activate_rna(C, region, list, "filter_name")) { + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; +} + +static void UI_OT_list_start_filter(wmOperatorType *ot) +{ + ot->name = "List Filter"; + ot->idname = "UI_OT_list_start_filter"; + ot->description = "Start entering filter text for the list in focus"; + + ot->invoke = ui_list_start_filter_invoke; + ot->poll = ui_list_focused_poll; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Operator & Keymap Registration * \{ */ @@ -1860,6 +1940,8 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_button_execute); WM_operatortype_append(UI_OT_button_string_clear); + WM_operatortype_append(UI_OT_list_start_filter); + /* external */ WM_operatortype_append(UI_OT_eyedropper_color); WM_operatortype_append(UI_OT_eyedropper_colorramp); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index dc0650af7a7..97d01ac3763 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -258,7 +258,7 @@ static Panel *panel_add_instanced(ARegion *region, /* Make sure the panel is added to the end of the display-order as well. This is needed for * loading existing files. * - * Note: We could use special behavior to place it after the panel that starts the list of + * NOTE: We could use special behavior to place it after the panel that starts the list of * instanced panels, but that would add complexity that isn't needed for now. */ int max_sortorder = 0; LISTBASE_FOREACH (Panel *, existing_panel, panels) { @@ -1892,7 +1892,7 @@ static void ui_do_animate(bContext *C, Panel *panel) } else { if (UI_panel_is_dragging(panel)) { - /* Note: doing this in #panel_activate_state would require + /* NOTE: doing this in #panel_activate_state would require * removing `const` for context in many other places. */ reorder_instanced_panel_list(C, region, panel); } @@ -2563,7 +2563,7 @@ PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wm /** \name Window Level Modal Panel Interaction * \{ */ -/* Note, this is modal handler and should not swallow events for animation. */ +/* NOTE: this is modal handler and should not swallow events for animation. */ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata) { Panel *panel = userdata; @@ -2653,7 +2653,7 @@ static void panel_activate_state(const bContext *C, Panel *panel, const uiHandle /* Initiate edge panning during drags for scrolling beyond the initial region view. */ wmOperatorType *ot = WM_operatortype_find("VIEW2D_OT_edge_pan", true); - ui_handle_afterfunc_add_operator(ot, WM_OP_INVOKE_DEFAULT, true); + ui_handle_afterfunc_add_operator(ot, WM_OP_INVOKE_DEFAULT); } else if (state == PANEL_STATE_ANIMATION) { panel_set_flag_recursive(panel, PNL_SELECT, false); diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c index 7d561aa1c71..8534c95b6fd 100644 --- a/source/blender/editors/interface/interface_query.c +++ b/source/blender/editors/interface/interface_query.c @@ -78,7 +78,7 @@ bool ui_but_is_toggle(const uiBut *but) */ bool ui_but_is_interactive(const uiBut *but, const bool labeledit) { - /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */ + /* NOTE: #UI_BTYPE_LABEL is included for highlights, this allows drags. */ if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) { return false; } @@ -266,11 +266,29 @@ bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEv return BLI_rcti_isect_pt(&rect, x, y); } +static uiBut *ui_but_find(const ARegion *region, + const uiButFindPollFn find_poll, + const void *find_custom_data) +{ + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { + LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) { + if (find_poll && find_poll(but, find_custom_data) == false) { + continue; + } + return but; + } + } + + return NULL; +} + /* x and y are only used in case event is NULL... */ uiBut *ui_but_find_mouse_over_ex(const ARegion *region, const int x, const int y, - const bool labeledit) + const bool labeledit, + const uiButFindPollFn find_poll, + const void *find_custom_data) { uiBut *butover = NULL; @@ -282,6 +300,9 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region, ui_window_to_block_fl(region, block, &mx, &my); LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) { + if (find_poll && find_poll(but, find_custom_data) == false) { + continue; + } if (ui_but_is_interactive(but, labeledit)) { if (but->pie_dir != UI_RADIAL_NONE) { if (ui_but_isect_pie_seg(block, but)) { @@ -310,7 +331,7 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region, uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event) { - return ui_but_find_mouse_over_ex(region, event->x, event->y, event->ctrl != 0); + return ui_but_find_mouse_over_ex(region, event->x, event->y, event->ctrl != 0, NULL, NULL); } uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) @@ -351,7 +372,7 @@ uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) return butover; } -uiBut *ui_list_find_mouse_over_ex(ARegion *region, int x, int y) +uiBut *ui_list_find_mouse_over_ex(const ARegion *region, int x, int y) { if (!ui_region_contains_point_px(region, x, y)) { return NULL; @@ -369,11 +390,77 @@ uiBut *ui_list_find_mouse_over_ex(ARegion *region, int x, int y) return NULL; } -uiBut *ui_list_find_mouse_over(ARegion *region, const wmEvent *event) +uiBut *ui_list_find_mouse_over(const ARegion *region, const wmEvent *event) { + if (event == NULL) { + /* If there is no info about the mouse, just act as if there is nothing underneath it. */ + return NULL; + } return ui_list_find_mouse_over_ex(region, event->x, event->y); } +uiList *UI_list_find_mouse_over(const ARegion *region, const wmEvent *event) +{ + uiBut *list_but = ui_list_find_mouse_over(region, event); + if (!list_but) { + return NULL; + } + + return list_but->custom_data; +} + +static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_but) +{ + BLI_assert(listbox_but->type == UI_BTYPE_LISTBOX); + BLI_assert(listrow_but->type == UI_BTYPE_LISTROW); + /* The list box and its rows have the same RNA data (active data pointer/prop). */ + return ui_but_rna_equals(listbox_but, listrow_but); +} + +static bool ui_but_is_listbox_with_row(const uiBut *but, const void *customdata) +{ + const uiBut *row_but = customdata; + return (but->type == UI_BTYPE_LISTBOX) && ui_list_contains_row(but, row_but); +} + +uiBut *ui_list_find_from_row(const ARegion *region, const uiBut *row_but) +{ + return ui_but_find(region, ui_but_is_listbox_with_row, row_but); +} + +static bool ui_but_is_listrow(const uiBut *but, const void *UNUSED(customdata)) +{ + return but->type == UI_BTYPE_LISTROW; +} + +uiBut *ui_list_row_find_mouse_over(const ARegion *region, const int x, const int y) +{ + return ui_but_find_mouse_over_ex(region, x, y, false, ui_but_is_listrow, NULL); +} + +struct ListRowFindIndexData { + int index; + uiBut *listbox; +}; + +static bool ui_but_is_listrow_at_index(const uiBut *but, const void *customdata) +{ + const struct ListRowFindIndexData *find_data = customdata; + + return ui_but_is_listrow(but, NULL) && ui_list_contains_row(find_data->listbox, but) && + (but->hardmax == find_data->index); +} + +uiBut *ui_list_row_find_from_index(const ARegion *region, const int index, uiBut *listbox) +{ + BLI_assert(listbox->type == UI_BTYPE_LISTBOX); + struct ListRowFindIndexData data = { + .index = index, + .listbox = listbox, + }; + return ui_but_find(region, ui_but_is_listrow_at_index, &data); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -485,6 +572,17 @@ size_t ui_but_tip_len_only_first_line(const uiBut *but) /** \name Block (#uiBlock) State * \{ */ +uiBut *ui_block_active_but_get(const uiBlock *block) +{ + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active) { + return but; + } + } + + return NULL; +} + bool ui_block_is_menu(const uiBlock *block) { return (((block->flag & UI_BLOCK_LOOP) != 0) && @@ -588,10 +686,9 @@ uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, b uiBut *ui_region_find_active_but(ARegion *region) { LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - if (but->active) { - return but; - } + uiBut *but = ui_block_active_but_get(block); + if (but) { + return but; } } diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c index e68705e4321..48952c4f121 100644 --- a/source/blender/editors/interface/interface_region_color_picker.c +++ b/source/blender/editors/interface/interface_region_color_picker.c @@ -624,7 +624,7 @@ static void ui_block_colorpicker(uiBlock *block, bt->custom_data = cpicker; } - /* Note: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */ + /* NOTE: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */ /* RGB values */ UI_block_align_begin(block); diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index 6e60ca79aaf..d3c1a97e957 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -403,7 +403,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, pup->layout = UI_block_layout( pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - /* note, this intentionally differs from the menu & sub-menu default because many operators + /* NOTE: this intentionally differs from the menu & sub-menu default because many operators * use popups like this to select one of their options - * where having invoke doesn't make sense */ uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index a9f72233cb1..b8c4d8ddb09 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -420,7 +420,7 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap) * For now close this style of popovers when accessed. */ UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN); - /* panels are created flipped (from event handling pov) */ + /* Panels are created flipped (from event handling POV). */ pup->block->flag ^= UI_BLOCK_IS_FLIP; } diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 60e51244384..55a162c883a 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -341,7 +341,7 @@ static void ui_popup_block_position(wmWindow *window, block->safety.ymax = block->rect.ymax + s1; } - /* exception for switched pulldowns... */ + /* Exception for switched pull-downs. */ if (dir1 && (dir1 & block->direction) == 0) { if (dir2 == UI_DIR_RIGHT) { block->safety.xmax = block->rect.xmax + s2; diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index c35dbc5d7a6..c863b1f8bdf 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -599,8 +599,12 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) ui_searchbox_butrect(&rect, data, a); /* widget itself */ - ui_draw_preview_item( - &data->fstyle, &rect, data->items.names[a], data->items.icons[a], state); + ui_draw_preview_item(&data->fstyle, + &rect, + data->items.names[a], + data->items.icons[a], + state, + UI_STYLE_TEXT_LEFT); } /* indicate more */ @@ -684,13 +688,13 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) if (data->items.more) { ui_searchbox_butrect(&rect, data, data->items.maxitem - 1); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymin - 9, ICON_TRIA_DOWN); GPU_blend(GPU_BLEND_NONE); } if (data->items.offset) { ui_searchbox_butrect(&rect, data, 0); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymax - 7, ICON_TRIA_UP); GPU_blend(GPU_BLEND_NONE); } } @@ -986,13 +990,13 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe if (data->items.more) { ui_searchbox_butrect(&rect, data, data->items.maxitem - 1); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymin - 9, ICON_TRIA_DOWN); GPU_blend(GPU_BLEND_NONE); } if (data->items.offset) { ui_searchbox_butrect(&rect, data, 0); GPU_blend(GPU_BLEND_ALPHA); - UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP); + UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymax - 7, ICON_TRIA_UP); GPU_blend(GPU_BLEND_NONE); } } diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index bf3425dd3eb..10bc3760b42 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -435,7 +435,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is } } else { - /* Note, this is an exceptional case, we could even remove it + /* NOTE: this is an exceptional case, we could even remove it * however there have been reports of tooltips failing, so keep it for now. */ expr_result = BLI_strdup(IFACE_("Internal error!")); is_error = true; @@ -492,7 +492,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is } } else { - /* Note, this is an exceptional case, we could even remove it + /* NOTE: this is an exceptional case, we could even remove it * however there have been reports of tooltips failing, so keep it for now. */ expr_result = BLI_strdup(TIP_("Internal error!")); is_error = true; @@ -574,7 +574,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is shortcut_toolbar, ARRAY_SIZE(shortcut_toolbar))) { /* Generate keymap in order to inspect it. - * Note, we could make a utility to avoid the keymap generation part of this. */ + * NOTE: we could make a utility to avoid the keymap generation part of this. */ const char *expr_imports[] = { "bpy", "bl_keymap_utils", "bl_keymap_utils.keymap_from_toolbar", NULL}; const char *expr = diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc new file mode 100644 index 00000000000..5a05813f947 --- /dev/null +++ b/source/blender/editors/interface/interface_template_asset_view.cc @@ -0,0 +1,272 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edinterface + */ + +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" + +#include "BKE_screen.h" + +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_string_ref.hh" + +#include "BLO_readfile.h" + +#include "ED_asset.h" +#include "ED_screen.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "UI_interface.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "interface_intern.h" + +struct AssetViewListData { + AssetLibraryReference asset_library; + bScreen *screen; +}; + +static void asset_view_item_but_drag_set(uiBut *but, + AssetViewListData *list_data, + AssetHandle *asset_handle) +{ + ID *id = asset_handle->file_data->id; + if (id != nullptr) { + UI_but_drag_set_id(but, id); + return; + } + + const blender::StringRef asset_list_path = ED_assetlist_library_path(&list_data->asset_library); + char blend_path[FILE_MAX_LIBEXTRA]; + + char path[FILE_MAX_LIBEXTRA]; + BLI_join_dirfile(path, sizeof(path), asset_list_path.data(), asset_handle->file_data->relpath); + if (BLO_library_path_explode(path, blend_path, nullptr, nullptr)) { + ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle); + UI_but_drag_set_asset(but, + asset_handle->file_data->name, + BLI_strdup(blend_path), + asset_handle->file_data->blentype, + FILE_ASSET_IMPORT_APPEND, + asset_handle->file_data->preview_icon_id, + imbuf, + 1.0f); + } +} + +static void asset_view_draw_item(uiList *ui_list, + bContext *UNUSED(C), + uiLayout *layout, + PointerRNA *UNUSED(dataptr), + PointerRNA *itemptr, + int UNUSED(icon), + PointerRNA *UNUSED(active_dataptr), + const char *UNUSED(active_propname), + int UNUSED(index), + int UNUSED(flt_flag)) +{ + AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata; + + BLI_assert(RNA_struct_is_a(itemptr->type, &RNA_AssetHandle)); + AssetHandle *asset_handle = (AssetHandle *)itemptr->data; + + uiLayoutSetContextPointer(layout, "asset_handle", itemptr); + + uiBlock *block = uiLayoutGetBlock(layout); + /* TODO ED_fileselect_init_layout(). Share somehow? */ + const float size_x = (96.0f / 20.0f) * UI_UNIT_X; + const float size_y = (96.0f / 20.0f) * UI_UNIT_Y; + uiBut *but = uiDefIconTextBut(block, + UI_BTYPE_PREVIEW_TILE, + 0, + asset_handle->file_data->preview_icon_id, + asset_handle->file_data->name, + 0, + 0, + size_x, + size_y, + nullptr, + 0, + 0, + 0, + 0, + ""); + ui_def_but_icon(but, + asset_handle->file_data->preview_icon_id, + /* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */ + UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + if (!ui_list->dyn_data->custom_drag_optype) { + asset_view_item_but_drag_set(but, list_data, asset_handle); + } +} + +static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params) +{ + AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata; + const wmNotifier *notifier = params->notifier; + + switch (notifier->category) { + case NC_ID: { + if (ELEM(notifier->action, NA_RENAME)) { + ED_assetlist_storage_tag_main_data_dirty(); + } + break; + } + } + + if (ED_assetlist_listen(&list_data->asset_library, params->notifier)) { + ED_region_tag_redraw(params->region); + } +} + +uiListType *UI_UL_asset_view() +{ + uiListType *list_type = (uiListType *)MEM_callocN(sizeof(*list_type), __func__); + + BLI_strncpy(list_type->idname, "UI_UL_asset_view", sizeof(list_type->idname)); + list_type->draw_item = asset_view_draw_item; + list_type->listener = asset_view_listener; + + return list_type; +} + +static void asset_view_template_refresh_asset_collection( + const AssetLibraryReference &asset_library, + PointerRNA &assets_dataptr, + const char *assets_propname) +{ + PropertyRNA *assets_prop = RNA_struct_find_property(&assets_dataptr, assets_propname); + if (!assets_prop) { + RNA_warning("Asset collection not found"); + return; + } + if (!RNA_struct_is_a(RNA_property_pointer_type(&assets_dataptr, assets_prop), + &RNA_AssetHandle)) { + RNA_warning("Expected a collection property for AssetHandle items"); + return; + } + + RNA_property_collection_clear(&assets_dataptr, assets_prop); + + ED_assetlist_iterate(&asset_library, [&](FileDirEntry &file) { + PointerRNA itemptr, fileptr; + RNA_property_collection_add(&assets_dataptr, assets_prop, &itemptr); + + RNA_pointer_create(nullptr, &RNA_FileSelectEntry, &file, &fileptr); + RNA_pointer_set(&itemptr, "file_data", fileptr); + + /* Copy name from file to asset-handle name ID-property. */ + char name[MAX_NAME]; + PropertyRNA *file_name_prop = RNA_struct_name_property(fileptr.type); + RNA_property_string_get(&fileptr, file_name_prop, name); + PropertyRNA *asset_name_prop = RNA_struct_name_property(&RNA_AssetHandle); + RNA_property_string_set(&itemptr, asset_name_prop, name); + + return true; + }); +} + +void uiTemplateAssetView(uiLayout *layout, + bContext *C, + const char *list_id, + PointerRNA *asset_library_dataptr, + const char *asset_library_propname, + PointerRNA *assets_dataptr, + const char *assets_propname, + PointerRNA *active_dataptr, + const char *active_propname, + const AssetFilterSettings *filter_settings, + const char *activate_opname, + PointerRNA *r_activate_op_properties, + const char *drag_opname, + PointerRNA *r_drag_op_properties) +{ + if (!list_id || !list_id[0]) { + RNA_warning("Asset view needs a valid identifier"); + return; + } + + uiLayout *col = uiLayoutColumn(layout, false); + + PropertyRNA *asset_library_prop = RNA_struct_find_property(asset_library_dataptr, + asset_library_propname); + AssetLibraryReference asset_library = ED_asset_library_reference_from_enum_value( + RNA_property_enum_get(asset_library_dataptr, asset_library_prop)); + + uiLayout *row = uiLayoutRow(col, true); + uiItemFullR(row, asset_library_dataptr, asset_library_prop, RNA_NO_INDEX, 0, 0, "", 0); + if (asset_library.type != ASSET_LIBRARY_LOCAL) { + uiItemO(row, "", ICON_FILE_REFRESH, "ASSET_OT_list_refresh"); + } + + ED_assetlist_storage_fetch(&asset_library, filter_settings, C); + ED_assetlist_ensure_previews_job(&asset_library, C); + const int tot_items = ED_assetlist_size(&asset_library); + + asset_view_template_refresh_asset_collection(asset_library, *assets_dataptr, assets_propname); + + AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data), + "AssetViewListData"); + list_data->asset_library = asset_library; + list_data->screen = CTX_wm_screen(C); + + /* TODO can we have some kind of model-view API to handle referencing, filtering and lazy loading + * (of previews) of the items? */ + uiList *list = uiTemplateList_ex(col, + C, + "UI_UL_asset_view", + list_id, + assets_dataptr, + assets_propname, + active_dataptr, + active_propname, + nullptr, + tot_items, + 0, + UILST_LAYOUT_BIG_PREVIEW_GRID, + 0, + UI_TEMPLATE_LIST_NO_GRIP, + list_data); + if (!list) { + /* List creation failed. */ + MEM_freeN(list_data); + return; + } + + if (activate_opname) { + PointerRNA *ptr = UI_list_custom_activate_operator_set( + list, activate_opname, r_activate_op_properties != nullptr); + if (r_activate_op_properties && ptr) { + *r_activate_op_properties = *ptr; + } + } + if (drag_opname) { + PointerRNA *ptr = UI_list_custom_drag_operator_set( + list, drag_opname, r_drag_op_properties != nullptr); + if (r_drag_op_properties && ptr) { + *r_drag_op_properties = *ptr; + } + } +} diff --git a/source/blender/editors/interface/interface_template_list.cc b/source/blender/editors/interface/interface_template_list.cc new file mode 100644 index 00000000000..eaab33e32c9 --- /dev/null +++ b/source/blender/editors/interface/interface_template_list.cc @@ -0,0 +1,1310 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edinterface + */ + +#include <cstdlib> +#include <cstring> + +#include "BLI_fnmatch.h" +#include "BLI_listbase.h" +#include "BLI_math_base.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BKE_screen.h" + +#include "BLT_translation.h" + +#include "ED_screen.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "UI_interface.h" +#include "UI_view2d.h" + +#include "WM_api.h" + +#include "interface_intern.h" + +/** + * The validated data that was passed to #uiTemplateList (typically through Python). + * Populated through #ui_template_list_data_retrieve(). + */ +struct TemplateListInputData { + PointerRNA dataptr; + PropertyRNA *prop; + PointerRNA active_dataptr; + PropertyRNA *activeprop; + const char *item_dyntip_propname; + + /* Index as stored in the input property. I.e. the index before sorting. */ + int active_item_idx; +}; + +/** + * Internal wrapper for a single item in the list (well, actually stored as a vector). + */ +struct _uilist_item { + PointerRNA item; + int org_idx; + int flt_flag; +}; + +/** + * Container for the item vector and additional info. + */ +struct TemplateListItems { + _uilist_item *item_vec; + /* Index of the active item following visual order. I.e. unlike + * TemplateListInputData.active_item_idx, this is the index after sorting. */ + int active_item_idx; + int tot_items; +}; + +struct TemplateListLayoutDrawData { + uiListDrawItemFunc draw_item; + uiListDrawFilterFunc draw_filter; + + int rows; + int maxrows; + int columns; +}; + +struct TemplateListVisualInfo { + int visual_items; /* Visual number of items (i.e. number of items we have room to display). */ + int start_idx; /* Index of first item to display. */ + int end_idx; /* Index of last item to display + 1. */ +}; + +static void uilist_draw_item_default(struct uiList *ui_list, + struct bContext *UNUSED(C), + struct uiLayout *layout, + struct PointerRNA *UNUSED(dataptr), + struct PointerRNA *itemptr, + int icon, + struct PointerRNA *UNUSED(active_dataptr), + const char *UNUSED(active_propname), + int UNUSED(index), + int UNUSED(flt_flag)) +{ + PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type); + + /* Simplest one! */ + switch (ui_list->layout_type) { + case UILST_LAYOUT_GRID: + uiItemL(layout, "", icon); + break; + case UILST_LAYOUT_DEFAULT: + case UILST_LAYOUT_COMPACT: + default: + if (nameprop) { + uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon); + } + else { + uiItemL(layout, "", icon); + } + break; + } +} + +static void uilist_draw_filter_default(struct uiList *ui_list, + struct bContext *UNUSED(C), + struct uiLayout *layout) +{ + PointerRNA listptr; + RNA_pointer_create(nullptr, &RNA_UIList, ui_list, &listptr); + + uiLayout *row = uiLayoutRow(layout, false); + + uiLayout *subrow = uiLayoutRow(row, true); + uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE); + uiItemR(subrow, + &listptr, + "use_filter_invert", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_ARROW_LEFTRIGHT); + + if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) { + subrow = uiLayoutRow(row, true); + uiItemR(subrow, + &listptr, + "use_filter_sort_alpha", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_NONE); + uiItemR(subrow, + &listptr, + "use_filter_sort_reverse", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC); + } +} + +struct StringCmp { + char name[MAX_IDPROP_NAME]; + int org_idx; +}; + +static int cmpstringp(const void *p1, const void *p2) +{ + /* Case-insensitive comparison. */ + return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name); +} + +static void uilist_filter_items_default(struct uiList *ui_list, + struct bContext *UNUSED(C), + struct PointerRNA *dataptr, + const char *propname) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + PropertyRNA *prop = RNA_struct_find_property(dataptr, propname); + + const char *filter_raw = ui_list->filter_byname; + char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = nullptr; + const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0; + const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) == + UILST_FLT_SORT_ALPHA; + const int len = RNA_property_collection_length(dataptr, prop); + + dyn_data->items_shown = dyn_data->items_len = len; + + if (len && (order_by_name || filter_raw[0])) { + StringCmp *names = nullptr; + int order_idx = 0, i = 0; + + if (order_by_name) { + names = static_cast<StringCmp *>(MEM_callocN(sizeof(StringCmp) * len, "StringCmp")); + } + if (filter_raw[0]) { + const size_t slen = strlen(filter_raw); + + dyn_data->items_filter_flags = static_cast<int *>( + MEM_callocN(sizeof(int) * len, "items_filter_flags")); + dyn_data->items_shown = 0; + + /* Implicitly add heading/trailing wildcards if needed. */ + if (slen + 3 <= sizeof(filter_buff)) { + filter = filter_buff; + } + else { + filter = filter_dyn = static_cast<char *>( + MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn")); + } + BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3); + } + + RNA_PROP_BEGIN (dataptr, itemptr, prop) { + bool do_order = false; + + char *namebuf = RNA_struct_name_get_alloc(&itemptr, nullptr, 0, nullptr); + const char *name = namebuf ? namebuf : ""; + + if (filter[0]) { + /* Case-insensitive! */ + if (fnmatch(filter, name, FNM_CASEFOLD) == 0) { + dyn_data->items_filter_flags[i] = UILST_FLT_ITEM; + if (!filter_exclude) { + dyn_data->items_shown++; + do_order = order_by_name; + } + // printf("%s: '%s' matches '%s'\n", __func__, name, filter); + } + else if (filter_exclude) { + dyn_data->items_shown++; + do_order = order_by_name; + } + } + else { + do_order = order_by_name; + } + + if (do_order) { + names[order_idx].org_idx = order_idx; + BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME); + } + + /* free name */ + if (namebuf) { + MEM_freeN(namebuf); + } + i++; + } + RNA_PROP_END; + + if (order_by_name) { + int new_idx; + /* NOTE: order_idx equals either to ui_list->items_len if no filtering done, + * or to ui_list->items_shown if filter is enabled, + * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded. + * This way, we only sort items we actually intend to draw! + */ + qsort(names, order_idx, sizeof(StringCmp), cmpstringp); + + dyn_data->items_filter_neworder = static_cast<int *>( + MEM_mallocN(sizeof(int) * order_idx, "items_filter_neworder")); + for (new_idx = 0; new_idx < order_idx; new_idx++) { + dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx; + } + } + + if (filter_dyn) { + MEM_freeN(filter_dyn); + } + if (names) { + MEM_freeN(names); + } + } +} + +static void uilist_free_dyn_data(uiList *ui_list) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + if (!dyn_data) { + return; + } + + if (dyn_data->custom_activate_opptr) { + WM_operator_properties_free(dyn_data->custom_activate_opptr); + MEM_freeN(dyn_data->custom_activate_opptr); + } + if (dyn_data->custom_drag_opptr) { + WM_operator_properties_free(dyn_data->custom_drag_opptr); + MEM_freeN(dyn_data->custom_drag_opptr); + } + + MEM_SAFE_FREE(dyn_data->items_filter_flags); + MEM_SAFE_FREE(dyn_data->items_filter_neworder); + MEM_SAFE_FREE(dyn_data->customdata); +} + +/** + * Validate input parameters and initialize \a r_data from that. Plus find the list-type and return + * it in \a r_list_type. + * + * \return false if the input data isn't valid. Will also raise an RNA warning in that case. + */ +static bool ui_template_list_data_retrieve(const char *listtype_name, + const char *list_id, + PointerRNA *dataptr, + const char *propname, + PointerRNA *active_dataptr, + const char *active_propname, + const char *item_dyntip_propname, + TemplateListInputData *r_input_data, + uiListType **r_list_type) +{ + memset(r_input_data, 0, sizeof(*r_input_data)); + + /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */ + if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) { + RNA_warning("template_list using default '%s' UIList class must provide a custom list_id", + UI_UL_DEFAULT_CLASS_NAME); + return false; + } + + if (!active_dataptr->data) { + RNA_warning("No active data"); + return false; + } + + r_input_data->dataptr = *dataptr; + if (dataptr->data) { + r_input_data->prop = RNA_struct_find_property(dataptr, propname); + if (!r_input_data->prop) { + RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname); + return false; + } + } + + r_input_data->active_dataptr = *active_dataptr; + r_input_data->activeprop = RNA_struct_find_property(active_dataptr, active_propname); + if (!r_input_data->activeprop) { + RNA_warning( + "Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname); + return false; + } + + if (r_input_data->prop) { + const PropertyType type = RNA_property_type(r_input_data->prop); + if (type != PROP_COLLECTION) { + RNA_warning("Expected a collection data property"); + return false; + } + } + + const PropertyType activetype = RNA_property_type(r_input_data->activeprop); + if (activetype != PROP_INT) { + RNA_warning("Expected an integer active data property"); + return false; + } + + /* Find the uiList type. */ + if (!(*r_list_type = WM_uilisttype_find(listtype_name, false))) { + RNA_warning("List type %s not found", listtype_name); + return false; + } + + r_input_data->active_item_idx = RNA_property_int_get(&r_input_data->active_dataptr, + r_input_data->activeprop); + r_input_data->item_dyntip_propname = item_dyntip_propname; + + return true; +} + +static void ui_template_list_collect_items(PointerRNA *list_ptr, + PropertyRNA *list_prop, + uiListDyn *dyn_data, + int filter_exclude, + bool order_reverse, + int activei, + TemplateListItems *r_items) +{ + int i = 0; + int reorder_i = 0; + bool activei_mapping_pending = true; + + RNA_PROP_BEGIN (list_ptr, itemptr, list_prop) { + if (!dyn_data->items_filter_flags || + ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) { + int new_order_idx; + if (dyn_data->items_filter_neworder) { + new_order_idx = dyn_data->items_filter_neworder[reorder_i++]; + new_order_idx = order_reverse ? dyn_data->items_shown - new_order_idx - 1 : new_order_idx; + } + else { + new_order_idx = order_reverse ? dyn_data->items_shown - ++reorder_i : reorder_i++; + } + // printf("%s: ii: %d\n", __func__, ii); + r_items->item_vec[new_order_idx].item = itemptr; + r_items->item_vec[new_order_idx].org_idx = i; + r_items->item_vec[new_order_idx].flt_flag = dyn_data->items_filter_flags ? + dyn_data->items_filter_flags[i] : + 0; + + if (activei_mapping_pending && activei == i) { + activei = new_order_idx; + /* So that we do not map again activei! */ + activei_mapping_pending = false; + } +#if 0 /* For now, do not alter active element, even if it will be hidden... */ + else if (activei < i) { + /* We do not want an active but invisible item! + * Only exception is when all items are filtered out... + */ + if (prev_order_idx >= 0) { + activei = prev_order_idx; + RNA_property_int_set(active_dataptr, activeprop, prev_i); + } + else { + activei = new_order_idx; + RNA_property_int_set(active_dataptr, activeprop, i); + } + } + prev_i = i; + prev_ii = new_order_idx; +#endif + } + i++; + } + RNA_PROP_END; + + /* If mapping is still pending, no active item was found. Mark as invalid (-1) */ + r_items->active_item_idx = activei_mapping_pending ? -1 : activei; +} + +/** + * Create the UI-list representation of the list items, sorted and filtered if needed. + */ +static void ui_template_list_collect_display_items(bContext *C, + uiList *ui_list, + TemplateListInputData *input_data, + const uiListFilterItemsFunc filter_items_fn, + TemplateListItems *r_items) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + memset(r_items, 0, sizeof(*r_items)); + + /* Filter list items! (not for compact layout, though) */ + if (input_data->dataptr.data && input_data->prop) { + const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; + const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0; + int items_shown; +#if 0 + int prev_ii = -1, prev_i; +#endif + + if (ui_list->layout_type == UILST_LAYOUT_COMPACT) { + dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length( + &input_data->dataptr, input_data->prop); + } + else { + // printf("%s: filtering...\n", __func__); + filter_items_fn(ui_list, C, &input_data->dataptr, RNA_property_identifier(input_data->prop)); + // printf("%s: filtering done.\n", __func__); + } + + items_shown = dyn_data->items_shown; + if (items_shown >= 0) { + r_items->item_vec = static_cast<_uilist_item *>( + MEM_mallocN(sizeof(*r_items->item_vec) * items_shown, __func__)); + // printf("%s: items shown: %d.\n", __func__, items_shown); + + ui_template_list_collect_items(&input_data->dataptr, + input_data->prop, + dyn_data, + filter_exclude, + order_reverse, + input_data->active_item_idx, + r_items); + } + if (dyn_data->items_shown >= 0) { + r_items->tot_items = dyn_data->items_shown; + } + else { + r_items->tot_items = dyn_data->items_len; + } + } +} + +static void ui_template_list_free_items(TemplateListItems *items) +{ + if (items->item_vec) { + MEM_freeN(items->item_vec); + } +} + +static void uilist_prepare(uiList *ui_list, + const TemplateListItems *items, + const TemplateListLayoutDrawData *layout_data, + TemplateListVisualInfo *r_visual_info) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + const bool use_auto_size = (ui_list->list_grip < + (layout_data->rows - UI_LIST_AUTO_SIZE_THRESHOLD)); + + int actual_rows = layout_data->rows; + int actual_maxrows = layout_data->maxrows; + int columns = layout_data->columns; + + /* default rows */ + if (actual_rows <= 0) { + actual_rows = 5; + } + dyn_data->visual_height_min = actual_rows; + if (actual_maxrows < actual_rows) { + actual_maxrows = max_ii(actual_rows, 5); + } + if (columns <= 0) { + columns = 9; + } + + int activei_row; + if (columns > 1) { + dyn_data->height = (int)ceil((double)items->tot_items / (double)columns); + activei_row = (int)floor((double)items->active_item_idx / (double)columns); + } + else { + dyn_data->height = items->tot_items; + activei_row = items->active_item_idx; + } + + dyn_data->columns = columns; + + if (!use_auto_size) { + /* No auto-size, yet we clamp at min size! */ + actual_rows = max_ii(ui_list->list_grip, actual_rows); + } + else if ((actual_rows != actual_maxrows) && (dyn_data->height > actual_rows)) { + /* Expand size if needed and possible. */ + actual_rows = min_ii(dyn_data->height, actual_maxrows); + } + + /* If list length changes or list is tagged to check this, + * and active is out of view, scroll to it. */ + if ((ui_list->list_last_len != items->tot_items) || + (ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM)) { + if (activei_row < ui_list->list_scroll) { + ui_list->list_scroll = activei_row; + } + else if (activei_row >= ui_list->list_scroll + actual_rows) { + ui_list->list_scroll = activei_row - actual_rows + 1; + } + ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM; + } + + const int max_scroll = max_ii(0, dyn_data->height - actual_rows); + CLAMP(ui_list->list_scroll, 0, max_scroll); + ui_list->list_last_len = items->tot_items; + dyn_data->visual_height = actual_rows; + r_visual_info->visual_items = actual_rows * columns; + r_visual_info->start_idx = ui_list->list_scroll * columns; + r_visual_info->end_idx = min_ii(r_visual_info->start_idx + actual_rows * columns, + items->tot_items); +} + +static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiList *ui_list = static_cast<uiList *>(arg1); + uiListDyn *dyn_data = ui_list->dyn_data; + + /* This way we get diff in number of additional items to show (positive) or hide (negative). */ + const int diff = round_fl_to_int((float)(dyn_data->resize - dyn_data->resize_prev) / + (float)UI_UNIT_Y); + + if (diff != 0) { + ui_list->list_grip += diff; + dyn_data->resize_prev += diff * UI_UNIT_Y; + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + } + + /* In case uilist is in popup, we need special refreshing */ + ED_region_tag_refresh_ui(CTX_wm_menu(C)); +} + +static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname) +{ + if (propname && propname[0] && itemptr && itemptr->data) { + PropertyRNA *prop = RNA_struct_find_property(itemptr, propname); + + if (prop && (RNA_property_type(prop) == PROP_STRING)) { + return RNA_property_string_get_alloc(itemptr, prop, nullptr, 0, nullptr); + } + } + return nullptr; +} + +static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const char *tip) +{ + char *dyn_tooltip = static_cast<char *>(argN); + return BLI_sprintfN("%s - %s", tip, dyn_tooltip); +} + +/** + * \note Note that \a layout_type may be null. + */ +static uiList *ui_list_ensure(bContext *C, + uiListType *ui_list_type, + const char *list_id, + int layout_type, + bool sort_reverse, + bool sort_lock) +{ + /* Allows to work in popups. */ + ARegion *region = CTX_wm_menu(C); + if (region == nullptr) { + region = CTX_wm_region(C); + } + + /* Find or add the uiList to the current Region. */ + + char full_list_id[UI_MAX_NAME_STR]; + WM_uilisttype_to_full_list_id(ui_list_type, list_id, full_list_id); + + uiList *ui_list = static_cast<uiList *>( + BLI_findstring(®ion->ui_lists, full_list_id, offsetof(uiList, list_id))); + + if (!ui_list) { + ui_list = static_cast<uiList *>(MEM_callocN(sizeof(uiList), "uiList")); + BLI_strncpy(ui_list->list_id, full_list_id, sizeof(ui_list->list_id)); + BLI_addtail(®ion->ui_lists, ui_list); + ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */ + if (sort_reverse) { + ui_list->filter_sort_flag |= UILST_FLT_SORT_REVERSE; + } + if (sort_lock) { + ui_list->filter_sort_flag |= UILST_FLT_SORT_LOCK; + } + } + + if (!ui_list->dyn_data) { + ui_list->dyn_data = static_cast<uiListDyn *>( + MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data")); + } + uiListDyn *dyn_data = ui_list->dyn_data; + /* Note that this isn't a `uiListType` callback, it's stored in the runtime list data. Otherwise + * the runtime data could leak when the type is unregistered (e.g. on "Reload Scripts"). */ + dyn_data->free_runtime_data_fn = uilist_free_dyn_data; + + /* Because we can't actually pass type across save&load... */ + ui_list->type = ui_list_type; + ui_list->layout_type = layout_type; + + /* Reset filtering data. */ + MEM_SAFE_FREE(dyn_data->items_filter_flags); + MEM_SAFE_FREE(dyn_data->items_filter_neworder); + dyn_data->items_len = dyn_data->items_shown = -1; + + return ui_list; +} + +static void ui_template_list_layout_draw(bContext *C, + uiList *ui_list, + uiLayout *layout, + TemplateListInputData *input_data, + TemplateListItems *items, + const TemplateListLayoutDrawData *layout_data, + const enum uiTemplateListFlags flags) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + const char *active_propname = RNA_property_identifier(input_data->activeprop); + + uiLayout *glob = nullptr, *box, *row, *col, *subrow, *sub, *overlap; + char numstr[32]; + int rnaicon = ICON_NONE, icon = ICON_NONE; + uiBut *but; + + uiBlock *block = uiLayoutGetBlock(layout); + + /* get icon */ + if (input_data->dataptr.data && input_data->prop) { + StructRNA *ptype = RNA_property_pointer_type(&input_data->dataptr, input_data->prop); + rnaicon = RNA_struct_ui_icon(ptype); + } + + TemplateListVisualInfo visual_info; + switch (ui_list->layout_type) { + case UILST_LAYOUT_DEFAULT: { + /* layout */ + box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop); + glob = uiLayoutColumn(box, true); + row = uiLayoutRow(glob, false); + col = uiLayoutColumn(row, true); + + TemplateListLayoutDrawData adjusted_layout_data = *layout_data; + adjusted_layout_data.columns = 1; + /* init numbers */ + uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info); + + int i = 0; + if (input_data->dataptr.data && input_data->prop) { + /* create list items */ + for (i = visual_info.start_idx; i < visual_info.end_idx; i++) { + PointerRNA *itemptr = &items->item_vec[i].item; + void *dyntip_data; + const int org_i = items->item_vec[i].org_idx; + const int flt_flag = items->item_vec[i].flt_flag; + uiBlock *subblock = uiLayoutGetBlock(col); + + overlap = uiLayoutOverlap(col); + + UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM); + + /* list item behind label & other buttons */ + uiLayoutRow(overlap, false); + + but = uiDefButR_prop(subblock, + UI_BTYPE_LISTROW, + 0, + "", + 0, + 0, + UI_UNIT_X * 10, + UI_UNIT_Y, + &input_data->active_dataptr, + input_data->activeprop, + 0, + 0, + org_i, + 0, + 0, + TIP_("Double click to rename")); + if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr, + input_data->item_dyntip_propname))) { + UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data, MEM_freeN); + } + + sub = uiLayoutRow(overlap, false); + + icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false); + if (icon == ICON_DOT) { + icon = ICON_NONE; + } + layout_data->draw_item(ui_list, + C, + sub, + &input_data->dataptr, + itemptr, + icon, + &input_data->active_dataptr, + active_propname, + org_i, + flt_flag); + + /* Items should be able to set context pointers for the layout. But the list-row button + * swallows events, so it needs the context storage too for handlers to see it. */ + but->context = uiLayoutGetContextStore(sub); + + /* If we are "drawing" active item, set all labels as active. */ + if (i == items->active_item_idx) { + ui_layout_list_set_labels_active(sub); + } + + UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM); + } + } + + /* add dummy buttons to fill space */ + for (; i < visual_info.start_idx + visual_info.visual_items; i++) { + uiItemL(col, "", ICON_NONE); + } + + /* add scrollbar */ + if (items->tot_items > visual_info.visual_items) { + uiLayoutColumn(row, false); + uiDefButI(block, + UI_BTYPE_SCROLL, + 0, + "", + 0, + 0, + V2D_SCROLL_WIDTH, + UI_UNIT_Y * dyn_data->visual_height, + &ui_list->list_scroll, + 0, + dyn_data->height - dyn_data->visual_height, + dyn_data->visual_height, + 0, + ""); + } + } break; + case UILST_LAYOUT_COMPACT: + row = uiLayoutRow(layout, true); + + if ((input_data->dataptr.data && input_data->prop) && (dyn_data->items_shown > 0) && + (items->active_item_idx >= 0) && (items->active_item_idx < dyn_data->items_shown)) { + PointerRNA *itemptr = &items->item_vec[items->active_item_idx].item; + const int org_i = items->item_vec[items->active_item_idx].org_idx; + + icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false); + if (icon == ICON_DOT) { + icon = ICON_NONE; + } + layout_data->draw_item(ui_list, + C, + row, + &input_data->dataptr, + itemptr, + icon, + &input_data->active_dataptr, + active_propname, + org_i, + 0); + } + /* if list is empty, add in dummy button */ + else { + uiItemL(row, "", ICON_NONE); + } + + /* next/prev button */ + BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown); + but = uiDefIconTextButR_prop(block, + UI_BTYPE_NUM, + 0, + 0, + numstr, + 0, + 0, + UI_UNIT_X * 5, + UI_UNIT_Y, + &input_data->active_dataptr, + input_data->activeprop, + 0, + 0, + 0, + 0, + 0, + ""); + if (dyn_data->items_shown == 0) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + break; + case UILST_LAYOUT_GRID: { + box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop); + glob = uiLayoutColumn(box, true); + row = uiLayoutRow(glob, false); + col = uiLayoutColumn(row, true); + subrow = nullptr; /* Quite gcc warning! */ + + uilist_prepare(ui_list, items, layout_data, &visual_info); + + int i = 0; + if (input_data->dataptr.data && input_data->prop) { + /* create list items */ + for (i = visual_info.start_idx; i < visual_info.end_idx; i++) { + PointerRNA *itemptr = &items->item_vec[i].item; + const int org_i = items->item_vec[i].org_idx; + const int flt_flag = items->item_vec[i].flt_flag; + + /* create button */ + if (!(i % layout_data->columns)) { + subrow = uiLayoutRow(col, false); + } + + uiBlock *subblock = uiLayoutGetBlock(subrow); + overlap = uiLayoutOverlap(subrow); + + UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM); + + /* list item behind label & other buttons */ + uiLayoutRow(overlap, false); + + but = uiDefButR_prop(subblock, + UI_BTYPE_LISTROW, + 0, + "", + 0, + 0, + UI_UNIT_X * 10, + UI_UNIT_Y, + &input_data->active_dataptr, + input_data->activeprop, + 0, + 0, + org_i, + 0, + 0, + nullptr); + UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP); + + sub = uiLayoutRow(overlap, false); + + icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false); + layout_data->draw_item(ui_list, + C, + sub, + &input_data->dataptr, + itemptr, + icon, + &input_data->active_dataptr, + active_propname, + org_i, + flt_flag); + + /* If we are "drawing" active item, set all labels as active. */ + if (i == items->active_item_idx) { + ui_layout_list_set_labels_active(sub); + } + + UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM); + } + } + + /* add dummy buttons to fill space */ + for (; i < visual_info.start_idx + visual_info.visual_items; i++) { + if (!(i % layout_data->columns)) { + subrow = uiLayoutRow(col, false); + } + uiItemL(subrow, "", ICON_NONE); + } + + /* add scrollbar */ + if (items->tot_items > visual_info.visual_items) { + /* col = */ uiLayoutColumn(row, false); + uiDefButI(block, + UI_BTYPE_SCROLL, + 0, + "", + 0, + 0, + V2D_SCROLL_WIDTH, + UI_UNIT_Y * dyn_data->visual_height, + &ui_list->list_scroll, + 0, + dyn_data->height - dyn_data->visual_height, + dyn_data->visual_height, + 0, + ""); + } + break; + } + case UILST_LAYOUT_BIG_PREVIEW_GRID: + box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop); + /* For grip button. */ + glob = uiLayoutColumn(box, true); + /* For scrollbar. */ + row = uiLayoutRow(glob, false); + + /* TODO ED_fileselect_init_layout(). Share somehow? */ + float size_x = (96.0f / 20.0f) * UI_UNIT_X; + float size_y = (96.0f / 20.0f) * UI_UNIT_Y; + + const int cols_per_row = MAX2((uiLayoutGetWidth(box) - V2D_SCROLL_WIDTH) / size_x, 1); + uiLayout *grid = uiLayoutGridFlow(row, true, cols_per_row, true, true, true); + + TemplateListLayoutDrawData adjusted_layout_data = *layout_data; + adjusted_layout_data.columns = cols_per_row; + uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info); + + if (input_data->dataptr.data && input_data->prop) { + /* create list items */ + for (int i = visual_info.start_idx; i < visual_info.end_idx; i++) { + PointerRNA *itemptr = &items->item_vec[i].item; + const int org_i = items->item_vec[i].org_idx; + const int flt_flag = items->item_vec[i].flt_flag; + + overlap = uiLayoutOverlap(grid); + col = uiLayoutColumn(overlap, false); + + uiBlock *subblock = uiLayoutGetBlock(col); + UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM); + + but = uiDefButR_prop(subblock, + UI_BTYPE_LISTROW, + 0, + "", + 0, + 0, + size_x, + size_y, + &input_data->active_dataptr, + input_data->activeprop, + 0, + 0, + org_i, + 0, + 0, + nullptr); + UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP); + + col = uiLayoutColumn(overlap, false); + + icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false); + layout_data->draw_item(ui_list, + C, + col, + &input_data->dataptr, + itemptr, + icon, + &input_data->active_dataptr, + active_propname, + org_i, + flt_flag); + + /* Items should be able to set context pointers for the layout. But the list-row button + * swallows events, so it needs the context storage too for handlers to see it. */ + but->context = uiLayoutGetContextStore(col); + + /* If we are "drawing" active item, set all labels as active. */ + if (i == items->active_item_idx) { + ui_layout_list_set_labels_active(col); + } + + UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM); + } + } + + if (items->tot_items > visual_info.visual_items) { + /* col = */ uiLayoutColumn(row, false); + uiDefButI(block, + UI_BTYPE_SCROLL, + 0, + "", + 0, + 0, + V2D_SCROLL_WIDTH, + size_y * dyn_data->visual_height, + &ui_list->list_scroll, + 0, + dyn_data->height - dyn_data->visual_height, + dyn_data->visual_height, + 0, + ""); + } + break; + } + + if (glob) { + const bool add_grip_but = (flags & UI_TEMPLATE_LIST_NO_GRIP) == 0; + + /* About #UI_BTYPE_GRIP drag-resize: + * We can't directly use results from a grip button, since we have a + * rather complex behavior here (sizing by discrete steps and, overall, auto-size feature). + * Since we *never* know whether we are grip-resizing or not + * (because there is no callback for when a button enters/leaves its "edit mode"), + * we use the fact that grip-controlled value (dyn_data->resize) is completely handled + * by the grip during the grab resize, so settings its value here has no effect at all. + * + * It is only meaningful when we are not resizing, + * in which case this gives us the correct "init drag" value. + * Note we cannot affect `dyn_data->resize_prev here`, + * since this value is not controlled by the grip! + */ + dyn_data->resize = dyn_data->resize_prev + + (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y; + + row = uiLayoutRow(glob, true); + uiBlock *subblock = uiLayoutGetBlock(row); + UI_block_emboss_set(subblock, UI_EMBOSS_NONE); + + if (ui_list->filter_flag & UILST_FLT_SHOW) { + but = uiDefIconButBitI(subblock, + UI_BTYPE_TOGGLE, + UILST_FLT_SHOW, + 0, + ICON_DISCLOSURE_TRI_DOWN, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y * 0.5f, + &(ui_list->filter_flag), + 0, + 0, + 0, + 0, + TIP_("Hide filtering options")); + UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + + if (add_grip_but) { + but = uiDefIconButI(subblock, + UI_BTYPE_GRIP, + 0, + ICON_GRIP, + 0, + 0, + UI_UNIT_X * 10.0f, + UI_UNIT_Y * 0.5f, + &dyn_data->resize, + 0.0, + 0.0, + 0, + 0, + ""); + UI_but_func_set(but, uilist_resize_update_cb, ui_list, nullptr); + } + + UI_block_emboss_set(subblock, UI_EMBOSS); + + col = uiLayoutColumn(glob, false); + subblock = uiLayoutGetBlock(col); + uiDefBut(subblock, + UI_BTYPE_SEPR, + 0, + "", + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y * 0.05f, + nullptr, + 0.0, + 0.0, + 0, + 0, + ""); + + layout_data->draw_filter(ui_list, C, col); + } + else { + but = uiDefIconButBitI(subblock, + UI_BTYPE_TOGGLE, + UILST_FLT_SHOW, + 0, + ICON_DISCLOSURE_TRI_RIGHT, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y * 0.5f, + &(ui_list->filter_flag), + 0, + 0, + 0, + 0, + TIP_("Show filtering options")); + UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + + if (add_grip_but) { + but = uiDefIconButI(subblock, + UI_BTYPE_GRIP, + 0, + ICON_GRIP, + 0, + 0, + UI_UNIT_X * 10.0f, + UI_UNIT_Y * 0.5f, + &dyn_data->resize, + 0.0, + 0.0, + 0, + 0, + ""); + UI_but_func_set(but, uilist_resize_update_cb, ui_list, nullptr); + } + + UI_block_emboss_set(subblock, UI_EMBOSS); + } + } +} + +uiList *uiTemplateList_ex(uiLayout *layout, + bContext *C, + const char *listtype_name, + const char *list_id, + PointerRNA *dataptr, + const char *propname, + PointerRNA *active_dataptr, + const char *active_propname, + const char *item_dyntip_propname, + int rows, + int maxrows, + int layout_type, + int columns, + enum uiTemplateListFlags flags, + void *customdata) +{ + TemplateListInputData input_data = {nullptr}; + uiListType *ui_list_type; + if (!ui_template_list_data_retrieve(listtype_name, + list_id, + dataptr, + propname, + active_dataptr, + active_propname, + item_dyntip_propname, + &input_data, + &ui_list_type)) { + return nullptr; + } + + uiListDrawItemFunc draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : + uilist_draw_item_default; + uiListDrawFilterFunc draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : + uilist_draw_filter_default; + uiListFilterItemsFunc filter_items = ui_list_type->filter_items ? ui_list_type->filter_items : + uilist_filter_items_default; + + uiList *ui_list = ui_list_ensure(C, + ui_list_type, + list_id, + layout_type, + flags & UI_TEMPLATE_LIST_SORT_REVERSE, + flags & UI_TEMPLATE_LIST_SORT_LOCK); + uiListDyn *dyn_data = ui_list->dyn_data; + + MEM_SAFE_FREE(dyn_data->customdata); + dyn_data->customdata = customdata; + + /* When active item changed since last draw, scroll to it. */ + if (input_data.active_item_idx != ui_list->list_last_activei) { + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ui_list->list_last_activei = input_data.active_item_idx; + } + + TemplateListItems items; + ui_template_list_collect_display_items(C, ui_list, &input_data, filter_items, &items); + + TemplateListLayoutDrawData layout_data; + layout_data.draw_item = draw_item; + layout_data.draw_filter = draw_filter; + layout_data.rows = rows; + layout_data.maxrows = maxrows; + layout_data.columns = columns; + + ui_template_list_layout_draw(C, ui_list, layout, &input_data, &items, &layout_data, flags); + + ui_template_list_free_items(&items); + + return ui_list; +} + +void uiTemplateList(uiLayout *layout, + bContext *C, + const char *listtype_name, + const char *list_id, + PointerRNA *dataptr, + const char *propname, + PointerRNA *active_dataptr, + const char *active_propname, + const char *item_dyntip_propname, + int rows, + int maxrows, + int layout_type, + int columns, + enum uiTemplateListFlags flags) +{ + uiTemplateList_ex(layout, + C, + listtype_name, + list_id, + dataptr, + propname, + active_dataptr, + active_propname, + item_dyntip_propname, + rows, + maxrows, + layout_type, + columns, + flags, + nullptr); +} + +/** + * \return: A RNA pointer for the operator properties. + */ +PointerRNA *UI_list_custom_activate_operator_set(uiList *ui_list, + const char *opname, + bool create_properties) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + dyn_data->custom_activate_optype = WM_operatortype_find(opname, false); + if (!dyn_data->custom_activate_optype) { + return nullptr; + } + + if (create_properties) { + WM_operator_properties_alloc(&dyn_data->custom_activate_opptr, nullptr, opname); + } + + return dyn_data->custom_activate_opptr; +} + +/** + * \return: A RNA pointer for the operator properties. + */ +PointerRNA *UI_list_custom_drag_operator_set(uiList *ui_list, + const char *opname, + bool create_properties) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + dyn_data->custom_drag_optype = WM_operatortype_find(opname, false); + if (!dyn_data->custom_drag_optype) { + return nullptr; + } + + if (create_properties) { + WM_operator_properties_alloc(&dyn_data->custom_drag_opptr, nullptr, opname); + } + + return dyn_data->custom_drag_opptr; +} + +/* -------------------------------------------------------------------- */ + +/** \name List-types Registration + * \{ */ + +void ED_uilisttypes_ui(void) +{ + WM_uilisttype_add(UI_UL_asset_view()); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 91ad6619889..3105891142f 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -873,7 +873,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create( /* Finally sort menu items. * - * Note: we might want to keep the in-menu order, for now sort all. */ + * NOTE: we might want to keep the in-menu order, for now sort all. */ BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full); BLI_ghash_free(menu_parent_map, NULL, NULL); @@ -1037,7 +1037,7 @@ static void menu_search_update_fn(const bContext *UNUSED(C), static bool ui_search_menu_create_context_menu(struct bContext *C, void *arg, void *active, - const struct wmEvent *UNUSED(event)) + const struct wmEvent *event) { struct MenuSearch_Data *data = arg; struct MenuSearch_Item *item = active; @@ -1058,7 +1058,7 @@ static bool ui_search_menu_create_context_menu(struct bContext *C, CTX_wm_region_set(C, item->wm_context->region); } - if (ui_popup_context_menu_for_button(C, but)) { + if (ui_popup_context_menu_for_button(C, but, event)) { has_menu = true; } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 5232d4310a3..766840909cc 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -877,7 +877,7 @@ static uiBut *template_id_def_new_but(uiBlock *block, BLT_I18NCONTEXT_ID_POINTCLOUD, BLT_I18NCONTEXT_ID_VOLUME, BLT_I18NCONTEXT_ID_SIMULATION, ); - /* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters, + /* NOTE: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters, * check the definition to see if a new call must be added when the limit * is exceeded. */ @@ -2399,8 +2399,8 @@ static eAutoPropButsReturn template_operator_property_buts_draw_single( op->type->ui((bContext *)C, op); op->layout = NULL; - /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could - * allow ot.ui callback to return this, but not needed right now. */ + /* #UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. + * We could allow #wmOperatorType.ui callback to return this, but not needed right now. */ } else { wmWindowManager *wm = CTX_wm_manager(C); @@ -2556,7 +2556,7 @@ void uiTemplateOperatorPropertyButs( wmWindowManager *wm = CTX_wm_manager(C); /* If there are only checkbox items, don't use split layout by default. It looks weird if the - * checkboxes only use half the width. */ + * check-boxes only use half the width. */ if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) { flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT; } @@ -4015,23 +4015,23 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) case UICURVE_FUNC_RESET_VIEW: BKE_curvemapping_reset_view(cumap); break; - case UICURVE_FUNC_HANDLE_VECTOR: /* set vector */ + case UICURVE_FUNC_HANDLE_VECTOR: /* Set vector. */ BKE_curvemap_handle_set(cuma, HD_VECT); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_HANDLE_AUTO: /* set auto */ + case UICURVE_FUNC_HANDLE_AUTO: /* Set auto. */ BKE_curvemap_handle_set(cuma, HD_AUTO); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* set auto-clamped */ + case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* Set auto-clamped. */ BKE_curvemap_handle_set(cuma, HD_AUTO_ANIM); BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */ + case UICURVE_FUNC_EXTEND_HOZ: /* Extend horizontal. */ cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; - case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */ + case UICURVE_FUNC_EXTEND_EXP: /* Extend extrapolate. */ cumap->flag |= CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; @@ -5645,887 +5645,6 @@ void uiTemplateLayers(uiLayout *layout, /** \} */ /* -------------------------------------------------------------------- */ -/** \name List Template - * \{ */ - -static void uilist_draw_item_default(struct uiList *ui_list, - struct bContext *UNUSED(C), - struct uiLayout *layout, - struct PointerRNA *UNUSED(dataptr), - struct PointerRNA *itemptr, - int icon, - struct PointerRNA *UNUSED(active_dataptr), - const char *UNUSED(active_propname), - int UNUSED(index), - int UNUSED(flt_flag)) -{ - PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type); - - /* Simplest one! */ - switch (ui_list->layout_type) { - case UILST_LAYOUT_GRID: - uiItemL(layout, "", icon); - break; - case UILST_LAYOUT_DEFAULT: - case UILST_LAYOUT_COMPACT: - default: - if (nameprop) { - uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon); - } - else { - uiItemL(layout, "", icon); - } - break; - } -} - -static void uilist_draw_filter_default(struct uiList *ui_list, - struct bContext *UNUSED(C), - struct uiLayout *layout) -{ - PointerRNA listptr; - RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr); - - uiLayout *row = uiLayoutRow(layout, false); - - uiLayout *subrow = uiLayoutRow(row, true); - uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE); - uiItemR(subrow, - &listptr, - "use_filter_invert", - UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, - "", - ICON_ARROW_LEFTRIGHT); - - if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) { - subrow = uiLayoutRow(row, true); - uiItemR(subrow, - &listptr, - "use_filter_sort_alpha", - UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, - "", - ICON_NONE); - uiItemR(subrow, - &listptr, - "use_filter_sort_reverse", - UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, - "", - (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC); - } -} - -typedef struct { - char name[MAX_IDPROP_NAME]; - int org_idx; -} StringCmp; - -static int cmpstringp(const void *p1, const void *p2) -{ - /* Case-insensitive comparison. */ - return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name); -} - -static void uilist_filter_items_default(struct uiList *ui_list, - struct bContext *UNUSED(C), - struct PointerRNA *dataptr, - const char *propname) -{ - uiListDyn *dyn_data = ui_list->dyn_data; - PropertyRNA *prop = RNA_struct_find_property(dataptr, propname); - - const char *filter_raw = ui_list->filter_byname; - char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL; - const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0; - const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) == - UILST_FLT_SORT_ALPHA; - const int len = RNA_property_collection_length(dataptr, prop); - - dyn_data->items_shown = dyn_data->items_len = len; - - if (len && (order_by_name || filter_raw[0])) { - StringCmp *names = NULL; - int order_idx = 0, i = 0; - - if (order_by_name) { - names = MEM_callocN(sizeof(StringCmp) * len, "StringCmp"); - } - if (filter_raw[0]) { - const size_t slen = strlen(filter_raw); - - dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, "items_filter_flags"); - dyn_data->items_shown = 0; - - /* Implicitly add heading/trailing wildcards if needed. */ - if (slen + 3 <= sizeof(filter_buff)) { - filter = filter_buff; - } - else { - filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn"); - } - BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3); - } - - RNA_PROP_BEGIN (dataptr, itemptr, prop) { - bool do_order = false; - - char *namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); - const char *name = namebuf ? namebuf : ""; - - if (filter[0]) { - /* Case-insensitive! */ - if (fnmatch(filter, name, FNM_CASEFOLD) == 0) { - dyn_data->items_filter_flags[i] = UILST_FLT_ITEM; - if (!filter_exclude) { - dyn_data->items_shown++; - do_order = order_by_name; - } - // printf("%s: '%s' matches '%s'\n", __func__, name, filter); - } - else if (filter_exclude) { - dyn_data->items_shown++; - do_order = order_by_name; - } - } - else { - do_order = order_by_name; - } - - if (do_order) { - names[order_idx].org_idx = order_idx; - BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME); - } - - /* free name */ - if (namebuf) { - MEM_freeN(namebuf); - } - i++; - } - RNA_PROP_END; - - if (order_by_name) { - int new_idx; - /* note: order_idx equals either to ui_list->items_len if no filtering done, - * or to ui_list->items_shown if filter is enabled, - * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded. - * This way, we only sort items we actually intend to draw! - */ - qsort(names, order_idx, sizeof(StringCmp), cmpstringp); - - dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx, - "items_filter_neworder"); - for (new_idx = 0; new_idx < order_idx; new_idx++) { - dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx; - } - } - - if (filter_dyn) { - MEM_freeN(filter_dyn); - } - if (names) { - MEM_freeN(names); - } - } -} - -typedef struct { - PointerRNA item; - int org_idx; - int flt_flag; -} _uilist_item; - -typedef struct { - int visual_items; /* Visual number of items (i.e. number of items we have room to display). */ - int start_idx; /* Index of first item to display. */ - int end_idx; /* Index of last item to display + 1. */ -} uiListLayoutdata; - -static void uilist_prepare(uiList *ui_list, - int len, - int activei, - int rows, - int maxrows, - int columns, - uiListLayoutdata *layoutdata) -{ - uiListDyn *dyn_data = ui_list->dyn_data; - const bool use_auto_size = (ui_list->list_grip < (rows - UI_LIST_AUTO_SIZE_THRESHOLD)); - - /* default rows */ - if (rows <= 0) { - rows = 5; - } - dyn_data->visual_height_min = rows; - if (maxrows < rows) { - maxrows = max_ii(rows, 5); - } - if (columns <= 0) { - columns = 9; - } - - int activei_row; - if (columns > 1) { - dyn_data->height = (int)ceil((double)len / (double)columns); - activei_row = (int)floor((double)activei / (double)columns); - } - else { - dyn_data->height = len; - activei_row = activei; - } - - if (!use_auto_size) { - /* No auto-size, yet we clamp at min size! */ - maxrows = rows = max_ii(ui_list->list_grip, rows); - } - else if ((rows != maxrows) && (dyn_data->height > rows)) { - /* Expand size if needed and possible. */ - rows = min_ii(dyn_data->height, maxrows); - } - - /* If list length changes or list is tagged to check this, - * and active is out of view, scroll to it. */ - if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) { - if (activei_row < ui_list->list_scroll) { - ui_list->list_scroll = activei_row; - } - else if (activei_row >= ui_list->list_scroll + rows) { - ui_list->list_scroll = activei_row - rows + 1; - } - ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM; - } - - const int max_scroll = max_ii(0, dyn_data->height - rows); - CLAMP(ui_list->list_scroll, 0, max_scroll); - ui_list->list_last_len = len; - dyn_data->visual_height = rows; - layoutdata->visual_items = rows * columns; - layoutdata->start_idx = ui_list->list_scroll * columns; - layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len); -} - -static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2)) -{ - uiList *ui_list = arg1; - uiListDyn *dyn_data = ui_list->dyn_data; - - /* This way we get diff in number of additional items to show (positive) or hide (negative). */ - const int diff = round_fl_to_int((float)(dyn_data->resize - dyn_data->resize_prev) / - (float)UI_UNIT_Y); - - if (diff != 0) { - ui_list->list_grip += diff; - dyn_data->resize_prev += diff * UI_UNIT_Y; - ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; - } - - /* In case uilist is in popup, we need special refreshing */ - ED_region_tag_refresh_ui(CTX_wm_menu(C)); -} - -static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname) -{ - if (propname && propname[0] && itemptr && itemptr->data) { - PropertyRNA *prop = RNA_struct_find_property(itemptr, propname); - - if (prop && (RNA_property_type(prop) == PROP_STRING)) { - return RNA_property_string_get_alloc(itemptr, prop, NULL, 0, NULL); - } - } - return NULL; -} - -static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const char *tip) -{ - char *dyn_tooltip = argN; - return BLI_sprintfN("%s - %s", tip, dyn_tooltip); -} - -void uiTemplateList(uiLayout *layout, - bContext *C, - const char *listtype_name, - const char *list_id, - PointerRNA *dataptr, - const char *propname, - PointerRNA *active_dataptr, - const char *active_propname, - const char *item_dyntip_propname, - int rows, - int maxrows, - int layout_type, - int columns, - bool sort_reverse, - bool sort_lock) -{ - PropertyRNA *prop = NULL, *activeprop; - _uilist_item *items_ptr = NULL; - uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap; - uiBut *but; - - uiListLayoutdata layoutdata; - char ui_list_id[UI_MAX_NAME_STR]; - char numstr[32]; - int rnaicon = ICON_NONE, icon = ICON_NONE; - int i = 0, activei = 0; - int len = 0; - - /* validate arguments */ - /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */ - if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) { - RNA_warning("template_list using default '%s' UIList class must provide a custom list_id", - UI_UL_DEFAULT_CLASS_NAME); - return; - } - - uiBlock *block = uiLayoutGetBlock(layout); - - if (!active_dataptr->data) { - RNA_warning("No active data"); - return; - } - - if (dataptr->data) { - prop = RNA_struct_find_property(dataptr, propname); - if (!prop) { - RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname); - return; - } - } - - activeprop = RNA_struct_find_property(active_dataptr, active_propname); - if (!activeprop) { - RNA_warning( - "Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname); - return; - } - - if (prop) { - const PropertyType type = RNA_property_type(prop); - if (type != PROP_COLLECTION) { - RNA_warning("Expected a collection data property"); - return; - } - } - - const PropertyType activetype = RNA_property_type(activeprop); - if (activetype != PROP_INT) { - RNA_warning("Expected an integer active data property"); - return; - } - - /* get icon */ - if (dataptr->data && prop) { - StructRNA *ptype = RNA_property_pointer_type(dataptr, prop); - rnaicon = RNA_struct_ui_icon(ptype); - } - - /* get active data */ - activei = RNA_property_int_get(active_dataptr, activeprop); - - /* Find the uiList type. */ - uiListType *ui_list_type = WM_uilisttype_find(listtype_name, false); - - if (ui_list_type == NULL) { - RNA_warning("List type %s not found", listtype_name); - return; - } - - uiListDrawItemFunc draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : - uilist_draw_item_default; - uiListDrawFilterFunc draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : - uilist_draw_filter_default; - uiListFilterItemsFunc filter_items = ui_list_type->filter_items ? ui_list_type->filter_items : - uilist_filter_items_default; - - /* Find or add the uiList to the current Region. */ - /* We tag the list id with the list type... */ - BLI_snprintf( - ui_list_id, sizeof(ui_list_id), "%s_%s", ui_list_type->idname, list_id ? list_id : ""); - - /* Allows to work in popups. */ - ARegion *region = CTX_wm_menu(C); - if (region == NULL) { - region = CTX_wm_region(C); - } - uiList *ui_list = BLI_findstring(®ion->ui_lists, ui_list_id, offsetof(uiList, list_id)); - - if (!ui_list) { - ui_list = MEM_callocN(sizeof(uiList), "uiList"); - BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id)); - BLI_addtail(®ion->ui_lists, ui_list); - ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */ - if (sort_reverse) { - ui_list->filter_sort_flag |= UILST_FLT_SORT_REVERSE; - } - if (sort_lock) { - ui_list->filter_sort_flag |= UILST_FLT_SORT_LOCK; - } - } - - if (!ui_list->dyn_data) { - ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data"); - } - uiListDyn *dyn_data = ui_list->dyn_data; - - /* Because we can't actually pass type across save&load... */ - ui_list->type = ui_list_type; - ui_list->layout_type = layout_type; - - /* Reset filtering data. */ - MEM_SAFE_FREE(dyn_data->items_filter_flags); - MEM_SAFE_FREE(dyn_data->items_filter_neworder); - dyn_data->items_len = dyn_data->items_shown = -1; - - /* When active item changed since last draw, scroll to it. */ - if (activei != ui_list->list_last_activei) { - ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; - ui_list->list_last_activei = activei; - } - - /* Filter list items! (not for compact layout, though) */ - if (dataptr->data && prop) { - const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; - const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0; - int items_shown, idx = 0; -#if 0 - int prev_ii = -1, prev_i; -#endif - - if (layout_type == UILST_LAYOUT_COMPACT) { - dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop); - } - else { - // printf("%s: filtering...\n", __func__); - filter_items(ui_list, C, dataptr, propname); - // printf("%s: filtering done.\n", __func__); - } - - items_shown = dyn_data->items_shown; - if (items_shown >= 0) { - bool activei_mapping_pending = true; - items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, __func__); - // printf("%s: items shown: %d.\n", __func__, items_shown); - RNA_PROP_BEGIN (dataptr, itemptr, prop) { - if (!dyn_data->items_filter_flags || - ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) { - int ii; - if (dyn_data->items_filter_neworder) { - ii = dyn_data->items_filter_neworder[idx++]; - ii = order_reverse ? items_shown - ii - 1 : ii; - } - else { - ii = order_reverse ? items_shown - ++idx : idx++; - } - // printf("%s: ii: %d\n", __func__, ii); - items_ptr[ii].item = itemptr; - items_ptr[ii].org_idx = i; - items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] : - 0; - - if (activei_mapping_pending && activei == i) { - activei = ii; - /* So that we do not map again activei! */ - activei_mapping_pending = false; - } -#if 0 /* For now, do not alter active element, even if it will be hidden... */ - else if (activei < i) { - /* We do not want an active but invisible item! - * Only exception is when all items are filtered out... - */ - if (prev_ii >= 0) { - activei = prev_ii; - RNA_property_int_set(active_dataptr, activeprop, prev_i); - } - else { - activei = ii; - RNA_property_int_set(active_dataptr, activeprop, i); - } - } - prev_i = i; - prev_ii = ii; -#endif - } - i++; - } - RNA_PROP_END; - - if (activei_mapping_pending) { - /* No active item found, set to 'invalid' -1 value... */ - activei = -1; - } - } - if (dyn_data->items_shown >= 0) { - len = dyn_data->items_shown; - } - else { - len = dyn_data->items_len; - } - } - - switch (layout_type) { - case UILST_LAYOUT_DEFAULT: - /* layout */ - box = uiLayoutListBox(layout, ui_list, active_dataptr, activeprop); - glob = uiLayoutColumn(box, true); - row = uiLayoutRow(glob, false); - col = uiLayoutColumn(row, true); - - /* init numbers */ - uilist_prepare(ui_list, len, activei, rows, maxrows, 1, &layoutdata); - - if (dataptr->data && prop) { - /* create list items */ - for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) { - PointerRNA *itemptr = &items_ptr[i].item; - void *dyntip_data; - const int org_i = items_ptr[i].org_idx; - const int flt_flag = items_ptr[i].flt_flag; - uiBlock *subblock = uiLayoutGetBlock(col); - - overlap = uiLayoutOverlap(col); - - UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM); - - /* list item behind label & other buttons */ - sub = uiLayoutRow(overlap, false); - - but = uiDefButR_prop(subblock, - UI_BTYPE_LISTROW, - 0, - "", - 0, - 0, - UI_UNIT_X * 10, - UI_UNIT_Y, - active_dataptr, - activeprop, - 0, - 0, - org_i, - 0, - 0, - TIP_("Double click to rename")); - if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr, item_dyntip_propname))) { - UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data, MEM_freeN); - } - - sub = uiLayoutRow(overlap, false); - - icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false); - if (icon == ICON_DOT) { - icon = ICON_NONE; - } - draw_item(ui_list, - C, - sub, - dataptr, - itemptr, - icon, - active_dataptr, - active_propname, - org_i, - flt_flag); - - /* Items should be able to set context pointers for the layout. But the list-row button - * swallows events, so it needs the context storage too for handlers to see it. */ - but->context = uiLayoutGetContextStore(sub); - - /* If we are "drawing" active item, set all labels as active. */ - if (i == activei) { - ui_layout_list_set_labels_active(sub); - } - - UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM); - } - } - - /* add dummy buttons to fill space */ - for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) { - uiItemL(col, "", ICON_NONE); - } - - /* add scrollbar */ - if (len > layoutdata.visual_items) { - col = uiLayoutColumn(row, false); - uiDefButI(block, - UI_BTYPE_SCROLL, - 0, - "", - 0, - 0, - V2D_SCROLL_WIDTH, - UI_UNIT_Y * dyn_data->visual_height, - &ui_list->list_scroll, - 0, - dyn_data->height - dyn_data->visual_height, - dyn_data->visual_height, - 0, - ""); - } - break; - case UILST_LAYOUT_COMPACT: - row = uiLayoutRow(layout, true); - - if ((dataptr->data && prop) && (dyn_data->items_shown > 0) && (activei >= 0) && - (activei < dyn_data->items_shown)) { - PointerRNA *itemptr = &items_ptr[activei].item; - const int org_i = items_ptr[activei].org_idx; - - icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false); - if (icon == ICON_DOT) { - icon = ICON_NONE; - } - draw_item( - ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0); - } - /* if list is empty, add in dummy button */ - else { - uiItemL(row, "", ICON_NONE); - } - - /* next/prev button */ - BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown); - but = uiDefIconTextButR_prop(block, - UI_BTYPE_NUM, - 0, - 0, - numstr, - 0, - 0, - UI_UNIT_X * 5, - UI_UNIT_Y, - active_dataptr, - activeprop, - 0, - 0, - 0, - 0, - 0, - ""); - if (dyn_data->items_shown == 0) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - break; - case UILST_LAYOUT_GRID: - box = uiLayoutListBox(layout, ui_list, active_dataptr, activeprop); - glob = uiLayoutColumn(box, true); - row = uiLayoutRow(glob, false); - col = uiLayoutColumn(row, true); - subrow = NULL; /* Quite gcc warning! */ - - uilist_prepare(ui_list, len, activei, rows, maxrows, columns, &layoutdata); - - if (dataptr->data && prop) { - /* create list items */ - for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) { - PointerRNA *itemptr = &items_ptr[i].item; - const int org_i = items_ptr[i].org_idx; - const int flt_flag = items_ptr[i].flt_flag; - - /* create button */ - if (!(i % columns)) { - subrow = uiLayoutRow(col, false); - } - - uiBlock *subblock = uiLayoutGetBlock(subrow); - overlap = uiLayoutOverlap(subrow); - - UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM); - - /* list item behind label & other buttons */ - sub = uiLayoutRow(overlap, false); - - but = uiDefButR_prop(subblock, - UI_BTYPE_LISTROW, - 0, - "", - 0, - 0, - UI_UNIT_X * 10, - UI_UNIT_Y, - active_dataptr, - activeprop, - 0, - 0, - org_i, - 0, - 0, - NULL); - UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP); - - sub = uiLayoutRow(overlap, false); - - icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false); - draw_item(ui_list, - C, - sub, - dataptr, - itemptr, - icon, - active_dataptr, - active_propname, - org_i, - flt_flag); - - /* If we are "drawing" active item, set all labels as active. */ - if (i == activei) { - ui_layout_list_set_labels_active(sub); - } - - UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM); - } - } - - /* add dummy buttons to fill space */ - for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) { - if (!(i % columns)) { - subrow = uiLayoutRow(col, false); - } - uiItemL(subrow, "", ICON_NONE); - } - - /* add scrollbar */ - if (len > layoutdata.visual_items) { - /* col = */ uiLayoutColumn(row, false); - uiDefButI(block, - UI_BTYPE_SCROLL, - 0, - "", - 0, - 0, - V2D_SCROLL_WIDTH, - UI_UNIT_Y * dyn_data->visual_height, - &ui_list->list_scroll, - 0, - dyn_data->height - dyn_data->visual_height, - dyn_data->visual_height, - 0, - ""); - } - break; - } - - if (glob) { - /* About #UI_BTYPE_GRIP drag-resize: - * We can't directly use results from a grip button, since we have a - * rather complex behavior here (sizing by discrete steps and, overall, auto-size feature). - * Since we *never* know whether we are grip-resizing or not - * (because there is no callback for when a button enters/leaves its "edit mode"), - * we use the fact that grip-controlled value (dyn_data->resize) is completely handled - * by the grip during the grab resize, so settings its value here has no effect at all. - * - * It is only meaningful when we are not resizing, - * in which case this gives us the correct "init drag" value. - * Note we cannot affect `dyn_data->resize_prev here`, - * since this value is not controlled by the grip! - */ - dyn_data->resize = dyn_data->resize_prev + - (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y; - - row = uiLayoutRow(glob, true); - uiBlock *subblock = uiLayoutGetBlock(row); - UI_block_emboss_set(subblock, UI_EMBOSS_NONE); - - if (ui_list->filter_flag & UILST_FLT_SHOW) { - but = uiDefIconButBitI(subblock, - UI_BTYPE_TOGGLE, - UILST_FLT_SHOW, - 0, - ICON_DISCLOSURE_TRI_DOWN, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y * 0.5f, - &(ui_list->filter_flag), - 0, - 0, - 0, - 0, - TIP_("Hide filtering options")); - UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */ - - but = uiDefIconButI(subblock, - UI_BTYPE_GRIP, - 0, - ICON_GRIP, - 0, - 0, - UI_UNIT_X * 10.0f, - UI_UNIT_Y * 0.5f, - &dyn_data->resize, - 0.0, - 0.0, - 0, - 0, - ""); - UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL); - - UI_block_emboss_set(subblock, UI_EMBOSS); - - col = uiLayoutColumn(glob, false); - subblock = uiLayoutGetBlock(col); - uiDefBut(subblock, - UI_BTYPE_SEPR, - 0, - "", - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y * 0.05f, - NULL, - 0.0, - 0.0, - 0, - 0, - ""); - - draw_filter(ui_list, C, col); - } - else { - but = uiDefIconButBitI(subblock, - UI_BTYPE_TOGGLE, - UILST_FLT_SHOW, - 0, - ICON_DISCLOSURE_TRI_RIGHT, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y * 0.5f, - &(ui_list->filter_flag), - 0, - 0, - 0, - 0, - TIP_("Show filtering options")); - UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */ - - but = uiDefIconButI(subblock, - UI_BTYPE_GRIP, - 0, - ICON_GRIP, - 0, - 0, - UI_UNIT_X * 10.0f, - UI_UNIT_Y * 0.5f, - &dyn_data->resize, - 0.0, - 0.0, - 0, - 0, - ""); - UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL); - - UI_block_emboss_set(subblock, UI_EMBOSS); - } - } - - if (items_ptr) { - MEM_freeN(items_ptr); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Running Jobs Template * \{ */ diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 6ad1de68a1f..93a790b53d0 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -29,6 +29,8 @@ #include "DNA_object_types.h" #include "DNA_screen_types.h" +#include "ED_screen.h" + #include "BLI_alloca.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -38,6 +40,7 @@ #include "BLT_translation.h" +#include "BKE_context.h" #include "BKE_lib_id.h" #include "BKE_report.h" @@ -48,6 +51,7 @@ #include "UI_interface.h" #include "UI_interface_icons.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "WM_api.h" #include "WM_types.h" @@ -701,7 +705,7 @@ int UI_calc_float_precision(int prec, double value) /* Check on the number of decimal places need to display the number, * this is so 0.00001 is not displayed as 0.00, - * _but_, this is only for small values si 10.0001 will not get the same treatment. + * _but_, this is only for small values as 10.0001 will not get the same treatment. */ value = fabs(value); if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) { @@ -774,6 +778,98 @@ bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, } /* -------------------------------------------------------------------- */ + +static rctf ui_but_rect_to_view(const uiBut *but, const ARegion *region, const View2D *v2d) +{ + rctf region_rect; + ui_block_to_region_rctf(region, but->block, ®ion_rect, &but->rect); + + rctf view_rect; + UI_view2d_region_to_view_rctf(v2d, ®ion_rect, &view_rect); + + return view_rect; +} + +/** + * To get a margin (typically wanted), add the margin to \a rect directly. + * + * Based on #file_ensure_inside_viewbounds(), could probably share code. + * + * \return true if anything changed. + */ +static bool ui_view2d_cur_ensure_rect_in_view(View2D *v2d, const rctf *rect) +{ + const float rect_width = BLI_rctf_size_x(rect); + const float rect_height = BLI_rctf_size_y(rect); + + rctf *cur = &v2d->cur; + const float cur_width = BLI_rctf_size_x(cur); + const float cur_height = BLI_rctf_size_y(cur); + + bool changed = false; + + /* Snap to bottom edge. Also use if rect is higher than view bounds (could be a parameter). */ + if ((cur->ymin > rect->ymin) || (rect_height > cur_height)) { + cur->ymin = rect->ymin; + cur->ymax = cur->ymin + cur_height; + changed = true; + } + /* Snap to upper edge. */ + else if (cur->ymax < rect->ymax) { + cur->ymax = rect->ymax; + cur->ymin = cur->ymax - cur_height; + changed = true; + } + /* Snap to left edge. Also use if rect is wider than view bounds. */ + else if ((cur->xmin > rect->xmin) || (rect_width > cur_width)) { + cur->xmin = rect->xmin; + cur->xmax = cur->xmin + cur_width; + changed = true; + } + /* Snap to right edge. */ + else if (cur->xmax < rect->xmax) { + cur->xmax = rect->xmax; + cur->xmin = cur->xmax - cur_width; + changed = true; + } + else { + BLI_assert(BLI_rctf_inside_rctf(cur, rect)); + } + + return changed; +} + +/** + * Adjust the view so the rectangle of \a but is in view, with some extra margin. + * + * It's important that this is only executed after buttons received their final #uiBut.rect. E.g. + * #UI_panels_end() modifies them, so if that is executed, this function must not be called before + * it. + * + * \param region: The region the button is placed in. Make sure this is actually the one the button + * is placed in, not just the context region. + */ +void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but) +{ + View2D *v2d = ®ion->v2d; + /* Uninitialized view or region that doesn't use View2D. */ + if ((v2d->flag & V2D_IS_INIT) == 0) { + return; + } + + rctf rect = ui_but_rect_to_view(but, region, v2d); + + const int margin = UI_UNIT_X * 0.5f; + BLI_rctf_pad(&rect, margin, margin); + + const bool changed = ui_view2d_cur_ensure_rect_in_view(v2d, &rect); + if (changed) { + UI_view2d_curRect_changed(C, v2d); + ED_region_tag_redraw_no_rebuild(region); + } +} + +/* -------------------------------------------------------------------- */ /** \name Button Store * * Modal Button Store API. @@ -932,7 +1028,7 @@ void UI_butstore_update(uiBlock *block) uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p); /* can be NULL if the buttons removed, - * note: we could allow passing in a callback when buttons are removed + * NOTE: we could allow passing in a callback when buttons are removed * so the caller can cleanup */ *bs_elem->but_p = but_new; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 1ab12a2c8ea..0decaa5e45d 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -106,6 +106,7 @@ typedef enum { /* specials */ UI_WTYPE_ICON, UI_WTYPE_ICON_LABEL, + UI_WTYPE_PREVIEW_TILE, UI_WTYPE_SWATCH, UI_WTYPE_RGB_PICKER, UI_WTYPE_UNITVEC, @@ -238,7 +239,7 @@ typedef struct uiWidgetTrias { #define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4) typedef struct uiWidgetBase { - /* TODO remove these completely */ + /* TODO: remove these completely. */ int totvert, halfwayvert; float outer_v[WIDGET_SIZE_MAX][2]; float inner_v[WIDGET_SIZE_MAX][2]; @@ -400,7 +401,7 @@ static struct { GPUBatch *roundbox_widget; GPUBatch *roundbox_shadow; - /* TODO remove */ + /* TODO: remove. */ GPUVertFormat format; uint vflag_id; } g_ui_batch_cache = {0}; @@ -524,7 +525,7 @@ void UI_draw_anti_tria( float draw_color[4]; copy_v4_v4(draw_color, color); - /* Note: This won't give back the original color. */ + /* NOTE: This won't give back the original color. */ draw_color[3] *= 1.0f / WIDGET_AA_JITTER; GPU_blend(GPU_BLEND_ALPHA); @@ -769,7 +770,7 @@ static void round_box__edges( BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect); BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi); - /* mult */ + /* Multiply by radius. */ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { veci[a][0] = radi * cornervec[a][0]; veci[a][1] = radi * cornervec[a][1]; @@ -1378,8 +1379,6 @@ static int ui_but_draw_menu_icon(const uiBut *but) static void widget_draw_icon( const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const uchar mono_color[4]) { - float xs = 0.0f, ys = 0.0f; - if (but->flag & UI_BUT_ICON_PREVIEW) { GPU_blend(GPU_BLEND_ALPHA); widget_draw_preview(icon, alpha, rect); @@ -1421,6 +1420,7 @@ static void widget_draw_icon( if (icon && icon != ICON_BLANK1) { const float ofs = 1.0f / aspect; + float xs, ys; if (but->drawflag & UI_BUT_ICON_LEFT) { /* special case - icon_only pie buttons */ @@ -1642,7 +1642,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, /* Corner case, the str already takes all available mem, * and the ellipsis chars would actually add more chars. * Better to just trim one or two letters to the right in this case... - * Note: with a single-char ellipsis, this should never happen! But better be safe + * NOTE: with a single-char ellipsis, this should never happen! But better be safe * here... */ ui_text_clip_right_ex( @@ -2007,14 +2007,15 @@ static void widget_draw_text(const uiFontStyle *fstyle, drawstr_left_len = INT_MAX; #ifdef WITH_INPUT_IME - /* FIXME, IME is modifying 'const char *drawstr! */ + /* FIXME: IME is modifying `const char *drawstr`! */ ime_data = ui_but_ime_data_get(but); if (ime_data && ime_data->composite_len) { /* insert composite string into cursor pos */ BLI_snprintf((char *)drawstr, UI_MAX_DRAW_STR, - "%s%s%s", + "%.*s%s%s", + but->pos, but->editstr, ime_data->str_composite, but->editstr + but->pos); @@ -2030,8 +2031,11 @@ static void widget_draw_text(const uiFontStyle *fstyle, /* text button selection, cursor, composite underline */ if (but->editstr && but->pos != -1) { int but_pos_ofs; - /* Shape of the cursor for drawing. */ - rcti but_cursor_shape; + +#ifdef WITH_INPUT_IME + bool ime_reposition_window = false; + int ime_win_x, ime_win_y; +#endif /* text button selection */ if ((but->selend - but->selsta) > 0) { @@ -2056,14 +2060,28 @@ static void widget_draw_text(const uiFontStyle *fstyle, immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + rcti selection_shape; + selection_shape.xmin = rect->xmin + selsta_draw; + selection_shape.xmax = min_ii(rect->xmin + selwidth_draw, rect->xmax - 2); + selection_shape.ymin = rect->ymin + U.pixelsize; + selection_shape.ymax = rect->ymax - U.pixelsize; immUniformColor4ubv(wcol->item); immRecti(pos, - rect->xmin + selsta_draw, - rect->ymin + U.pixelsize, - min_ii(rect->xmin + selwidth_draw, rect->xmax - 2), - rect->ymax - U.pixelsize); + selection_shape.xmin, + selection_shape.ymin, + selection_shape.xmax, + selection_shape.ymax); immUnbindProgram(); + +#ifdef WITH_INPUT_IME + /* IME candidate window uses selection position. */ + if (!ime_reposition_window) { + ime_reposition_window = true; + ime_win_x = selection_shape.xmin; + ime_win_y = selection_shape.ymin; + } +#endif } } @@ -2071,7 +2089,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, but_pos_ofs = but->pos; #ifdef WITH_INPUT_IME - /* if is ime compositing, move the cursor */ + /* If is IME compositing, move the cursor. */ if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) { but_pos_ofs += ime_data->cursor_pos; } @@ -2096,6 +2114,8 @@ static void widget_draw_text(const uiFontStyle *fstyle, immUniformThemeColor(TH_WIDGET_TEXT_CURSOR); + /* Shape of the cursor for drawing. */ + rcti but_cursor_shape; but_cursor_shape.xmin = (rect->xmin + t) - U.pixelsize; but_cursor_shape.ymin = rect->ymin + U.pixelsize; but_cursor_shape.xmax = (rect->xmin + t) + U.pixelsize; @@ -2109,16 +2129,24 @@ static void widget_draw_text(const uiFontStyle *fstyle, but_cursor_shape.ymax); immUnbindProgram(); - } #ifdef WITH_INPUT_IME - if (ime_data && ime_data->composite_len) { - /* ime cursor following */ - if (but->pos >= but->ofs) { - ui_but_ime_reposition(but, but_cursor_shape.xmax + 5, but_cursor_shape.ymin + 3, false); + /* IME candidate window uses cursor position. */ + if (!ime_reposition_window) { + ime_reposition_window = true; + ime_win_x = but_cursor_shape.xmax + 5; + ime_win_y = but_cursor_shape.ymin + 3; } +#endif + } - /* composite underline */ +#ifdef WITH_INPUT_IME + /* IME cursor following. */ + if (ime_reposition_window) { + ui_but_ime_reposition(but, ime_win_x, ime_win_y, false); + } + if (ime_data && ime_data->composite_len) { + /* Composite underline. */ widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr); } #endif @@ -2494,7 +2522,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, ui_text_clip_middle(fstyle, but, rect); } - /* always draw text for textbutton cursor */ + /* Always draw text for text-button cursor. */ widget_draw_text(fstyle, wcol, but, rect); ui_but_text_password_hide(password_str, but, true); @@ -3089,7 +3117,7 @@ void ui_draw_gradient(const rcti *rect, copy_v3_v3(col1[3], col1[2]); break; default: - BLI_assert(!"invalid 'type' argument"); + BLI_assert_msg(0, "invalid 'type' argument"); hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); @@ -3693,10 +3721,6 @@ static void widget_progressbar( /* "slider" bar color */ copy_v3_v3_uchar(wcol->inner, wcol->item); widgetbase_draw(&wtb_bar, wcol); - - /* raise text a bit */ - rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2); - rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2); } static void widget_datasetrow( @@ -3996,6 +4020,14 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun widgetbase_draw(&wtb, wcol); } +static void widget_preview_tile( + uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign)) +{ + const uiStyle *style = UI_style_get(); + ui_draw_preview_item_stateless( + &style->widget, rect, but->drawstr, but->icon, wcol->text, UI_STYLE_TEXT_CENTER); +} + static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), @@ -4307,7 +4339,7 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * widget_init(&wtb); if (but->block->drawextra) { - /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */ + /* NOTE: drawextra can change rect +1 or -1, to match round errors of existing previews. */ but->block->drawextra( C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect); @@ -4461,6 +4493,13 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) wt.custom = widget_icon_has_anim; break; + case UI_WTYPE_PREVIEW_TILE: + wt.draw = NULL; + /* Drawn via the `custom` callback. */ + wt.text = NULL; + wt.custom = widget_preview_tile; + break; + case UI_WTYPE_SWATCH: wt.custom = widget_swatch; break; @@ -4756,6 +4795,10 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu wt = widget_type(UI_WTYPE_BOX); break; + case UI_BTYPE_PREVIEW_TILE: + wt = widget_type(UI_WTYPE_PREVIEW_TILE); + break; + case UI_BTYPE_EXTRA: widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect); break; @@ -4909,13 +4952,15 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu wt->draw(&wt->wcol, rect, state, roundboxalign); } - if (use_alpha_blend) { - GPU_blend(GPU_BLEND_ALPHA); - } + if (wt->text) { + if (use_alpha_blend) { + GPU_blend(GPU_BLEND_ALPHA); + } - wt->text(fstyle, &wt->wcol, but, rect); - if (use_alpha_blend) { - GPU_blend(GPU_BLEND_NONE); + wt->text(fstyle, &wt->wcol, but, rect); + if (use_alpha_blend) { + GPU_blend(GPU_BLEND_NONE); + } } } @@ -5352,7 +5397,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, } } else { - BLI_assert(!"Unknwon menu item separator type"); + BLI_assert_msg(0, "Unknwon menu item separator type"); } if (fstyle->kerning == 1) { @@ -5437,17 +5482,20 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, } } -void ui_draw_preview_item( - const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state) +/** + * Version of #ui_draw_preview_item() that does not draw the menu background and item text based on + * state. It just draws the preview and text directly. + */ +void ui_draw_preview_item_stateless(const uiFontStyle *fstyle, + rcti *rect, + const char *name, + int iconid, + const uchar text_col[4], + eFontStyle_Align text_align) { rcti trect = *rect; const float text_size = UI_UNIT_Y; float font_dims[2] = {0.0f, 0.0f}; - uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); - - /* drawing button background */ - wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED); - wt->draw(&wt->wcol, rect, 0, 0); /* draw icon in rect above the space reserved for the label */ rect->ymin += text_size; @@ -5459,8 +5507,6 @@ void ui_draw_preview_item( fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]); /* text rect */ - trect.xmin += 0; - trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2; trect.ymin += U.widget_unit / 2; trect.ymax = trect.ymin + font_dims[1]; if (trect.xmax > rect->xmax - PREVIEW_PAD) { @@ -5479,11 +5525,27 @@ void ui_draw_preview_item( UI_fontstyle_draw(fstyle, &trect, drawstr, - wt->wcol.text, + text_col, &(struct uiFontStyleDraw_Params){ - .align = UI_STYLE_TEXT_CENTER, + .align = text_align, }); } } +void ui_draw_preview_item(const uiFontStyle *fstyle, + rcti *rect, + const char *name, + int iconid, + int state, + eFontStyle_Align text_align) +{ + uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); + + /* drawing button background */ + wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED); + wt->draw(&wt->wcol, rect, 0, 0); + + ui_draw_preview_item_stateless(fstyle, rect, name, iconid, wt->wcol.text, text_align); +} + /** \} */ diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 5eb20ae601b..e9804840801 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -347,7 +347,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y); v2d->keeptot = V2D_KEEPTOT_BOUNDS; - /* note, scroll is being flipped in ED_region_panels() drawing */ + /* NOTE: scroll is being flipped in #ED_region_panels() drawing. */ v2d->scroll |= (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE); if (do_init) { @@ -717,7 +717,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) * * So, resolution is to just shift view by the gap between the extremities. * We favor moving the 'minimum' across, as that's origin for most things. - * (XXX - in the past, max was favored... if there are bugs, swap!) + * (XXX: in the past, max was favored... if there are bugs, swap!) */ if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) { /* outside boundaries on both sides, @@ -1059,7 +1059,7 @@ void UI_view2d_zoom_cache_reset(void) /* While scaling we can accumulate fonts at many sizes (~20 or so). * Not an issue with embedded font, but can use over 500Mb with i18n ones! See T38244. */ - /* Note: only some views draw text, we could check for this case to avoid cleaning cache. */ + /* NOTE: only some views draw text, we could check for this case to avoid cleaning cache. */ BLF_cache_clear(); } @@ -1158,7 +1158,7 @@ void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis) * correspondence with pixels for smooth UI drawing, * but only applied where requested. */ - /* XXX temp (ton) */ + /* XXX(ton): temp. */ xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f; yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f; @@ -1844,7 +1844,7 @@ View2D *UI_view2d_fromcontext(const bContext *C) return &(region->v2d); } -/* same as above, but it returns regionwindow. Utility for pulldowns or buttons */ +/* Same as above, but it returns region-window. Utility for pull-downs or buttons. */ View2D *UI_view2d_fromcontext_rwin(const bContext *C) { ScrArea *area = CTX_wm_area(C); diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c index 5801b7cdbdb..f7ef8c06389 100644 --- a/source/blender/editors/interface/view2d_draw.c +++ b/source/blender/editors/interface/view2d_draw.c @@ -216,7 +216,7 @@ static void draw_parallel_lines(const ParallelLinesSet *lines, immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); immUniform2fv("viewportSize", &viewport[2]); /* -1.0f offset here is because the line is too fat due to the builtin anti-aliasing. - * TODO make a variant or a uniform to toggle it off. */ + * TODO: make a variant or a uniform to toggle it off. */ immUniform1f("lineWidth", U.pixelsize - 1.0f); } else { diff --git a/source/blender/editors/interface/view2d_edge_pan.c b/source/blender/editors/interface/view2d_edge_pan.c index ca32a754f1d..1d300c7b275 100644 --- a/source/blender/editors/interface/view2d_edge_pan.c +++ b/source/blender/editors/interface/view2d_edge_pan.c @@ -160,7 +160,7 @@ static float edge_pan_speed(View2DEdgePanData *vpd, distance = min - event_loc; } else { - BLI_assert(!"Calculating speed outside of pan zones"); + BLI_assert_msg(0, "Calculating speed outside of pan zones"); return 0.0f; } float distance_factor = distance / (vpd->speed_ramp * U.widget_unit); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 69acfc657dc..1fd1b6c984d 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -271,7 +271,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) view_pan_apply(C, op); break; } - /* XXX - Mode switching isn't implemented. See comments in 36818. + /* XXX: Mode switching isn't implemented. See comments in 36818. * switch to zoom */ #if 0 case LEFTMOUSE: @@ -1527,7 +1527,7 @@ struct SmoothView2DStore { /** * function to get a factor out of a rectangle * - * note: this doesn't always work as well as it might because the target size + * NOTE: this doesn't always work as well as it might because the target size * may not be reached because of clamping the desired rect, we _could_ * attempt to clamp the rect before working out the zoom factor but its * not really worthwhile for the few cases this happens. @@ -1745,7 +1745,7 @@ typedef struct v2dScrollerMove { * This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, * as we only need focus bubble info. * - * \warning: The start of this struct must not change, + * \warning The start of this struct must not change, * so that it stays in sync with the 'real' version. * For now, we don't need to have a separate (internal) header for structs like this... */ @@ -2132,7 +2132,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * scroller_activate_exit(C, op); /* can't catch this event for ourselves, so let it go to someone else? */ - /* XXX note: if handlers use mask rect to clip input, input will fail for this case */ + /* XXX NOTE: if handlers use mask rect to clip input, input will fail for this case. */ return OPERATOR_PASS_THROUGH; } diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 28838d677f0..12890552b1d 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -63,10 +63,26 @@ # include "WM_api.h" # include "WM_types.h" +# include "DEG_depsgraph.h" + # include "io_alembic.h" # include "ABC_alembic.h" +const EnumPropertyItem rna_enum_abc_export_evaluation_mode_items[] = { + {DAG_EVAL_RENDER, + "RENDER", + 0, + "Render", + "Use Render settings for object visibility, modifier settings, etc"}, + {DAG_EVAL_VIEWPORT, + "VIEWPORT", + 0, + "Viewport", + "Use Viewport settings for object visibility, modifier settings, etc"}, + {0, NULL, 0, NULL, NULL}, +}; + static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) { @@ -126,7 +142,6 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"), .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"), .visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only"), - .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), .face_sets = RNA_boolean_get(op->ptr, "face_sets"), .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), .export_hair = RNA_boolean_get(op->ptr, "export_hair"), @@ -137,6 +152,7 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .triangulate = RNA_boolean_get(op->ptr, "triangulate"), .quad_method = RNA_enum_get(op->ptr, "quad_method"), .ngon_method = RNA_enum_get(op->ptr, "ngon_method"), + .evaluation_mode = RNA_enum_get(op->ptr, "evaluation_mode"), .global_scale = RNA_float_get(op->ptr, "global_scale"), }; @@ -194,9 +210,11 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) sub = uiLayoutColumnWithHeading(col, true, IFACE_("Only")); uiItemR(sub, imfptr, "selected", 0, IFACE_("Selected Objects"), ICON_NONE); - uiItemR(sub, imfptr, "renderable_only", 0, IFACE_("Renderable Objects"), ICON_NONE); uiItemR(sub, imfptr, "visible_objects_only", 0, IFACE_("Visible Objects"), ICON_NONE); + col = uiLayoutColumn(box, true); + uiItemR(col, imfptr, "evaluation_mode", 0, NULL, ICON_NONE); + /* Object Data */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); @@ -355,12 +373,6 @@ void WM_OT_alembic_export(wmOperatorType *ot) ot->srna, "selected", 0, "Selected Objects Only", "Export only selected objects"); RNA_def_boolean(ot->srna, - "renderable_only", - 1, - "Renderable Objects Only", - "Export only objects marked renderable in the outliner"); - - RNA_def_boolean(ot->srna, "visible_objects_only", 0, "Visible Objects Only", @@ -468,6 +480,14 @@ void WM_OT_alembic_export(wmOperatorType *ot) "This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it " "to run as a background job"); + RNA_def_enum(ot->srna, + "evaluation_mode", + rna_enum_abc_export_evaluation_mode_items, + DAG_EVAL_RENDER, + "Use Settings for", + "Determines visibility of objects, modifier settings, and other areas where there " + "are different settings for viewport and rendering"); + /* This dummy prop is used to check whether we need to init the start and * end frame values to that of the scene's, otherwise they are reset at * every change, draw update. */ diff --git a/source/blender/editors/io/io_gpencil.h b/source/blender/editors/io/io_gpencil.h index b347be00412..428b09f0e9c 100644 --- a/source/blender/editors/io/io_gpencil.h +++ b/source/blender/editors/io/io_gpencil.h @@ -25,8 +25,8 @@ */ struct ARegion; -struct bContext; struct View3D; +struct bContext; struct wmOperatorType; void WM_OT_gpencil_import_svg(struct wmOperatorType *ot); diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index 8d8e1e9f06a..e6f190f335b 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -236,7 +236,7 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op) } } - /* TODO, only notify changes */ + /* TODO: only notify changes. */ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -514,7 +514,7 @@ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) BPoint *bp; int a, tot; - if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) { + if (BLI_listbase_is_empty(<->vertex_group_names) || lt->dvert == NULL) { continue; } diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index d92a81179cc..23eaf991fd3 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -240,7 +240,7 @@ static void lattice_undosys_step_decode(struct bContext *C, } undolatt_to_editlatt(&elem->data, lt->editlatt); lt->editlatt->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(<->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 36edbbe31d6..880d27e1615 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -145,7 +145,7 @@ static void setup_vertex_point(Mask *mask, /* parent */ reference_parent_point = close_point; - /* note, we may want to copy other attributes later, radius? pressure? color? */ + /* NOTE: we may want to copy other attributes later, radius? pressure? color? */ } } @@ -189,7 +189,7 @@ static void finSelectedSplinePoint(MaskLayer *mask_layer, *point = NULL; if (check_active) { - /* TODO, having an active point but no active spline is possible, why? */ + /* TODO: having an active point but no active spline is possible, why? */ if (mask_layer->act_spline && mask_layer->act_point && MASKPOINT_ISSEL_ANY(mask_layer->act_point)) { *spline = mask_layer->act_spline; @@ -277,7 +277,7 @@ static bool add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2 setup_vertex_point(mask, spline, new_point, co, u, ctime, NULL, true); - /* TODO - we could pass the spline! */ + /* TODO: we could pass the spline! */ BKE_mask_layer_shape_changed_add(mask_layer, BKE_mask_layer_shape_spline_to_index(mask_layer, spline) + point_index + 1, @@ -479,7 +479,7 @@ static int add_vertex_handle_cyclic_at_point(bContext *C, spline->flag |= MASK_SPLINE_CYCLIC; - /* TODO, update keyframes in time. */ + /* TODO: update keyframes in time. */ BKE_mask_calc_handle_point_auto(spline, active_point, false); BKE_mask_calc_handle_point_auto(spline, other_point, false); @@ -526,7 +526,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) float co[2]; RNA_float_get_array(op->ptr, "location", co); - /* TODO, having an active point but no active spline is possible, why? */ + /* TODO: having an active point but no active spline is possible, why? */ if (mask_layer && mask_layer->act_spline && mask_layer->act_point && MASKPOINT_ISSEL_ANY(mask_layer->act_point)) { MaskSpline *spline = mask_layer->act_spline; diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index d3fa0e93597..de8ea8e21eb 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -211,7 +211,7 @@ static void draw_spline_points(const bContext *C, undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); } - /* TODO, add this to sequence editor */ + /* TODO: add this to sequence editor. */ float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; mask_spline_color_get(mask_layer, spline, is_spline_sel, rgb_spline); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 3476f1ca735..6fa7457ce14 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -390,7 +390,7 @@ static void select_sliding_point(Mask *mask, point->bezt.f3 |= SELECT; break; default: - BLI_assert(!"Unexpected situation in select_sliding_point()"); + BLI_assert_msg(0, "Unexpected situation in select_sliding_point()"); } mask_layer->act_spline = spline; diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 4ce4a416796..a5a3489c143 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -173,7 +173,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op) MaskSplinePoint *point = &spline->points[i]; if (MASKPOINT_ISSEL_ANY(point)) { - /* TODO - nicer access here */ + /* TODO: nicer access here. */ shape_ele_dst->value[6] = shape_ele_src->value[6]; } @@ -291,7 +291,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) BLI_addtail(&shapes_tmp, mask_layer_shape_tmp); } - /* re-key, note: can't modify the keys here since it messes uop */ + /* re-key, NOTE: can't modify the keys here since it messes up. */ for (mask_layer_shape_tmp = shapes_tmp.first; mask_layer_shape_tmp; mask_layer_shape_tmp = mask_layer_shape_tmp->next) { BKE_mask_layer_evaluate(mask_layer, mask_layer_shape_tmp->frame, true); diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index b7ee50a9461..648008a4779 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -65,7 +65,7 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag) return; } - /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */ + /* NOTE: call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags. */ /* we could call this directly in all areas that change selection, * since this could become slow for realtime updates (circle-select for eg) */ @@ -433,7 +433,7 @@ bool paintface_mouse_select( /* image window redraw */ paintface_flush_flags(C, ob, SELECT); - ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */ + ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */ return true; } diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 110f1975d8d..01736f2919a 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -279,7 +279,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) for (int i = 0; i < NUM_VALUE_KINDS; i++) { opdata->shift_value[i] = -1.0f; opdata->initial_length[i] = -1.0f; - /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */ + /* NOTE: scale for #OFFSET_VALUE will get overwritten in #edbm_bevel_invoke. */ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch; initNumInput(&opdata->num_input[i]); @@ -347,7 +347,7 @@ static bool edbm_bevel_calc(wmOperator *op) /* revert to original mesh */ if (opdata->is_modal) { - EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false); + EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false); } const int material = CLAMPIS(material_init, -1, obedit->totcol - 1); @@ -436,7 +436,7 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false); + EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); if (v3d) { @@ -456,7 +456,7 @@ static void edbm_bevel_cancel(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { Object *obedit = opdata->ob_store[ob_index].ob; BMEditMesh *em = BKE_editmesh_from_object(obedit); - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true); + EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true); EDBM_update(obedit->data, &(const struct EDBMUpdate_Params){ .calc_looptri = false, diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 42cf36dda81..3c8afe8e7db 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -67,7 +67,7 @@ typedef struct { /* Aligned with objects array. */ struct { - BMBackup mesh; + BMBackup mesh_backup; bool is_valid; bool is_dirty; } * backup; @@ -160,7 +160,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (em->bm->totedgesel != 0) { opdata->backup[ob_index].is_valid = true; - opdata->backup[ob_index].mesh = EDBM_redo_state_store(em); + opdata->backup[ob_index].mesh_backup = EDBM_redo_state_store(em); } } @@ -184,7 +184,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata) for (int ob_index = 0; ob_index < opdata->backup_len; ob_index++) { if (opdata->backup[ob_index].is_valid) { - EDBM_redo_state_free(&opdata->backup[ob_index].mesh, NULL, false); + EDBM_redo_state_free(&opdata->backup[ob_index].mesh_backup); } } MEM_freeN(opdata->backup); @@ -280,7 +280,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) /* -------------------------------------------------------------------- */ /* Modal support */ - /* Note: keep this isolated, exec can work without this */ + /* NOTE: keep this isolated, exec can work without this. */ if (opdata != NULL) { mesh_bisect_interactive_calc(C, op, plane_co, plane_no); /* Write back to the props. */ @@ -301,7 +301,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) if (opdata != NULL) { if (opdata->backup[ob_index].is_dirty) { - EDBM_redo_state_restore(opdata->backup[ob_index].mesh, em, false); + EDBM_redo_state_restore(&opdata->backup[ob_index].mesh_backup, em, false); opdata->backup[ob_index].is_dirty = false; } } diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 1c27ab00715..18f51ae9df2 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -209,7 +209,7 @@ static void edbm_inset_exit(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false); + EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); if (v3d) { @@ -235,7 +235,7 @@ static void edbm_inset_cancel(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { Object *obedit = opdata->ob_store[ob_index].ob; BMEditMesh *em = BKE_editmesh_from_object(obedit); - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true); + EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true); EDBM_update(obedit->data, &(const struct EDBMUpdate_Params){ .calc_looptri = false, @@ -276,7 +276,7 @@ static bool edbm_inset_calc(wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); if (opdata->is_modal) { - EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false); + EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false); } if (use_individual) { diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 0e2dd492e06..73f6a3f3238 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -157,7 +157,7 @@ typedef struct KnifePosData { typedef struct KnifeTool_OpData { ARegion *region; /* region that knifetool was activated in */ void *draw_handle; /* for drawing preview loop */ - ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */ + ViewContext vc; /* NOTE: _don't_ use 'mval', instead use the one we define below. */ float mval[2]; /* mouse value with snapping applied */ // bContext *C; @@ -1475,7 +1475,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) } } - /* Note: as following loop progresses, the 'v' fields of + /* NOTE: as following loop progresses, the 'v' fields of * the linehits will be filled in (as edges are split or * in-face verts are made), so it may be true that both * the v and the kfe or f fields will be non-NULL. */ @@ -1760,7 +1760,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd, if (RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d)) { float view_clip[2][3]; - /* note: view_clip[0] should never get clipped */ + /* NOTE: view_clip[0] should never get clipped. */ copy_v3_v3(view_clip[0], p_ofs); madd_v3_v3v3fl(view_clip[1], p_ofs, view, dist); diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index aa144dd3f3c..09b17acf56d 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -30,6 +30,7 @@ #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" @@ -59,7 +60,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ARegion *region = CTX_wm_region(C); - struct Mesh *me_eval; + const struct Mesh *me_eval; bool me_eval_needs_free; if (ob->type == OB_MESH || ob->runtime.data_eval) { @@ -113,7 +114,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, BKE_nurbList_free(&nurbslist); if (me_eval_needs_free) { - BKE_mesh_free(me_eval); + BKE_mesh_free((struct Mesh *)me_eval); } } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 71319338a53..0a4fecde6ea 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -241,7 +241,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) * in editmesh_select.c (around line 1000)... */ /* sets as active, useful for other tools */ if (em->selectmode & SCE_SELECT_VERTEX) { - /* low priority TODO, get vertrex close to mouse */ + /* low priority TODO: get vertrex close to mouse. */ BM_select_history_store(em->bm, lcd->eed->v1); } if (em->selectmode & SCE_SELECT_EDGE) { diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 993905462db..cccfc7e934c 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -126,7 +126,7 @@ static int geometry_extract_apply(bContext *C, .calc_face_normal = true, })); - BMEditMesh *em = BKE_editmesh_create(bm, false); + BMEditMesh *em = BKE_editmesh_create(bm); /* Generate the tags for deleting geometry in the extracted object. */ tag_fn(bm, params); @@ -206,7 +206,7 @@ static int geometry_extract_apply(bContext *C, }), mesh); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); MEM_freeN(em); if (new_mesh->totvert == 0) { diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 593545ddcef..30a453a32ee 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -29,6 +29,7 @@ #include "DNA_windowmanager_types.h" #ifdef WITH_FREESTYLE +# include "BKE_customdata.h" # include "DNA_meshdata_types.h" #endif diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 8626520ec37..5a2a090b725 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -927,7 +927,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed /* single edge, extend */ if (i == 1 && e_best->l) { - /* note: if the case of 3 edges has one change in loop stepping, + /* NOTE: if the case of 3 edges has one change in loop stepping, * if this becomes more involved we may be better off splitting * the 3 edge case into its own else-if branch */ if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) { @@ -975,7 +975,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed BM_mesh_edgesplit(em->bm, true, true, true); - /* note: the output of the bmesh operator is ignored, since we built + /* NOTE: the output of the bmesh operator is ignored, since we built * the contiguous loop pairs to split already, its possible that some * edge did not split even though it was tagged which would not work * as expected (but not crash), however there are checks to ensure diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index d8973e100bc..830c9abb41e 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -35,6 +35,8 @@ #include "BLI_utildefines_stack.h" #include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_report.h" @@ -434,7 +436,7 @@ struct NearestEdgeUserData { struct NearestEdgeUserData_Hit hit_cycle; }; -/* note; uses v3d, so needs active 3d window */ +/* NOTE: uses v3d, so needs active 3d window. */ static void find_nearest_edge__doClosest( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { @@ -964,7 +966,7 @@ static bool unified_findnearest(ViewContext *vc, } } - /* return only one of 3 pointers, for frontbuffer redraws */ + /* Return only one of 3 pointers, for front-buffer redraws. */ if (hit.v.ele) { hit.f.ele = NULL; hit.e.ele = NULL; @@ -3446,7 +3448,7 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in select_linked_delimit_begin(bm, delimit); } - /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */ + /* NOTE: logic closely matches #edbm_select_linked_exec, keep in sync. */ if (ele->head.htype == BM_VERT) { BMVert *eve = (BMVert *)ele; @@ -4739,10 +4741,11 @@ static bool edbm_select_ungrouped_poll(bContext *C) BMEditMesh *em = BKE_editmesh_from_object(obedit); const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); + const ListBase *defbase = BKE_object_defgroup_list(obedit); if ((em->selectmode & SCE_SELECT_VERTEX) == 0) { CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode"); } - else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) { + else if (BLI_listbase_is_empty(defbase) || cd_dvert_offset == -1) { CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object"); } else { diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index 2ffeaa06751..c452f7a7487 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -29,6 +29,8 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_material.h" @@ -559,7 +561,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) * \{ */ /** - * Note: This is not normal, but the edge direction itself and always in + * NOTE: This is not normal, but the edge direction itself and always in * a positive quadrant (tries z, y then x). * Therefore we need to use the entire object transformation matrix. */ @@ -1041,7 +1043,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (cd_dvert_offset == -1) { continue; } - defbase_len = BLI_listbase_count(&ob->defbase); + defbase_len = BKE_object_defgroup_count(ob); if (defbase_len == 0) { continue; } @@ -1090,8 +1092,10 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) /* We store the names of the vertex groups, so we can select * vertex groups with the same name in different objects. */ + const ListBase *defbase = BKE_object_defgroup_list(ob); + int i = 0; - LISTBASE_FOREACH (bDeformGroup *, dg, &ob->defbase) { + LISTBASE_FOREACH (bDeformGroup *, dg, defbase) { if (BLI_BITMAP_TEST(defbase_selected, i)) { BLI_gset_add(gset, dg->name); } @@ -1128,7 +1132,8 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (cd_dvert_offset == -1) { continue; } - defbase_len = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + defbase_len = BLI_listbase_count(defbase); if (defbase_len == 0) { continue; } @@ -1141,7 +1146,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) GSetIterator gs_iter; GSET_ITER (gs_iter, gset) { const char *name = BLI_gsetIterator_getKey(&gs_iter); - int vgroup_id = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)); + int vgroup_id = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name)); if (vgroup_id != -1) { BLI_BITMAP_ENABLE(defbase_selected, vgroup_id); found_any = true; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index fe9656d277e..41a9f426798 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -44,6 +44,7 @@ #include "BLI_string.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_key.h" @@ -145,7 +146,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/* Note, these values must match delete_mesh() event values */ +/* NOTE: these values must match delete_mesh() event values. */ static const EnumPropertyItem prop_mesh_cornervert_types[] = { {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""}, {SUBD_CORNER_PATH, "PATH", 0, "Path", ""}, @@ -245,7 +246,7 @@ static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_min, const int cuts_default) { - /* Note, these values must match delete_mesh() event values */ + /* NOTE: these values must match delete_mesh() event values. */ static const EnumPropertyItem prop_subd_edgering_types[] = { {SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""}, {SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""}, @@ -431,7 +432,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot) /** \name Delete Operator * \{ */ -/* Note, these values must match delete_mesh() event values */ +/* NOTE: these values must match delete_mesh() event values. */ enum { MESH_DELETE_VERT = 0, MESH_DELETE_EDGE = 1, @@ -973,7 +974,7 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) #ifdef USE_FACE_CREATE_SEL_EXTEND /* normally we would want to leave the new geometry selected, * but being able to press F many times to add geometry is too useful! */ - if (ele_desel && (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) && + if (ele_desel && (BMO_slot_buffer_len(bmop.slots_out, "faces.out") == 1) && (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) { edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face); } @@ -1264,9 +1265,12 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * } } if (checks_succeded) { + BMBackup em_backup = EDBM_redo_state_store(em); + BM_custom_loop_normals_to_vector_layer(bm); BMO_op_exec(bm, &bmop); + const bool failure = BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL); len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (len && is_pair) { @@ -1275,8 +1279,14 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); } - if (!EDBM_op_finish(em, &bmop, op, true)) { + bool em_backup_free = true; + if (!EDBM_op_finish(em, &bmop, op, false)) { + len = 0; + } + else if (failure) { len = 0; + EDBM_redo_state_restore_and_free(&em_backup, em, true); + em_backup_free = false; } else { /* so newly created edges get the selection state from the vertex */ @@ -1291,6 +1301,10 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * .is_destructive = true, }); } + + if (em_backup_free) { + EDBM_redo_state_free(&em_backup); + } } MEM_freeN(verts); @@ -2331,7 +2345,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BMO_slot_buffer_hflag_enable( em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); - const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out"); + const int tot_rotate = BMO_slot_buffer_len(bmop.slots_out, "edges.out"); const int tot_failed = tot - tot_rotate; tot_rotate_all += tot_rotate; @@ -3012,10 +3026,8 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, true)) { @@ -3050,13 +3062,10 @@ static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } @@ -3091,13 +3100,10 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } @@ -3133,15 +3139,12 @@ static int edbm_reverse_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { - return OPERATOR_CANCELLED; + continue; } EDBM_update(obedit->data, @@ -4222,7 +4225,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) /* for ED_view3d_project_float_object */ ED_view3d_init_mats_rv3d(obedit, region->regiondata); - /* TODO, investigate using index lookup for screen_vert_coords() rather than a hash table */ + /* TODO: investigate using index lookup for #screen_vert_coords() rather than a hash table. */ /* the floating point coordinates of verts in screen space will be * stored in a hash table according to the vertices pointer */ @@ -5737,7 +5740,7 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op) float *vweights = MEM_mallocN(sizeof(*vweights) * bm->totvert, __func__); { const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); - const int defbase_act = obedit->actdef - 1; + const int defbase_act = BKE_object_defgroup_active_index_get(obedit) - 1; if (use_vertex_group && (cd_dvert_offset == -1)) { BKE_report(op->reports, RPT_WARNING, "No active vertex group"); @@ -5874,7 +5877,7 @@ void MESH_OT_decimate(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* Note, keep in sync with 'rna_def_modifier_decimate' */ + /* NOTE: keep in sync with 'rna_def_modifier_decimate'. */ RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f); RNA_def_boolean(ot->srna, @@ -6558,7 +6561,7 @@ enum { typedef struct BMElemSort { /** Sort factor */ float srt; - /** Original index of this element _in its mempool_ */ + /** Original index of this element (in its #BLI_mempool). */ int org_idx; } BMElemSort; @@ -6751,7 +6754,7 @@ static void sort_bmelem_flag(bContext *C, BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { /* Reverse materials' order, not order of faces inside each mat! */ - /* Note: cannot use totcol, as mat_nr may sometimes be greater... */ + /* NOTE: cannot use totcol, as mat_nr may sometimes be greater... */ float srt = reverse ? (float)(MAXMAT - fa->mat_nr) : (float)fa->mat_nr; pb[i] = false; sb[affected[2]].org_idx = i; @@ -7304,7 +7307,7 @@ static int edbm_bridge_edge_loops_for_single_editmesh(wmOperator *op, BMO_op_exec(em->bm, &bmop); - if (!BMO_error_occurred(em->bm)) { + if (!BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) { /* when merge is used the edges are joined and remain selected */ if (use_merge == false) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -7670,7 +7673,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); /* Hull fails if input is coplanar */ - if (BMO_error_occurred(em->bm)) { + if (BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) { EDBM_op_finish(em, &bmop, op, true); continue; } @@ -8385,7 +8388,7 @@ static void point_normals_update_header(bContext *C, wmOperator *op) ED_area_status_text(CTX_wm_area(C), header); } -/* TODO move that to generic function in BMesh? */ +/* TODO: move that to generic function in BMesh? */ static void bmesh_selected_verts_center_calc(BMesh *bm, float *r_center) { BMVert *v; @@ -9691,7 +9694,7 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) BKE_lnor_space_custom_data_to_normal( bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal); - /* Note: again, this is not true spherical interpolation that normals would need... + /* NOTE: again, this is not true spherical interpolation that normals would need... * But it's probably good enough for now. */ mul_v3_fl(current_normal, 1.0f - factor); mul_v3_fl(smooth_normal[i], factor); diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 112de68b52c..fc9e1aa8b1a 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -33,6 +33,7 @@ #include "BLI_listbase.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_key.h" #include "BKE_layer.h" @@ -671,7 +672,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * em->bm->shapenr = um->shapenr; - EDBM_mesh_free(em); + EDBM_mesh_free_data(em); bm = BM_mesh_create(&allocsize, &((struct BMeshCreateParams){ @@ -681,13 +682,21 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * BM_mesh_bm_from_me(bm, &um->me, (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, + /* Handled with tessellation. */ + .calc_face_normal = false, .active_shapekey = um->shapenr, })); - em_tmp = BKE_editmesh_create(bm, true); + em_tmp = BKE_editmesh_create(bm); *em = *em_tmp; + /* Calculate face normals and tessellation at once since it's multi-threaded. + * The vertex normals are stored in the undo-mesh, so this doesn't need to be updated. */ + BKE_editmesh_looptri_calc_ex(em, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = true, + }); + em->selectmode = um->selectmode; bm->selectmode = um->selectmode; @@ -865,7 +874,7 @@ static void mesh_undosys_step_decode(struct bContext *C, BMEditMesh *em = me->edit_mesh; undomesh_to_editmesh(&elem->data, obedit, em, me->key); em->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 141b69f0465..85c646d689c 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -68,6 +68,9 @@ * just as the undo stack would. * So leaving this as an interface for further work */ +/** + * Save a copy of the #BMesh for restoring later. + */ BMBackup EDBM_redo_state_store(BMEditMesh *em) { BMBackup backup; @@ -75,42 +78,41 @@ BMBackup EDBM_redo_state_store(BMEditMesh *em) return backup; } -void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess) +void EDBM_redo_state_restore(BMBackup *backup, BMEditMesh *em, bool recalc_looptri) { BMesh *tmpbm; - if (!em || !backup.bmcopy) { - return; - } BM_mesh_data_free(em->bm); - tmpbm = BM_mesh_copy(backup.bmcopy); + tmpbm = BM_mesh_copy(backup->bmcopy); *em->bm = *tmpbm; MEM_freeN(tmpbm); tmpbm = NULL; - if (recalctess) { + if (recalc_looptri) { BKE_editmesh_looptri_calc(em); } } -void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) +/** + * Delete the backup, flushing it to an edit-mesh. + */ +void EDBM_redo_state_restore_and_free(BMBackup *backup, BMEditMesh *em, bool recalc_looptri) { - if (em && backup->bmcopy) { - BM_mesh_data_free(em->bm); - *em->bm = *backup->bmcopy; - } - else if (backup->bmcopy) { - BM_mesh_data_free(backup->bmcopy); + BM_mesh_data_free(em->bm); + *em->bm = *backup->bmcopy; + MEM_freeN(backup->bmcopy); + backup->bmcopy = NULL; + if (recalc_looptri) { + BKE_editmesh_looptri_calc(em); } +} +void EDBM_redo_state_free(BMBackup *backup) +{ if (backup->bmcopy) { + BM_mesh_data_free(backup->bmcopy); MEM_freeN(backup->bmcopy); } - backup->bmcopy = NULL; - - if (recalctess && em) { - BKE_editmesh_looptri_calc(em); - } } /** \} */ @@ -132,75 +134,76 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char * return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - va_end(list); return true; } -/* returns 0 on error, 1 on success. executes and finishes a bmesh operator */ +/** + * The return value: + * - False on error (the mesh must not be changed). + * - True on success, executes and finishes a #BMesh operator. + */ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report) { const char *errmsg; - BMO_op_finish(em->bm, bmop); - - if (BMO_error_get(em->bm, &errmsg, NULL)) { - BMEditMesh *emcopy = em->emcopy; +#ifndef NDEBUG + struct { + int verts_len, edges_len, loops_len, faces_len; + } em_state_prev = { + .verts_len = em->bm->totvert, + .edges_len = em->bm->totedge, + .loops_len = em->bm->totloop, + .faces_len = em->bm->totface, + }; +#endif - if (do_report) { - BKE_report(op->reports, RPT_ERROR, errmsg); - } + BMO_op_finish(em->bm, bmop); - EDBM_mesh_free(em); - *em = *emcopy; - - MEM_freeN(emcopy); - em->emcopyusers = 0; - em->emcopy = NULL; - - /** - * Note, we could pass in the mesh, however this is an exceptional case, allow a slow lookup. - * - * This is needed because the COW mesh makes a full copy of the #BMEditMesh - * instead of sharing the pointer, tagging since this has been freed above, - * the #BMEditMesh.emcopy needs to be flushed to the COW edit-mesh, see T55457. - */ - { - Main *bmain = G_MAIN; - for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) { - if (mesh->edit_mesh == em) { - DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE); - break; - } + bool changed = false; + bool changed_was_set = false; + + eBMOpErrorLevel level; + while (BMO_error_pop(em->bm, &errmsg, NULL, &level)) { + ReportType type = RPT_INFO; + switch (level) { + case BMO_ERROR_CANCEL: { + changed_was_set = true; + break; + } + case BMO_ERROR_WARN: { + type = RPT_WARNING; + changed_was_set = true; + changed = true; + break; + } + case BMO_ERROR_FATAL: { + type = RPT_ERROR; + changed_was_set = true; + changed = true; + break; } } - /* when copying, tessellation isn't to for faster copying, - * but means we need to re-tessellate here */ - if (em->looptris == NULL) { - BKE_editmesh_looptri_calc(em); + if (do_report) { + BKE_report(op->reports, type, errmsg); } - - return false; } - - em->emcopyusers--; - if (em->emcopyusers < 0) { - printf("warning: em->emcopyusers was less than zero.\n"); + if (changed_was_set == false) { + changed = true; } - if (em->emcopyusers <= 0) { - BKE_editmesh_free(em->emcopy); - MEM_freeN(em->emcopy); - em->emcopy = NULL; +#ifndef NDEBUG + if (changed == false) { + BLI_assert((em_state_prev.verts_len == em->bm->totvert) && + (em_state_prev.edges_len == em->bm->totedge) && + (em_state_prev.loops_len == em->bm->totloop) && + (em_state_prev.faces_len == em->bm->totface)); } +#endif - return true; + return changed; } bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) @@ -217,11 +220,6 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); va_end(list); @@ -249,11 +247,6 @@ bool EDBM_op_call_and_selectf(BMEditMesh *em, return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out); @@ -284,11 +277,6 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...) return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); va_end(list); @@ -317,17 +305,13 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) if (me->edit_mesh) { /* this happens when switching shape keys */ - EDBM_mesh_free(me->edit_mesh); + EDBM_mesh_free_data(me->edit_mesh); MEM_freeN(me->edit_mesh); } - /* currently executing operators re-tessellates, so we can avoid doing here - * but at some point it may need to be added back. */ -#if 0 - me->edit_mesh = BKE_editmesh_create(bm, true); -#else - me->edit_mesh = BKE_editmesh_create(bm, false); -#endif + /* Executing operators re-tessellates, + * so we can avoid doing here but at some point it may need to be added back. */ + me->edit_mesh = BKE_editmesh_create(bm); me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode; me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0; @@ -338,7 +322,8 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) /** * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates). - * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 + * Most callers should run #DEG_id_tag_update on `ob->data`, see: T46738, T46913. + * This ensures #BKE_object_free_derived_caches runs on all objects that use this mesh. */ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) { @@ -358,25 +343,6 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) .calc_object_remap = true, .update_shapekey_indices = !free_data, })); - - /* Free derived mesh. usually this would happen through depsgraph but there - * are exceptions like file save that will not cause this, and we want to - * avoid ending up with an invalid derived mesh then. - * - * Do it for all objects which shares the same mesh datablock, since their - * derived meshes might also be referencing data which was just freed, - * - * Annoying enough, but currently seems most efficient way to avoid access - * of freed data on scene update, especially in cases when there are dependency - * cycles. - */ -#if 0 - for (Object *other_object = bmain->objects.first; other_object != NULL; other_object = other_object->id.next) { - if (other_object->data == ob->data) { - BKE_object_free_derived_caches(other_object); - } - } -#endif } void EDBM_mesh_clear(BMEditMesh *em) @@ -384,8 +350,8 @@ void EDBM_mesh_clear(BMEditMesh *em) /* clear bmesh */ BM_mesh_clear(em->bm); - /* free derived meshes */ - BKE_editmesh_free_derivedmesh(em); + /* Free evaluated meshes & cache. */ + BKE_editmesh_free_derived_caches(em); /* free tessellation data */ em->tottri = 0; @@ -401,9 +367,9 @@ void EDBM_mesh_load(Main *bmain, Object *ob) } /** - * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free + * Should only be called on the active edit-mesh, otherwise call #BKE_editmesh_free_data. */ -void EDBM_mesh_free(BMEditMesh *em) +void EDBM_mesh_free_data(BMEditMesh *em) { /* These tables aren't used yet, so it's not strictly necessary * to 'end' them but if someone tries to start using them, @@ -411,7 +377,7 @@ void EDBM_mesh_free(BMEditMesh *em) ED_mesh_mirror_spatial_table_end(NULL); ED_mesh_mirror_topo_table_end(NULL); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); } /** \} */ @@ -1472,7 +1438,7 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params) } if (params->is_destructive) { - /* TODO. we may be able to remove this now! - Campbell */ + /* TODO(campbell): we may be able to remove this now! */ // BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP); } else { @@ -1483,8 +1449,8 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params) BM_lnorspace_invalidate(em->bm, false); em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET; } - /* don't keep stale derivedMesh data around, see: T38872. */ - BKE_editmesh_free_derivedmesh(em); + /* Don't keep stale evaluated mesh data around, see: T38872. */ + BKE_editmesh_free_derived_caches(em); #ifdef DEBUG { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 7c6dc6516ed..73b3fb9724e 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -34,6 +34,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_report.h" @@ -252,7 +253,7 @@ void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me) WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } -/* note: keep in sync with ED_mesh_color_add */ +/* NOTE: keep in sync with #ED_mesh_color_add. */ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; @@ -377,7 +378,7 @@ bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name) return false; } -/* note: keep in sync with ED_mesh_uv_texture_add */ +/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; @@ -483,7 +484,7 @@ bool ED_mesh_color_remove_named(Mesh *me, const char *name) /*********************** Sculpt Vertex colors operators ************************/ -/* note: keep in sync with ED_mesh_uv_texture_add */ +/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */ int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c index 25d3eaf11d4..5eb69aab48b 100644 --- a/source/blender/editors/mesh/mesh_mirror.c +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -308,8 +308,9 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em, last = 0; - /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, - * but you can't ever access the last 'a' index of MirrTopoPairs */ + /* Get the pairs out of the sorted hashes. + * NOTE: `totvert + 1` means we can use the previous 2, + * but you can't ever access the last 'a' index of #MirrTopoPairs. */ if (em) { BMVert **vtable = em->bm->vtable; for (a = 1; a <= totvert; a++) { diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index f306612f295..27fb21e1dfb 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -390,7 +390,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* Apply parent transform if the active object's parent was joined to it. - * Note: This doesn't apply recursive parenting. */ + * NOTE: This doesn't apply recursive parenting. */ if (join_parent) { ob->parent = NULL; BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false); @@ -475,16 +475,17 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) me = ob_iter->data; /* Join this object's vertex groups to the base one's */ - for (dg = ob_iter->defbase.first; dg; dg = dg->next) { + for (dg = me->vertex_group_names.first; dg; dg = dg->next) { /* See if this group exists in the object (if it doesn't, add it to the end) */ if (!BKE_object_defgroup_find_name(ob, dg->name)) { odg = MEM_mallocN(sizeof(bDeformGroup), "join deformGroup"); memcpy(odg, dg, sizeof(bDeformGroup)); - BLI_addtail(&ob->defbase, odg); + BLI_addtail(&mesh_active->vertex_group_names, odg); } } - if (ob->defbase.first && ob->actdef == 0) { - ob->actdef = 1; + if (!BLI_listbase_is_empty(&mesh_active->vertex_group_names) && + me->vertex_group_active_index == 0) { + me->vertex_group_active_index = 1; } /* Join this object's face maps to the base one's. */ @@ -1060,7 +1061,7 @@ static float *editmesh_get_mirror_uv( cent_vec[1] = face_cent[1]; } - /* TODO - Optimize */ + /* TODO: Optimize. */ { BMIter iter; BMFace *efa; @@ -1473,19 +1474,21 @@ bool ED_mesh_pick_vert( MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve) { - if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) { + if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH) { Mesh *me = ob->data; - BMesh *bm = me->edit_mesh->bm; - const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); + if (!BLI_listbase_is_empty(&me->vertex_group_names)) { + BMesh *bm = me->edit_mesh->bm; + const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); - if (cd_dvert_offset != -1) { - BMVert *eve = BM_mesh_active_vert_get(bm); + if (cd_dvert_offset != -1) { + BMVert *eve = BM_mesh_active_vert_get(bm); - if (eve) { - if (r_eve) { - *r_eve = eve; + if (eve) { + if (r_eve) { + *r_eve = eve; + } + return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); } - return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); } } } diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index a8b471a7c92..f7b53b5513f 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -215,7 +215,7 @@ static void mball_undosys_step_decode(struct bContext *C, } undomball_to_editmball(&elem->data, mb); mb->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&mb->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 11cf3ea5083..8ae74fbfafa 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -407,7 +407,7 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) "Enter edit mode when adding this object"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } - /* note: this property gets hidden for add-camera operator */ + /* NOTE: this property gets hidden for add-camera operator. */ prop = RNA_def_enum( ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object"); RNA_def_property_update_runtime(prop, view_align_update); @@ -1325,7 +1325,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; bool newob = false; - /* Note: We use 'Y' here (not 'Z'), as */ + /* NOTE: We use 'Y' here (not 'Z'), as. */ WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, NULL, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; @@ -1845,7 +1845,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) * ready to be moved around to re-time the sound and/or make new sound clips. */ { /* create new data for NLA hierarchy */ - AnimData *adt = BKE_animdata_add_id(&ob->id); + AnimData *adt = BKE_animdata_ensure_id(&ob->id); NlaTrack *nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, ob->data); strip->start = CFRA; @@ -1977,7 +1977,7 @@ void OBJECT_OT_pointcloud_add(wmOperatorType *ot) /** \name Delete Object Operator * \{ */ /* remove base from a specific scene */ -/* note: now unlinks constraints as well */ +/* NOTE: now unlinks constraints as well. */ void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob) { if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 && @@ -2163,7 +2163,7 @@ static void copy_object_set_idnew(bContext *C) /** \name Make Instanced Objects Real Operator * \{ */ -/* XXX TODO That whole hierarchy handling based on persistent_id tricks is +/* XXX TODO: That whole hierarchy handling based on persistent_id tricks is * very confusing and convoluted, and it will fail in many cases besides basic ones. * Think this should be replaced by a proper tree-like representation of the instantiations, * should help a lot in both readability, and precise consistent rebuilding of hierarchy. @@ -2442,7 +2442,7 @@ static void make_object_duplilist_real(bContext *C, } if (ob_dst->parent) { - /* note, this may be the parent of other objects, but it should + /* NOTE: this may be the parent of other objects, but it should * still work out ok */ BKE_object_apply_mat4(ob_dst, dob->mat, false, true); @@ -2906,7 +2906,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) } /* make new mesh data from the original copy */ - /* note: get the mesh from the original, not from the copy in some + /* NOTE: get the mesh from the original, not from the copy in some * cases this doesn't give correct results (when MDEF is used for eg) */ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); @@ -3349,8 +3349,8 @@ static Base *object_add_duplicate_internal(Main *bmain, /* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */ /* leaves selection of base/object unaltered. - * note: don't call this within a loop since clear_* funcs loop over the entire database. - * note: caller must do DAG_relations_tag_update(bmain); + * NOTE: don't call this within a loop since clear_* funcs loop over the entire database. + * NOTE: caller must do DAG_relations_tag_update(bmain); * this is not done automatic since we may duplicate many objects in a batch */ Base *ED_object_add_duplicate( Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag) diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index a5cad4e087c..3a10a423e91 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -566,7 +566,7 @@ static int multiresbake_image_exec(bContext *C, wmOperator *op) WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE); WM_jobs_customdata_set(wm_job, bkr, multiresbake_freejob); - WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ + WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO: only draw bake image, can we enforce this. */ WM_jobs_callbacks(wm_job, multiresbake_startjob, NULL, NULL, NULL); G.is_break = false; diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index e941b27879b..233f2a65dac 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -158,7 +158,7 @@ static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) /** * for exec() when there is no render job - * note: this won't check for the escape key being pressed, but doing so isn't thread-safe. + * NOTE: this won't check for the escape key being pressed, but doing so isn't thread-safe. */ static int bake_break(void *UNUSED(rjv)) { @@ -1939,7 +1939,7 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event) WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE); WM_jobs_customdata_set(wm_job, bkr, bake_freejob); - /* TODO - only draw bake image, can we enforce this */ + /* TODO: only draw bake image, can we enforce this. */ WM_jobs_timer( wm_job, 0.5, (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) ? NC_GEOM | ND_DATA : NC_IMAGE, 0); WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index a7aa6b4d6a4..4970338973d 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1731,7 +1731,7 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) /* force depsgraph to get recalculated since relationships removed */ DEG_relations_tag_update(bmain); - /* note, calling BIK_clear_data() isn't needed here */ + /* NOTE: calling BIK_clear_data() isn't needed here. */ return OPERATOR_FINISHED; } @@ -1745,7 +1745,7 @@ void POSE_OT_constraints_clear(wmOperatorType *ot) /* callbacks */ ot->exec = pose_constraints_clear_exec; - /* XXX - do we want to ensure there are selected bones too? */ + /* XXX: do we want to ensure there are selected bones too? */ ot->poll = ED_operator_object_active_local_editable_posemode_exclusive; } @@ -2461,7 +2461,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op)) /* Refresh depsgraph. */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - /* Note, notifier might evolve. */ + /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); } } diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 7b7970fbfe5..6251fb799c5 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -33,6 +33,7 @@ #include "BKE_context.h" #include "BKE_data_transfer.h" +#include "BKE_deform.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_mesh_runtime.h" @@ -96,7 +97,7 @@ static const EnumPropertyItem DT_layer_items[] = { {0, NULL, 0, NULL, NULL}, }; -/* Note: rna_enum_dt_layers_select_src_items enum is from rna_modifier.c */ +/* NOTE: #rna_enum_dt_layers_select_src_items enum is from rna_modifier.c. */ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -122,9 +123,14 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, RNA_enum_items_add_value( &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC); - if (data_type == DT_TYPE_MDEFORMVERT) { - Object *ob_src = CTX_data_active_object(C); + Object *ob_src = CTX_data_active_object(C); + if (ob_src == NULL) { + RNA_enum_item_end(&item, &totitem); + *r_free = true; + return item; + } + if (data_type == DT_TYPE_MDEFORMVERT && BKE_object_supports_vertex_groups(ob_src)) { if (BKE_object_pose_armature_get(ob_src)) { RNA_enum_items_add_value( &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT); @@ -132,66 +138,57 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM); } - if (ob_src) { - bDeformGroup *dg; - int i; + const bDeformGroup *dg; + int i; - RNA_enum_item_add_separator(&item, &totitem); + RNA_enum_item_add_separator(&item, &totitem); - for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) { - tmp_item.value = i; - tmp_item.identifier = tmp_item.name = dg->name; - RNA_enum_item_add(&item, &totitem, &tmp_item); - } + const ListBase *defbase = BKE_object_defgroup_list(ob_src); + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { + tmp_item.value = i; + tmp_item.identifier = tmp_item.name = dg->name; + RNA_enum_item_add(&item, &totitem, &tmp_item); } } else if (data_type == DT_TYPE_SHAPEKEY) { /* TODO */ } else if (data_type == DT_TYPE_UV) { - Object *ob_src = CTX_data_active_object(C); - - if (ob_src) { - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); - CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; - cddata_masks.lmask |= CD_MASK_MLOOPUV; - Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); - int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV); + CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; + cddata_masks.lmask |= CD_MASK_MLOOPUV; + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); + int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV); - RNA_enum_item_add_separator(&item, &totitem); + RNA_enum_item_add_separator(&item, &totitem); - for (int i = 0; i < num_data; i++) { - tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( - &me_eval->ldata, CD_MLOOPUV, i); - RNA_enum_item_add(&item, &totitem, &tmp_item); - } + for (int i = 0; i < num_data; i++) { + tmp_item.value = i; + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( + &me_eval->ldata, CD_MLOOPUV, i); + RNA_enum_item_add(&item, &totitem, &tmp_item); } } else if (data_type == DT_TYPE_VCOL) { - Object *ob_src = CTX_data_active_object(C); - - if (ob_src) { - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src); - CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; - cddata_masks.lmask |= CD_MASK_MLOOPCOL; - Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); - int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL); + CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH; + cddata_masks.lmask |= CD_MASK_MLOOPCOL; + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks); + int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL); - RNA_enum_item_add_separator(&item, &totitem); + RNA_enum_item_add_separator(&item, &totitem); - for (int i = 0; i < num_data; i++) { - tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( - &me_eval->ldata, CD_MLOOPCOL, i); - RNA_enum_item_add(&item, &totitem, &tmp_item); - } + for (int i = 0; i < num_data; i++) { + tmp_item.value = i; + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name( + &me_eval->ldata, CD_MLOOPCOL, i); + RNA_enum_item_add(&item, &totitem, &tmp_item); } } @@ -201,7 +198,7 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C, return item; } -/* Note: rna_enum_dt_layers_select_dst_items enum is from rna_modifier.c */ +/* NOTE: #rna_enum_dt_layers_select_dst_items enum is from `rna_modifier.c`. */ static const EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -255,7 +252,7 @@ static const EnumPropertyItem *dt_layers_select_itemf(bContext *C, return dt_layers_select_src_itemf(C, ptr, prop, r_free); } -/* Note: rna_enum_dt_mix_mode_items enum is from rna_modifier.c */ +/* NOTE: rna_enum_dt_mix_mode_items enum is from `rna_modifier.c`. */ static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -511,7 +508,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op) } #if 0 /* TODO */ - /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */ + /* NOTE: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; #else return OPERATOR_FINISHED; @@ -767,7 +764,7 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot) } /******************************************************************************/ -/* Note: This operator is hybrid, it can work as a usual standalone Object operator, +/* NOTE: This operator is hybrid, it can work as a usual standalone Object operator, * or as a DataTransfer modifier tool. */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 1ca967d9112..6108691b2f1 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -134,8 +134,8 @@ Object *ED_object_context(const bContext *C) return CTX_data_pointer_get_type(C, "object", &RNA_Object).data; } -/* find the correct active object per context - * note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */ +/* Find the correct active object per context. + * NOTE: context can be NULL when called from a enum with #PROP_ENUM_NO_CONTEXT. */ Object *ED_object_active_context(const bContext *C) { Object *ob = NULL; @@ -557,7 +557,7 @@ static bool ED_object_editmode_load_free_ex(Main *bmain, } if (free_data) { - EDBM_mesh_free(me->edit_mesh); + EDBM_mesh_free_data(me->edit_mesh); MEM_freeN(me->edit_mesh); me->edit_mesh = NULL; } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index fcee2818b22..5065a2c00f0 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -105,14 +105,13 @@ static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3]) { - const int cd_dvert_offset = obedit->actdef ? + const int active_index = BKE_object_defgroup_active_index_get(obedit); + const int cd_dvert_offset = active_index ? CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT) : -1; - zero_v3(r_cent); - if (cd_dvert_offset != -1) { - const int defgrp_index = obedit->actdef - 1; + const int defgrp_index = active_index - 1; int totvert = 0; MDeformVert *dvert; @@ -129,7 +128,8 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, } } if (totvert) { - bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index); + const ListBase *defbase = BKE_object_defgroup_list(obedit); + bDeformGroup *dg = BLI_findlink(defbase, defgrp_index); BLI_strncpy(r_name, dg->name, sizeof(dg->name)); mul_v3_fl(r_cent, 1.0f / (float)totvert); return true; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 5bf04e195fe..5a3a28b5a3f 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -247,7 +247,6 @@ void OBJECT_OT_vertex_group_assign_new(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot); -void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 620c58196dd..7bbca7ea9e6 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -2598,7 +2598,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, BLI_bitmap *edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); - /* note: we use EditBones here, easier to set them up and use + /* NOTE: we use EditBones here, easier to set them up and use * edit-armature functions to convert back to regular bones */ for (int v = 0; v < me->totvert; v++) { if (mvert_skin[v].flag & MVERT_SKIN_ROOT) { diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 00ef439c18a..a438c760d3b 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -201,7 +201,6 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_vertex_group_remove_from); WM_operatortype_append(OBJECT_OT_vertex_group_select); WM_operatortype_append(OBJECT_OT_vertex_group_deselect); - WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked); WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected); WM_operatortype_append(OBJECT_OT_vertex_group_copy); WM_operatortype_append(OBJECT_OT_vertex_group_normalize); @@ -322,7 +321,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0); /* Object Mode ---------------------------------------------------------------- */ - /* Note: this keymap gets disabled in non-objectmode. */ + /* NOTE: this keymap gets disabled in non-objectmode. */ keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0); keymap->poll = object_mode_poll; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 15695c4c6f7..c61965b3e23 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -593,7 +593,7 @@ void ED_object_parent_clear(Object *ob, const int type) DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); } -/* note, poll should check for editable scene */ +/* NOTE: poll should check for editable scene. */ static int parent_clear_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -791,8 +791,8 @@ bool ED_object_parent_set(ReportList *reports, * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, * creating the virtual modifiers. */ - ob->partype = PAROBJECT; /* Note: DNA define, not operator property. */ - /* ob->partype = PARSKEL; */ /* Note: DNA define, not operator property. */ + ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */ + /* ob->partype = PARSKEL; */ /* NOTE: DNA define, not operator property. */ /* BUT, to keep the deforms, we need a modifier, * and then we need to set the object that it uses @@ -837,14 +837,14 @@ bool ED_object_parent_set(ReportList *reports, } break; case PAR_BONE: - ob->partype = PARBONE; /* Note: DNA define, not operator property. */ + ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */ if (pchan->bone) { pchan->bone->flag &= ~BONE_RELATIVE_PARENTING; pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING; } break; case PAR_BONE_RELATIVE: - ob->partype = PARBONE; /* Note: DNA define, not operator property. */ + ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */ if (pchan->bone) { pchan->bone->flag |= BONE_RELATIVE_PARENTING; pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING; @@ -860,7 +860,7 @@ bool ED_object_parent_set(ReportList *reports, break; case PAR_OBJECT: case PAR_FOLLOW: - ob->partype = PAROBJECT; /* Note: DNA define, not operator property. */ + ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */ break; } @@ -1248,7 +1248,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op) /* set parenting type for object - object only... */ ob->parent = par; - ob->partype = PAROBJECT; /* note, dna define, not operator property */ + ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */ } } } @@ -1298,7 +1298,7 @@ static const EnumPropertyItem prop_clear_track_types[] = { {0, NULL, 0, NULL, NULL}, }; -/* note, poll should check for editable scene */ +/* NOTE: poll should check for editable scene. */ static int object_track_clear_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -2022,7 +2022,7 @@ static void single_obdata_users( break; default: printf("ERROR %s: can't copy %s\n", __func__, id->name); - BLI_assert(!"This should never happen."); + BLI_assert_msg(0, "This should never happen."); /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */ BKE_scene_objects_iterator_end(&iter_macro); @@ -2061,6 +2061,23 @@ static void single_object_action_users( FOREACH_OBJECT_FLAG_END; } +static void single_objectdata_action_users( + Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) +{ + FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { + if (!ID_IS_LINKED(ob) && ob->data != NULL) { + ID *id_obdata = (ID *)ob->data; + AnimData *adt = BKE_animdata_from_id(id_obdata); + ID *id_act = (ID *)adt->action; + if (id_act && id_act->us > 1) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + BKE_animdata_copy_id_action(bmain, id_obdata); + } + } + } + FOREACH_OBJECT_FLAG_END; +} + static void single_mat_users( Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) { @@ -2236,7 +2253,7 @@ static int make_local_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "type"); int a; - /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ + /* NOTE: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ if (mode == MAKE_LOCAL_ALL) { ViewLayer *view_layer = CTX_data_view_layer(C); Collection *collection = CTX_data_collection(C); @@ -2643,6 +2660,10 @@ static int make_single_user_exec(bContext *C, wmOperator *op) single_object_action_users(bmain, scene, view_layer, v3d, flag); } + if (RNA_boolean_get(op->ptr, "obdata_animation")) { + single_objectdata_action_users(bmain, scene, view_layer, v3d, flag); + } + BKE_main_id_newptr_and_tag_clear(bmain); WM_event_add_notifier(C, NC_WINDOW, NULL); @@ -2684,8 +2705,16 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects"); RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data"); RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block"); - RNA_def_boolean( - ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object"); + RNA_def_boolean(ot->srna, + "animation", + 0, + "Object Animation", + "Make object animation data local to each object"); + RNA_def_boolean(ot->srna, + "obdata_animation", + 0, + "Object Data Animation", + "Make object data (mesh, curve etc.) animation data local to each object"); } /** \} */ diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 1a0c5a6a83f..eb37aebcff2 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -295,7 +295,7 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_ return false; } - /* TODO, use 'reveal_hidden', as is done with bones. */ + /* TODO: use 'reveal_hidden', as is done with bones. */ if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) { /* Select if not selected. */ @@ -1496,7 +1496,7 @@ void OBJECT_OT_select_random(wmOperatorType *ot) ot->idname = "OBJECT_OT_select_random"; /* api callbacks */ - /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/ + /*ot->invoke = object_select_random_invoke XXX: need a number popup ;*/ ot->exec = object_select_random_exec; ot->poll = objects_selectable_poll; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index d1e912b2f37..4c4727f51ee 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1152,51 +1152,53 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) for (int object_index = 0; object_index < num_objects; object_index++) { Object *ob = objects[object_index]; + if (ob->flag & OB_DONE) { + continue; + } - if ((ob->flag & OB_DONE) == 0) { - bool do_inverse_offset = false; - ob->flag |= OB_DONE; + bool do_inverse_offset = false; + ob->flag |= OB_DONE; - if (centermode == ORIGIN_TO_CURSOR) { - copy_v3_v3(cent, cursor); - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + copy_v3_v3(cent, cursor); + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->imat, cent); + } - if (ob->data == NULL) { - /* special support for dupligroups */ - if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && - (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) { - if (ID_IS_LINKED(ob->instance_collection)) { - tot_lib_error++; + if (ob->data == NULL) { + /* special support for dupligroups */ + if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && + (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) { + if (ID_IS_LINKED(ob->instance_collection)) { + tot_lib_error++; + } + else { + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else { - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else { - float min[3], max[3]; - /* only bounds support */ - INIT_MINMAX(min, max); - BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); - mid_v3_v3v3(cent, min, max); - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, cent); - } + float min[3], max[3]; + /* only bounds support */ + INIT_MINMAX(min, max); + BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); + mid_v3_v3v3(cent, min, max); + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->imat, cent); + } - add_v3_v3(ob->instance_collection->instance_offset, cent); + add_v3_v3(ob->instance_collection->instance_offset, cent); - tot_change++; - ob->instance_collection->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } + tot_change++; + ob->instance_collection->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; } } - else if (ID_IS_LINKED(ob->data)) { - tot_lib_error++; - } - - if (obedit == NULL && ob->type == OB_MESH) { + } + else if (ID_IS_LINKED(ob->data)) { + tot_lib_error++; + } + else if (ob->type == OB_MESH) { + if (obedit == NULL) { Mesh *me = ob->data; if (centermode == ORIGIN_TO_CURSOR) { @@ -1222,265 +1224,265 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) me->id.tag |= LIB_TAG_DOIT; do_inverse_offset = true; } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - Curve *cu = ob->data; + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + Curve *cu = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_curve_center_bounds(cu, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_curve_center_median(cu, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_curve_center_bounds(cu, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_curve_center_median(cu, cent); + } - /* don't allow Z change if curve is 2D */ - if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { - cent[2] = 0.0; - } + /* don't allow Z change if curve is 2D */ + if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { + cent[2] = 0.0; + } - negate_v3_v3(cent_neg, cent); - BKE_curve_translate(cu, cent_neg, 1); + negate_v3_v3(cent_neg, cent); + BKE_curve_translate(cu, cent_neg, 1); - tot_change++; - cu->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; + tot_change++; + cu->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; - if (obedit) { - if (centermode == GEOMETRY_TO_ORIGIN) { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - break; + if (obedit) { + if (centermode == GEOMETRY_TO_ORIGIN) { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } + break; } - else if (ob->type == OB_FONT) { - /* Get from bounding-box. */ + } + else if (ob->type == OB_FONT) { + /* Get from bounding-box. */ - Curve *cu = ob->data; + Curve *cu = ob->data; - if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) { - /* Do nothing. */ + if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) { + /* Do nothing. */ + } + else { + if (centermode == ORIGIN_TO_CURSOR) { + /* Done. */ } else { - if (centermode == ORIGIN_TO_CURSOR) { - /* Done. */ - } - else { - /* extra 0.5 is the height o above line */ - cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]); - cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]); - } + /* extra 0.5 is the height o above line */ + cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]); + cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]); + } - cent[2] = 0.0f; + cent[2] = 0.0f; - cu->xof = cu->xof - cent[0]; - cu->yof = cu->yof - cent[1]; + cu->xof = cu->xof - cent[0]; + cu->yof = cu->yof - cent[1]; - tot_change++; - cu->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } + tot_change++; + cu->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; } - else if (ob->type == OB_ARMATURE) { - bArmature *arm = ob->data; + } + else if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; - if (ID_REAL_USERS(arm) > 1) { + if (ID_REAL_USERS(arm) > 1) { #if 0 BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature"); return; #endif - tot_multiuser_arm_error++; - } - else { - /* Function to recenter armatures in editarmature.c - * Bone + object locations are handled there. - */ - ED_armature_origin_set(bmain, ob, cursor, centermode, around); + tot_multiuser_arm_error++; + } + else { + /* Function to recenter armatures in editarmature.c + * Bone + object locations are handled there. + */ + ED_armature_origin_set(bmain, ob, cursor, centermode, around); - tot_change++; - arm->id.tag |= LIB_TAG_DOIT; - /* do_inverse_offset = true; */ /* docenter_armature() handles this */ + tot_change++; + arm->id.tag |= LIB_TAG_DOIT; + /* do_inverse_offset = true; */ /* docenter_armature() handles this */ - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_transform_copy(ob_eval, ob); - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_object_where_is_calc(depsgraph, scene, ob_eval); - BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */ + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_transform_copy(ob_eval, ob); + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_object_where_is_calc(depsgraph, scene, ob_eval); + BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */ - ignore_parent_tx(bmain, depsgraph, scene, ob); + ignore_parent_tx(bmain, depsgraph, scene, ob); - if (obedit) { - break; - } + if (obedit) { + break; } } - else if (ob->type == OB_MBALL) { - MetaBall *mb = ob->data; + } + else if (ob->type == OB_MBALL) { + MetaBall *mb = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_mball_center_bounds(mb, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_mball_center_median(mb, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_mball_center_bounds(mb, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_mball_center_median(mb, cent); + } - negate_v3_v3(cent_neg, cent); - BKE_mball_translate(mb, cent_neg); + negate_v3_v3(cent_neg, cent); + BKE_mball_translate(mb, cent_neg); - tot_change++; - mb->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; + tot_change++; + mb->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; - if (obedit) { - if (centermode == GEOMETRY_TO_ORIGIN) { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - break; + if (obedit) { + if (centermode == GEOMETRY_TO_ORIGIN) { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } + break; } - else if (ob->type == OB_LATTICE) { - Lattice *lt = ob->data; + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { - /* done */ - } - else if (around == V3D_AROUND_CENTER_BOUNDS) { - BKE_lattice_center_bounds(lt, cent); - } - else { /* #V3D_AROUND_CENTER_MEDIAN. */ - BKE_lattice_center_median(lt, cent); - } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (around == V3D_AROUND_CENTER_BOUNDS) { + BKE_lattice_center_bounds(lt, cent); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_lattice_center_median(lt, cent); + } - negate_v3_v3(cent_neg, cent); - BKE_lattice_translate(lt, cent_neg, 1); + negate_v3_v3(cent_neg, cent); + BKE_lattice_translate(lt, cent_neg, 1); - tot_change++; - lt->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; - } - else if (ob->type == OB_GPENCIL) { - bGPdata *gpd = ob->data; - float gpcenter[3]; - if (gpd) { - if (centermode == ORIGIN_TO_GEOMETRY) { - zero_v3(gpcenter); - BKE_gpencil_centroid_3d(gpd, gpcenter); - add_v3_v3(gpcenter, ob->obmat[3]); - } - if (centermode == ORIGIN_TO_CURSOR) { - copy_v3_v3(gpcenter, cursor); - } - if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) { - bGPDspoint *pt; - float imat[3][3], bmat[3][3]; - float offset_global[3]; - float offset_local[3]; - int i; - - sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]); - copy_m3_m4(bmat, obact->obmat); - invert_m3_m3(imat, bmat); - mul_m3_v3(imat, offset_global); - mul_v3_m3v3(offset_local, imat, offset_global); - - float diff_mat[4][4]; - float inverse_diff_mat[4][4]; - - /* recalculate all strokes - * (all layers are considered without evaluating lock attributes) */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* calculate difference matrix */ - BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); - /* undo matrix */ - invert_m4_m4(inverse_diff_mat, diff_mat); - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - float mpt[3]; - mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); - sub_v3_v3(mpt, offset_local); - mul_v3_m4v3(&pt->x, diff_mat, mpt); - } + tot_change++; + lt->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; + } + else if (ob->type == OB_GPENCIL) { + bGPdata *gpd = ob->data; + float gpcenter[3]; + if (gpd) { + if (centermode == ORIGIN_TO_GEOMETRY) { + zero_v3(gpcenter); + BKE_gpencil_centroid_3d(gpd, gpcenter); + add_v3_v3(gpcenter, ob->obmat[3]); + } + if (centermode == ORIGIN_TO_CURSOR) { + copy_v3_v3(gpcenter, cursor); + } + if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) { + bGPDspoint *pt; + float imat[3][3], bmat[3][3]; + float offset_global[3]; + float offset_local[3]; + int i; + + sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]); + copy_m3_m4(bmat, obact->obmat); + invert_m3_m3(imat, bmat); + mul_m3_v3(imat, offset_global); + mul_v3_m3v3(offset_local, imat, offset_global); + + float diff_mat[4][4]; + float inverse_diff_mat[4][4]; + + /* recalculate all strokes + * (all layers are considered without evaluating lock attributes) */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* calculate difference matrix */ + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + /* undo matrix */ + invert_m4_m4(inverse_diff_mat, diff_mat); + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + float mpt[3]; + mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); + sub_v3_v3(mpt, offset_local); + mul_v3_m4v3(&pt->x, diff_mat, mpt); } } } - tot_change++; - if (centermode == ORIGIN_TO_GEOMETRY) { - copy_v3_v3(ob->loc, gpcenter); - } - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - - ob->id.tag |= LIB_TAG_DOIT; - do_inverse_offset = true; } - else { - BKE_report(op->reports, - RPT_WARNING, - "Grease Pencil Object does not support this set origin option"); + tot_change++; + if (centermode == ORIGIN_TO_GEOMETRY) { + copy_v3_v3(ob->loc, gpcenter); } + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + + ob->id.tag |= LIB_TAG_DOIT; + do_inverse_offset = true; + } + else { + BKE_report(op->reports, + RPT_WARNING, + "Grease Pencil Object does not support this set origin option"); } } + } - /* offset other selected objects */ - if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { - float obmat[4][4]; + /* offset other selected objects */ + if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { + float obmat[4][4]; - /* was the object data modified - * note: the functions above must set 'cent' */ + /* was the object data modified + * NOTE: the functions above must set 'cent'. */ - /* convert the offset to parent space */ - BKE_object_to_mat4(ob, obmat); - mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ + /* convert the offset to parent space */ + BKE_object_to_mat4(ob, obmat); + mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ - add_v3_v3(ob->loc, centn); + add_v3_v3(ob->loc, centn); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_transform_copy(ob_eval, ob); - BKE_object_where_is_calc(depsgraph, scene, ob_eval); - if (ob->type == OB_ARMATURE) { - /* needed for bone parents */ - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_pose_where_is(depsgraph, scene, ob_eval); - } - - ignore_parent_tx(bmain, depsgraph, scene, ob); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_transform_copy(ob_eval, ob); + BKE_object_where_is_calc(depsgraph, scene, ob_eval); + if (ob->type == OB_ARMATURE) { + /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_pose_where_is(depsgraph, scene, ob_eval); + } - /* other users? */ - // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) - //{ - - /* use existing context looper */ - for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) { - Object *ob_other = objects[other_object_index]; - - if ((ob_other->flag & OB_DONE) == 0 && - ((ob->data && (ob->data == ob_other->data)) || - (ob->instance_collection == ob_other->instance_collection && - (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) { - ob_other->flag |= OB_DONE; - DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - - mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ - add_v3_v3(ob_other->loc, centn); - - Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other); - BKE_object_transform_copy(ob_other_eval, ob_other); - BKE_object_where_is_calc(depsgraph, scene, ob_other_eval); - if (ob_other->type == OB_ARMATURE) { - /* needed for bone parents */ - BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); - BKE_pose_where_is(depsgraph, scene, ob_other_eval); - } - ignore_parent_tx(bmain, depsgraph, scene, ob_other); + ignore_parent_tx(bmain, depsgraph, scene, ob); + + /* other users? */ + // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) + //{ + + /* use existing context looper */ + for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) { + Object *ob_other = objects[other_object_index]; + + if ((ob_other->flag & OB_DONE) == 0 && + ((ob->data && (ob->data == ob_other->data)) || + (ob->instance_collection == ob_other->instance_collection && + (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) { + ob_other->flag |= OB_DONE; + DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + + mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ + add_v3_v3(ob_other->loc, centn); + + Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other); + BKE_object_transform_copy(ob_other_eval, ob_other); + BKE_object_where_is_calc(depsgraph, scene, ob_other_eval); + if (ob_other->type == OB_ARMATURE) { + /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); + BKE_pose_where_is(depsgraph, scene, ob_other_eval); } + ignore_parent_tx(bmain, depsgraph, scene, ob_other); } - // CTX_DATA_END; } + // CTX_DATA_END; } } MEM_freeN(objects); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index e6cde60e9aa..f64f95c5322 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -130,7 +130,7 @@ bool ED_vgroup_sync_from_pose(Object *ob) if (arm->act_bone) { int def_num = BKE_object_defgroup_name_index(ob, arm->act_bone->name); if (def_num != -1) { - ob->actdef = def_num + 1; + BKE_object_defgroup_active_index_set(ob, def_num + 1); return true; } } @@ -389,11 +389,16 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) int dvert_tot_from; int dvert_tot; int i; - int defbase_tot_from = BLI_listbase_count(&ob_from->defbase); - int defbase_tot = BLI_listbase_count(&ob->defbase); + ListBase *defbase_dst = BKE_object_defgroup_list_mutable(ob); + const ListBase *defbase_src = BKE_object_defgroup_list(ob_from); + + int defbase_tot_from = BLI_listbase_count(defbase_src); + int defbase_tot = BLI_listbase_count(defbase_dst); bool new_vgroup = false; - if (ob == ob_from) { + BLI_assert(ob != ob_from); + + if (ob->data == ob_from->data) { return true; } @@ -429,9 +434,9 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) } /* do the copy */ - BLI_freelistN(&ob->defbase); - BLI_duplicatelist(&ob->defbase, &ob_from->defbase); - ob->actdef = ob_from->actdef; + BLI_freelistN(defbase_dst); + BLI_duplicatelist(defbase_dst, defbase_src); + BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_active_index_get(ob_from)); if (defbase_tot_from < defbase_tot) { /* correct vgroup indices because the number of vgroups is being reduced. */ @@ -509,7 +514,7 @@ void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array, } } -/* TODO, cache flip data to speedup calls within a loop. */ +/* TODO: cache flip data to speedup calls within a loop. */ static void mesh_defvert_mirror_update_internal(Object *ob, MDeformVert *dvert_dst, MDeformVert *dvert_src, @@ -882,7 +887,8 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, /* add the vert to the deform group with the * specified assign mode */ - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); MDeformVert *dv = NULL; int tot; @@ -913,7 +919,8 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) /* TODO(campbell): This is slow in a loop, better pass def_nr directly, * but leave for later. */ - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); if (def_nr != -1) { MDeformVert *dvert = NULL; @@ -989,7 +996,8 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum) { - const int def_nr = BLI_findindex(&ob->defbase, dg); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int def_nr = BLI_findindex(defbase, dg); if (def_nr == -1) { return -1; @@ -1000,9 +1008,9 @@ float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum) void ED_vgroup_select_by_name(Object *ob, const char *name) { - /* note: ob->actdef==0 signals on painting to create a new one, + /* NOTE: actdef==0 signals on painting to create a new one, * if a bone in posemode is selected */ - ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1; + BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_name_index(ob, name) + 1); } /** \} */ @@ -1014,9 +1022,10 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) { - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_findlink(defbase, def_nr)) { return; } @@ -1111,7 +1120,9 @@ static void vgroup_duplicate(Object *ob) MDeformVert **dvert_array = NULL; int i, idg, icdg, dvert_tot = 0; - dg = BLI_findlink(&ob->defbase, (ob->actdef - 1)); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if (!dg) { return; } @@ -1127,13 +1138,13 @@ static void vgroup_duplicate(Object *ob) BLI_strncpy(cdg->name, name, sizeof(cdg->name)); BKE_object_defgroup_unique_name(cdg, ob); - BLI_addtail(&ob->defbase, cdg); + BLI_addtail(defbase, cdg); - idg = (ob->actdef - 1); - ob->actdef = BLI_listbase_count(&ob->defbase); - icdg = (ob->actdef - 1); + idg = BKE_object_defgroup_active_index_get(ob) - 1; + BKE_object_defgroup_active_index_set(ob, BLI_listbase_count(defbase)); + icdg = BKE_object_defgroup_active_index_get(ob) - 1; - /* TODO, we might want to allow only copy selected verts here? - campbell */ + /* TODO(campbell): we might want to allow only copy selected verts here? */ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); if (dvert_array) { @@ -1157,11 +1168,12 @@ static bool vgroup_normalize(Object *ob) MDeformWeight *dw; MDeformVert *dv, **dvert_array = NULL; int dvert_tot = 0; - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const bool use_vert_sel = vertex_group_use_vert_sel(ob); - if (!BLI_findlink(&ob->defbase, def_nr)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_findlink(defbase, def_nr)) { return false; } @@ -1639,7 +1651,7 @@ static bool vgroup_normalize_all(Object *ob, { MDeformVert *dv, **dvert_array = NULL; int i, dvert_tot = 0; - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const bool use_vert_sel = vertex_group_use_vert_sel(ob); @@ -1651,7 +1663,8 @@ static bool vgroup_normalize_all(Object *ob, ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { - const int defbase_tot = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const int defbase_tot = BLI_listbase_count(defbase); bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot); bool changed = false; @@ -1742,7 +1755,7 @@ static const EnumPropertyItem vgroup_lock_mask[] = { static bool *vgroup_selected_get(Object *ob) { - int sel_count = 0, defbase_tot = BLI_listbase_count(&ob->defbase); + int sel_count = 0, defbase_tot = BKE_object_defgroup_count(ob); bool *mask; if (ob->mode & OB_MODE_WEIGHT_PAINT) { @@ -1759,8 +1772,9 @@ static bool *vgroup_selected_get(Object *ob) mask = MEM_callocN(defbase_tot * sizeof(bool), __func__); } - if (sel_count == 0 && ob->actdef >= 1 && ob->actdef <= defbase_tot) { - mask[ob->actdef - 1] = true; + const int actdef = BKE_object_defgroup_active_index_get(ob); + if (sel_count == 0 && actdef >= 1 && actdef <= defbase_tot) { + mask[actdef - 1] = true; } return mask; @@ -1775,11 +1789,12 @@ static void vgroup_lock_all(Object *ob, int action, int mask) if (mask != VGROUP_MASK_ALL) { selected = vgroup_selected_get(ob); } + const ListBase *defbase = BKE_object_defgroup_list(ob); if (action == VGROUP_TOGGLE) { action = VGROUP_LOCK; - for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { switch (mask) { case VGROUP_MASK_INVERT_UNSELECTED: case VGROUP_MASK_SELECTED: @@ -1802,7 +1817,7 @@ static void vgroup_lock_all(Object *ob, int action, int mask) } } - for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { switch (mask) { case VGROUP_MASK_SELECTED: if (!selected[i]) { @@ -2352,8 +2367,8 @@ static void dvert_mirror_op(MDeformVert *dvert, } } -/* TODO, vgroup locking */ -/* TODO, face masking */ +/* TODO: vgroup locking. */ +/* TODO: face masking. */ void ED_vgroup_mirror(Object *ob, const bool mirror_weights, const bool flip_vgroups, @@ -2379,13 +2394,15 @@ void ED_vgroup_mirror(Object *ob, MDeformVert *dvert, *dvert_mirr; char sel, sel_mirr; int *flip_map = NULL, flip_map_len; - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; int totmirr = 0, totfail = 0; *r_totmirr = *r_totfail = 0; + const ListBase *defbase = BKE_object_defgroup_list(ob); + if ((mirror_weights == false && flip_vgroups == false) || - (BLI_findlink(&ob->defbase, def_nr) == NULL)) { + (BLI_findlink(defbase, def_nr) == NULL)) { return; } @@ -2569,7 +2586,8 @@ cleanup: static void vgroup_delete_active(Object *ob) { - bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if (!dg) { return; } @@ -2580,9 +2598,10 @@ static void vgroup_delete_active(Object *ob) /* only in editmode */ static void vgroup_assign_verts(Object *ob, const float weight) { - const int def_nr = ob->actdef - 1; + const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_findlink(defbase, def_nr)) { return; } @@ -2700,7 +2719,8 @@ static bool vertex_group_poll_ex(bContext *C, Object *ob) return false; } - if (BLI_listbase_is_empty(&ob->defbase)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (BLI_listbase_is_empty(defbase)) { CTX_wm_operator_poll_msg_set(C, "Object has no vertex groups"); return false; } @@ -2823,8 +2843,10 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C) return false; } - if (ob->actdef != 0) { - bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1); + const int def_nr = BKE_object_defgroup_active_index_get(ob); + if (def_nr != 0) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + const bDeformGroup *dg = BLI_findlink(defbase, def_nr - 1); if (dg) { return !(dg->flag & DG_LOCK_WEIGHT); } @@ -3025,8 +3047,8 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) } } else { - bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1); - + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) { return OPERATOR_CANCELLED; } @@ -3774,7 +3796,7 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - /* note, would normally return canceled, except we want the redo + /* NOTE: would normally return canceled, except we want the redo * UI to show up for users to change */ return OPERATOR_FINISHED; } @@ -3860,55 +3882,6 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Vertex Group Copy to Linked Operator - * \{ */ - -static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - Object *ob_active = ED_object_context(C); - int retval = OPERATOR_CANCELLED; - - FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) { - if (ob_iter->type == ob_active->type) { - if (ob_iter != ob_active && ob_iter->data == ob_active->data) { - BLI_freelistN(&ob_iter->defbase); - BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase); - ob_iter->actdef = ob_active->actdef; - - DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter); - WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data); - - retval = OPERATOR_FINISHED; - } - } - } - FOREACH_SCENE_OBJECT_END; - - return retval; -} - -void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Copy Vertex Groups to Linked"; - ot->idname = "OBJECT_OT_vertex_group_copy_to_linked"; - ot->description = - "Replace vertex groups of all users of the same geometry data by vertex groups of active " - "object"; - - /* api callbacks */ - ot->poll = vertex_group_poll; - ot->exec = vertex_group_copy_to_linked_exec; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Vertex Group Copy to Selected Operator * \{ */ @@ -3919,7 +3892,7 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) int fail = 0; CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - if (obact != ob) { + if (obact != ob && BKE_object_supports_vertex_groups(ob)) { if (ED_vgroup_array_copy(ob, obact)) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); DEG_relations_tag_update(CTX_data_main(C)); @@ -3936,8 +3909,8 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) if ((changed_tot == 0 && fail == 0) || fail) { BKE_reportf(op->reports, RPT_ERROR, - "Copy vertex groups to selected: %d done, %d failed (object data must have " - "matching indices)", + "Copy vertex groups to selected: %d done, %d failed (object data must support " + "vertex groups and have matching indices)", changed_tot, fail); } @@ -3972,7 +3945,7 @@ static int set_active_group_exec(bContext *C, wmOperator *op) int nr = RNA_enum_get(op->ptr, "group"); BLI_assert(nr + 1 >= 0); - ob->actdef = nr + 1; + BKE_object_defgroup_active_index_set(ob, nr + 1); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); @@ -3999,7 +3972,8 @@ static const EnumPropertyItem *vgroup_itemf(bContext *C, return DummyRNA_NULL_items; } - for (a = 0, def = ob->defbase.first; def; def = def->next, a++) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + for (a = 0, def = defbase->first; def; def = def->next, a++) { tmp.value = a; tmp.icon = ICON_GROUP_VERTEX; tmp.identifier = def->name; @@ -4048,13 +4022,13 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot) * with the order of vgroups then call vgroup_do_remap after */ static char *vgroup_init_remap(Object *ob) { - bDeformGroup *def; - int defbase_tot = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + int defbase_tot = BLI_listbase_count(defbase); char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups"); char *name; name = name_array; - for (def = ob->defbase.first; def; def = def->next) { + for (const bDeformGroup *def = defbase->first; def; def = def->next) { BLI_strncpy(name, def->name, MAX_VGROUP_NAME); name += MAX_VGROUP_NAME; } @@ -4065,8 +4039,9 @@ static char *vgroup_init_remap(Object *ob) static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) { MDeformVert *dvert = NULL; - bDeformGroup *def; - int defbase_tot = BLI_listbase_count(&ob->defbase); + const bDeformGroup *def; + const ListBase *defbase = BKE_object_defgroup_list(ob); + int defbase_tot = BLI_listbase_count(defbase); /* Needs a dummy index at the start. */ int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups"); @@ -4076,8 +4051,8 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) int i; name = name_array; - for (def = ob->defbase.first, i = 0; def; def = def->next, i++) { - sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)); + for (def = defbase->first, i = 0; def; def = def->next, i++) { + sort_map[i] = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name)); name += MAX_VGROUP_NAME; BLI_assert(sort_map[i] != -1); @@ -4130,8 +4105,9 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) sort_map_update[0] = 0; BKE_object_defgroup_remap_update_users(ob, sort_map_update); - BLI_assert(sort_map_update[ob->actdef] >= 0); - ob->actdef = sort_map_update[ob->actdef]; + BLI_assert(sort_map_update[BKE_object_defgroup_active_index_get(ob)] >= 0); + BKE_object_defgroup_active_index_set(ob, + sort_map_update[BKE_object_defgroup_active_index_get(ob)]); MEM_freeN(sort_map_update); @@ -4159,6 +4135,7 @@ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) bonebase = &armature->bonebase; } } + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); if (bonebase != NULL) { Bone *bone; @@ -4167,8 +4144,8 @@ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) vgroup_sort_bone_hierarchy(ob, &bone->childbase); if (dg != NULL) { - BLI_remlink(&ob->defbase, dg); - BLI_addhead(&ob->defbase, dg); + BLI_remlink(defbase, dg); + BLI_addhead(defbase, dg); } } } @@ -4189,10 +4166,12 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op) /* Init remapping. */ name_array = vgroup_init_remap(ob); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + /* Sort vgroup names. */ switch (sort_type) { case SORT_TYPE_NAME: - BLI_listbase_sort(&ob->defbase, vgroup_sort_name); + BLI_listbase_sort(defbase, vgroup_sort_name); break; case SORT_TYPE_BONEHIERARCHY: vgroup_sort_bone_hierarchy(ob, NULL); @@ -4250,14 +4229,16 @@ static int vgroup_move_exec(bContext *C, wmOperator *op) int dir = RNA_enum_get(op->ptr, "direction"); int ret = OPERATOR_FINISHED; - def = BLI_findlink(&ob->defbase, ob->actdef - 1); + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + def = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); if (!def) { return OPERATOR_CANCELLED; } name_array = vgroup_init_remap(ob); - if (BLI_listbase_link_move(&ob->defbase, def, dir)) { + if (BLI_listbase_link_move(defbase, def, dir)) { ret = vgroup_do_remap(ob, name_array, op); if (ret != OPERATOR_CANCELLED) { @@ -4376,7 +4357,8 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) static bool check_vertex_group_accessible(wmOperator *op, Object *ob, int def_nr) { - bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, def_nr); if (!dg) { BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index"); @@ -4498,7 +4480,7 @@ static int vertex_weight_set_active_exec(bContext *C, wmOperator *op) const int wg_index = RNA_int_get(op->ptr, "weight_group"); if (wg_index != -1) { - ob->actdef = wg_index + 1; + BKE_object_defgroup_active_index_set(ob, wg_index + 1); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 3f15d572cdd..f2bbd6d5084 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -300,7 +300,7 @@ static void pe_update_hair_particle_edit_pointers(PTCacheEdit *edit) /* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set * - * note: this function runs on poll, therefore it can runs many times a second + * NOTE: this function runs on poll, therefore it can runs many times a second * keep it fast! */ static PTCacheEdit *pe_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob, bool create) { @@ -537,7 +537,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data) static bool PE_create_shape_tree(PEData *data, Object *shapeob) { Object *shapeob_eval = DEG_get_evaluated_object(data->depsgraph, shapeob); - Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval); + const Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval); memset(&data->shape_bvh, 0, sizeof(data->shape_bvh)); @@ -631,7 +631,7 @@ static bool key_inside_circle(const PEData *data, float rad, const float co[3], float dx, dy, dist; int screen_co[2]; - /* TODO, should this check V3D_PROJ_TEST_CLIP_BB too? */ + /* TODO: should this check V3D_PROJ_TEST_CLIP_BB too? */ if (ED_view3d_project_int_global(data->vc.region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) { return 0; @@ -5444,7 +5444,7 @@ void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, O edit = PE_create_current(depsgraph, scene, ob); /* Mesh may have changed since last entering editmode. - * note, this may have run before if the edit data was just created, + * NOTE: this may have run before if the edit data was just created, * so could avoid this and speed up a little. */ if (edit && edit->psys) { /* Make sure pointer to the evaluated modifier data is up to date, diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 6bcc9df16bf..387d10d538b 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -848,7 +848,8 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, copy_m4_m4(imat, target_ob->obmat); } else { - /* note: using target_dm here, which is in target_ob object space and has full modifiers */ + /* NOTE: using target_dm here, which is in target_ob object space and has full modifiers. + */ psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat); invert_m4_m4(imat, hairmat); } @@ -1160,7 +1161,7 @@ static bool copy_particle_systems_to_object(const bContext *C, } MEM_freeN(tmp_psys); - /* note: do this after creating DM copies for all the particle system modifiers, + /* NOTE: do this after creating DM copies for all the particle system modifiers, * the remapping otherwise makes final_dm invalid! */ for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0; psys; diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index d39570857ab..d5ad5a5eb84 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -121,7 +121,7 @@ static bool image_buffer_calc_tile_rect(const RenderResult *rr, { int tile_y, tile_height, tile_x, tile_width; - /* if renrect argument, we only refresh scanlines */ + /* When `renrect` argument is not NULL, we only refresh scan-lines. */ if (renrect) { /* if (tile_height == recty), rendering of layer is ready, * we should not draw, other things happen... */ @@ -793,7 +793,7 @@ static int render_breakjob(void *rjv) /** * For exec() when there is no render job - * note: this won't check for the escape key being pressed, but doing so isn't thread-safe. + * NOTE: this won't check for the escape key being pressed, but doing so isn't thread-safe. */ static int render_break(void *UNUSED(rjv)) { diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index f36ce7408b5..5aa63ac56d8 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -54,7 +54,9 @@ #include "DNA_space_types.h" #include "DNA_world_types.h" +#include "BKE_animsys.h" #include "BKE_appdir.h" +#include "BKE_armature.h" #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -93,6 +95,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "ED_armature.h" #include "ED_datafiles.h" #include "ED_render.h" #include "ED_screen.h" @@ -151,6 +154,10 @@ typedef struct IconPreview { void *owner; ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */ ListBase sizes; + + /* May be NULL, is used for rendering IDs that require some other object for it to be applied on + * before the ID can be represented as an image, for example when rendering an Action. */ + struct Object *active_object; } IconPreview; /** \} */ @@ -253,7 +260,7 @@ static const char *preview_collection_name(const char pr_type) case MA_ATMOS: return "Atmosphere"; default: - BLI_assert(!"Unknown preview type"); + BLI_assert_msg(0, "Unknown preview type"); return ""; } } @@ -335,7 +342,7 @@ static ID *duplicate_ids(ID *id, const bool allow_failure) return NULL; default: if (!allow_failure) { - BLI_assert(!"ID type preview not supported."); + BLI_assert_msg(0, "ID type preview not supported."); } return NULL; } @@ -794,7 +801,7 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview NULL, NULL, err_out); - /* TODO color-management? */ + /* TODO: color-management? */ U.pixelsize = pixelsize_old; @@ -813,9 +820,50 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview /** \name Action Preview * \{ */ -/* Render a pose. It is assumed that the pose has already been applied and that the scene camera is - * capturing the pose. In other words, this function just renders from the scene camera without - * evaluating the Action stored in preview->id. */ +static struct PoseBackup *action_preview_render_prepare(IconPreview *preview) +{ + Object *object = preview->active_object; + if (object == NULL) { + WM_report(RPT_WARNING, "No active object, unable to apply the Action before rendering"); + return NULL; + } + if (object->pose == NULL) { + WM_reportf(RPT_WARNING, + "Object %s has no pose, unable to apply the Action before rendering", + object->id.name + 2); + return NULL; + } + + /* Create a backup of the current pose. */ + struct bAction *action = (struct bAction *)preview->id; + struct PoseBackup *pose_backup = ED_pose_backup_create_all_bones(object, action); + + /* Apply the Action as pose, so that it can be rendered. This assumes the Action represents a + * single pose, and that thus the evaluation time doesn't matter. */ + AnimationEvalContext anim_eval_context = {preview->depsgraph, 0.0f}; + BKE_pose_apply_action_all_bones(object, action, &anim_eval_context); + + /* Force evaluation of the new pose, before the preview is rendered. */ + DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); + DEG_evaluate_on_refresh(preview->depsgraph); + + return pose_backup; +} + +static void action_preview_render_cleanup(IconPreview *preview, struct PoseBackup *pose_backup) +{ + if (pose_backup == NULL) { + return; + } + ED_pose_backup_restore(pose_backup); + ED_pose_backup_free(pose_backup); + + DEG_id_tag_update(&preview->active_object->id, ID_RECALC_GEOMETRY); +} + +/* Render a pose from the scene camera. It is assumed that the scene camera is + * capturing the pose. The pose is applied temporarily to the current object + * before rendering. */ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview_sized) { char err_out[256] = ""; @@ -827,6 +875,9 @@ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview BLI_assert(depsgraph != NULL); BLI_assert(preview->scene == DEG_get_input_scene(depsgraph)); + /* Apply the pose before getting the evaluated scene, so that the new pose is evaluated. */ + struct PoseBackup *pose_backup = action_preview_render_prepare(preview); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *camera_eval = scene_eval->camera; if (camera_eval == NULL) { @@ -850,6 +901,8 @@ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview NULL, err_out); + action_preview_render_cleanup(preview, pose_backup); + if (err_out[0] != '\0') { printf("Error rendering Action %s preview: %s\n", preview->id->name + 2, err_out); } @@ -1255,8 +1308,9 @@ static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect) scaledy = (float)h; } - ex = (short)scaledx; - ey = (short)scaledy; + /* Scaling down must never assign zero width/height, see: T89868. */ + ex = MAX2(1, (short)scaledx); + ey = MAX2(1, (short)scaledy); dx = (w - ex) / 2; dy = (h - ey) / 2; @@ -1469,7 +1523,7 @@ static int icon_previewimg_size_index_get(const IconPreviewSize *icon_size, } } - BLI_assert(!"The searched icon size does not match any in the preview image"); + BLI_assert_msg(0, "The searched icon size does not match any in the preview image"); return -1; } @@ -1625,6 +1679,7 @@ void ED_preview_icon_render( /* Control isn't given back to the caller until the preview is done. So we don't need to copy * the ID to avoid thread races. */ ip.id_copy = duplicate_ids(id, true); + ip.active_object = CTX_data_active_object(C); icon_preview_add_size(&ip, rect, sizex, sizey); @@ -1666,6 +1721,7 @@ void ED_preview_icon_job( ip->bmain = CTX_data_main(C); ip->depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ip->scene = DEG_get_input_scene(ip->depsgraph); + ip->active_object = CTX_data_active_object(C); ip->owner = owner; ip->id = id; ip->id_copy = duplicate_ids(id, false); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index ae9f80f746a..d2b1ebdad78 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -294,7 +294,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) } else { /* Find the first matching material. - * Note: there may be multiple but that's not a common use case. */ + * NOTE: there may be multiple but that's not a common use case. */ for (int i = 0; i < ob->totcol; i++) { const Material *mat = BKE_object_material_get(ob, i + 1); if (mat_active == mat) { @@ -401,7 +401,7 @@ static int material_slot_de_select(bContext *C, bool select) } else { /* Find the first matching material. - * Note: there may be multiple but that's not a common use case. */ + * NOTE: there may be multiple but that's not a common use case. */ for (int i = 0; i < ob->totcol; i++) { const Material *mat = BKE_object_material_get(ob, i + 1); if (mat_active == mat) { @@ -1183,7 +1183,7 @@ static int light_cache_bake_exec(bContext *C, wmOperator *op) G.is_break = false; - /* TODO abort if selected engine is not eevee. */ + /* TODO: abort if selected engine is not eevee. */ void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra); light_cache_bake_tag_cache(scene, op); @@ -2418,7 +2418,7 @@ static void paste_mtex_copybuf(ID *id) mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]); break; default: - BLI_assert(!"invalid id type"); + BLI_assert_msg(0, "invalid id type"); return; } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 175efc5387b..c351ade9954 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -161,6 +161,12 @@ void ED_region_do_listen(wmRegionListenerParams *params) if (region->type && region->type->listener) { region->type->listener(params); } + + LISTBASE_FOREACH (uiList *, list, ®ion->ui_lists) { + if (list->type && list->type->listener) { + list->type->listener(list, params); + } + } } /* only exported for WM */ @@ -1539,8 +1545,8 @@ static void region_rect_recursive( region->winx = BLI_rcti_size_x(®ion->winrct) + 1; region->winy = BLI_rcti_size_y(®ion->winrct) + 1; - /* if region opened normally, we store this for hide/reveal usage */ - /* prevent rounding errors for UI_DPI_FAC mult and divide */ + /* If region opened normally, we store this for hide/reveal usage. */ + /* Prevent rounding errors for UI_DPI_FAC multiply and divide. */ if (region->winx > 1) { region->sizex = (region->winx + 0.5f) / UI_DPI_FAC; } @@ -1680,7 +1686,7 @@ static void ed_default_handlers( { BLI_assert(region ? (®ion->handlers == handlers) : (&area->handlers == handlers)); - /* note, add-handler checks if it already exists */ + /* NOTE: add-handler checks if it already exists. */ /* XXX it would be good to have boundbox checks for some of these... */ if (flag & ED_KEYMAP_UI) { @@ -2081,7 +2087,7 @@ void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free) } BKE_spacedata_copylist(&area_dst->spacedata, &area_src->spacedata); - /* Note; SPACE_EMPTY is possible on new screens */ + /* NOTE: SPACE_EMPTY is possible on new screens. */ /* regions */ if (do_free) { @@ -3018,6 +3024,8 @@ void ED_region_panels_layout_ex(const bContext *C, y = -y; } + UI_blocklist_update_view_for_buttons(C, ®ion->uiblocks); + if (update_tot_size) { /* this also changes the 'cur' */ UI_view2d_totRect_set(v2d, x, y); @@ -3672,7 +3680,7 @@ static void region_visible_rect_calc(ARegion *region, rcti *rect) /* Skip floating. */ } else { - BLI_assert(!"Region overlap with unknown alignment"); + BLI_assert_msg(0, "Region overlap with unknown alignment"); } } } diff --git a/source/blender/editors/screen/area_query.c b/source/blender/editors/screen/area_query.c index d569e56e11b..fd4f3964398 100644 --- a/source/blender/editors/screen/area_query.c +++ b/source/blender/editors/screen/area_query.c @@ -88,7 +88,7 @@ bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_re r_region_gutter->xmin = r_region_gutter->xmax - category_tabs_width; } else { - BLI_assert(!"Unsupported alignment"); + BLI_assert_msg(0, "Unsupported alignment"); } return true; } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index e366760a55d..f651fd4fb61 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -126,7 +126,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, components = 1; } else { - BLI_assert(!"Incompatible format passed to immDrawPixels"); + BLI_assert_msg(0, "Incompatible format passed to immDrawPixels"); return; } @@ -426,7 +426,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, format = GPU_RGBA16F; } else { - BLI_assert(!"Incompatible number of channels for GLSL display"); + BLI_assert_msg(0, "Incompatible number of channels for GLSL display"); } if (format != 0) { diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 45cf1775ccb..3ce2f326dca 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -36,6 +36,7 @@ #include "DNA_sequence_types.h" #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "BLI_ghash.h" #include "BLI_listbase.h" @@ -111,6 +112,8 @@ const char *screen_context_dir[] = { "selected_editable_fcurves", "active_editable_fcurve", "selected_editable_keyframes", + "ui_list", + "asset_library", NULL, }; @@ -896,11 +899,11 @@ static eContextResult screen_ctx_active_operator(const bContext *C, bContextData /* do nothing */ } else { - /* note, this checks poll, could be a problem, but this also + /* NOTE: this checks poll, could be a problem, but this also * happens for the toolbar */ op = WM_operator_last_redo(C); } - /* TODO, get the operator from popup's */ + /* TODO: get the operator from popup's. */ if (op && op->ptr) { CTX_data_pointer_set(result, NULL, &RNA_Operator, op); @@ -1024,6 +1027,23 @@ static eContextResult screen_ctx_selected_editable_keyframes(const bContext *C, return CTX_RESULT_NO_DATA; } +static eContextResult screen_ctx_asset_library(const bContext *C, bContextDataResult *result) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + CTX_data_pointer_set( + result, &workspace->id, &RNA_AssetLibraryReference, &workspace->active_asset_library); + return CTX_RESULT_OK; +} + +static eContextResult screen_ctx_ui_list(const bContext *C, bContextDataResult *result) +{ + wmWindow *win = CTX_wm_window(C); + ARegion *region = CTX_wm_region(C); + uiList *list = UI_list_find_mouse_over(region, win->eventstate); + CTX_data_pointer_set(result, NULL, &RNA_UIList, list); + return CTX_RESULT_OK; +} + /* Registry of context callback functions. */ typedef eContextResult (*context_callback)(const bContext *C, bContextDataResult *result); @@ -1098,6 +1118,8 @@ static void ensure_ed_screen_context_functions(void) register_context_function("selected_visible_fcurves", screen_ctx_selected_visible_fcurves); register_context_function("active_editable_fcurve", screen_ctx_active_editable_fcurve); register_context_function("selected_editable_keyframes", screen_ctx_selected_editable_keyframes); + register_context_function("asset_library", screen_ctx_asset_library); + register_context_function("ui_list", screen_ctx_ui_list); } /* Entry point for the screen context. */ diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index e2d95035ba8..2a81fcfde8f 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -125,9 +125,9 @@ ScrArea *area_split(const wmWindow *win, return NULL; } - /* note regarding (fac > 0.5f) checks below. + /* NOTE(campbell): regarding (fac > 0.5f) checks below. * normally it shouldn't matter which is used since the copy should match the original - * however with viewport rendering and python console this isn't the case. - campbell */ + * however with viewport rendering and python console this isn't the case. */ if (dir_axis == SCREEN_AXIS_H) { /* new vertices */ @@ -1683,7 +1683,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable) sad->region = CTX_wm_region(C); /* If start-frame is larger than current frame, we put current-frame on start-frame. - * note: first frame then is not drawn! (ton) */ + * NOTE(ton): first frame then is not drawn! */ if (PRVRANGEON) { if (scene->r.psfra > scene->r.cfra) { sad->sfra = scene->r.cfra; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 159b649ec71..ffeaf514642 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2792,9 +2792,9 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) } CLAMP(rmd->region->sizey, 0, rmd->maxsize); - /* note, 'UI_UNIT_Y/4' means you need to drag the footer and execute region + /* NOTE: `UI_UNIT_Y / 4` means you need to drag the footer and execute region * almost all the way down for it to become hidden, this is done - * otherwise its too easy to do this by accident */ + * otherwise its too easy to do this by accident. */ if (size_no_snap < (UI_UNIT_Y / 4) / aspect) { rmd->region->sizey = rmd->origval; if (!(rmd->region->flag & RGN_FLAG_HIDDEN)) { @@ -5219,7 +5219,7 @@ static void SCREEN_OT_delete(wmOperatorType *ot) /* -------------------------------------------------------------------- */ /** \name Region Alpha Blending Operator * - * Implementation note: a disappearing region needs at least 1 last draw with + * Implementation NOTE: a disappearing region needs at least 1 last draw with * 100% back-buffer texture over it - then triple buffer will clear it entirely. * This because flag #RGN_FLAG_HIDDEN is set in end - region doesn't draw at all then. * diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 324fd5d3075..39d776e0054 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -176,7 +176,7 @@ void imapaint_image_update( ibuf->userflags |= IB_MIPMAP_INVALID; } - /* todo: should set_tpage create ->rect? */ + /* TODO: should set_tpage create ->rect? */ if (texpaint || (sima && sima->lock)) { int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; @@ -681,7 +681,7 @@ static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mou { PaintOperation *pop; - /* TODO Should avoid putting this here. Instead, last position should be requested + /* TODO: Should avoid putting this here. Instead, last position should be requested * from stroke system. */ if (!(pop = texture_paint_init(C, op, mouse))) { diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 392f39bbb94..23b90171a1d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -784,11 +784,10 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s, bool do_random = false; bool do_partial_update = false; - bool update_color = ((brush->flag & BRUSH_USE_GRADIENT) && - ((ELEM(brush->gradient_stroke_mode, - BRUSH_GRADIENT_SPACING_REPEAT, - BRUSH_GRADIENT_SPACING_CLAMP)) || - (cache->last_pressure != pressure))); + bool update_color = ((brush->flag & BRUSH_USE_GRADIENT) && (ELEM(brush->gradient_stroke_mode, + BRUSH_GRADIENT_SPACING_REPEAT, + BRUSH_GRADIENT_SPACING_CLAMP) || + (cache->last_pressure != pressure))); float tex_rotation = -brush->mtex.rot; float mask_rotation = -brush->mask_mtex.rot; @@ -1248,7 +1247,7 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short paint static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, const int *pos) { - /* note: allocImbuf returns zero'd memory, so regions outside image will + /* NOTE: allocImbuf returns zero'd memory, so regions outside image will * have zero alpha, and hence not be blended onto the image */ int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1]; ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 2437e0d1939..bd05d309421 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -930,7 +930,7 @@ static bool project_bucket_point_occluded(const ProjPaintState *ps, } if (isect_ret >= 1) { - /* TODO - we may want to cache the first hit, + /* TODO: we may want to cache the first hit, * it is not possible to swap the face order in the list anymore */ return true; } @@ -1661,7 +1661,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps, const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index]; const float *lt_other_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other)}; - /* BKE_image_acquire_ibuf - TODO - this may be slow */ + /* #BKE_image_acquire_ibuf - TODO: this may be slow. */ uchar rgba_ub[4]; float rgba_f[4]; @@ -1768,7 +1768,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps, angle_cos = dot_v3v3(viewDirPersp, no); } - /* If backface culling is disabled, allow painting on back faces. */ + /* If back-face culling is disabled, allow painting on back faces. */ if (!ps->do_backfacecull) { angle_cos = fabsf(angle_cos); } @@ -1959,7 +1959,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps, const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)}; - /* BKE_image_acquire_ibuf - TODO - this may be slow */ + /* #BKE_image_acquire_ibuf - TODO: this may be slow. */ if (ibuf->rect_float) { if (ibuf_other->rect_float) { /* from float to float */ @@ -2052,7 +2052,7 @@ static bool line_clip_rect2f(const rctf *cliprect, float l2_clip[2]) { /* first account for horizontal, then vertical lines */ - /* horiz */ + /* Horizontal. */ if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) { /* is the line out of range on its Y axis? */ if (l1[1] < rect->ymin || l1[1] > rect->ymax) { @@ -3160,7 +3160,7 @@ static void project_paint_face_init(const ProjPaintState *ps, //#endif } -#if 0 /* TODO - investigate why this doesn't work sometimes! it should! */ +#if 0 /* TODO: investigate why this doesn't work sometimes! it should! */ /* no intersection for this entire row, * after some intersection above means we can quit now */ if (has_x_isect == 0 && has_isect) { @@ -3401,7 +3401,7 @@ static void project_paint_face_init(const ProjPaintState *ps, } } -# if 0 /* TODO - investigate why this doesn't work sometimes! it should! */ +# if 0 /* TODO: investigate why this doesn't work sometimes! it should! */ /* no intersection for this entire row, * after some intersection above means we can quit now */ if (has_x_isect == 0 && has_isect) { @@ -3432,8 +3432,8 @@ static void project_paint_bucket_bounds(const ProjPaintState *ps, { /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */ - /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f - * is always truncated to 1, is this really correct?? - jwilkins */ + /* XXX(jwilkins ): the offset of 0.5 is always truncated to zero and the offset of 1.5f + * is always truncated to 1, is this really correct? */ /* these offsets of 0.5 and 1.5 seem odd but they are correct */ bucketMin[0] = @@ -3553,18 +3553,18 @@ static void project_bucket_init(const ProjPaintState *ps, ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT; } -/* We want to know if a bucket and a face overlap in screen-space +/* We want to know if a bucket and a face overlap in screen-space. * - * Note, if this ever returns false positives its not that bad, since a face in the bounding area + * NOTE: if this ever returns false positives its not that bad, since a face in the bounding area * will have its pixels calculated when it might not be needed later, (at the moment at least) - * obviously it shouldn't have bugs though */ + * obviously it shouldn't have bugs though. */ static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MLoopTri *lt) { - /* TODO - replace this with a trickier method that uses side-of-line for all + /* TODO: replace this with a trickier method that uses side-of-line for all * #ProjPaintState.screenCoords edges against the closest bucket corner. */ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)}; rctf bucket_bounds; @@ -3611,7 +3611,7 @@ static bool project_bucket_face_isect(ProjPaintState *ps, } /* Add faces to the bucket but don't initialize its pixels - * TODO - when painting occluded, sort the faces on their min-Z + * TODO: when painting occluded, sort the faces on their min-Z * and only add faces that faces that are not occluded */ static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri *lt, @@ -3824,7 +3824,7 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } else { - /* TODO - deal with cases where 1 side of a face goes behind the view ? + /* TODO: deal with cases where 1 side of a face goes behind the view ? * * After some research this is actually very tricky, only option is to * clip the derived mesh before painting, which is a Pain */ @@ -4358,7 +4358,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, #endif // PROJ_DEBUG_WINCLIP - /* backface culls individual triangles but mask normal will use polygon */ + /* Back-face culls individual triangles but mask normal will use polygon. */ if (ps->do_backfacecull) { if (ps->do_mask_normal) { if (prev_poly != lt->poly) { @@ -4696,7 +4696,7 @@ static bool project_image_refresh_tagged(ProjPaintState *ps) /* look over each bound cell */ for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) { pr = &(projIma->partRedrawRect[i]); - if (pr->x2 != -1) { /* TODO - use 'enabled' ? */ + if (pr->x2 != -1) { /* TODO: use 'enabled' ? */ set_imapaintpartial(pr); imapaint_image_update(NULL, projIma->ima, projIma->ibuf, &projIma->iuser, true); redraw = 1; @@ -5393,7 +5393,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v samplecos[2] = 0.0f; } - /* note, for clone and smear, + /* NOTE: for clone and smear, * we only use the alpha, could be a special function */ BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index da34723eed4..d968b6cc319 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -293,8 +293,8 @@ typedef struct SculptGestureContext { /* These store the view origin and normal in world space, which is used in some gestures to * generate geometry aligned from the view directly in world space. */ /* World space view origin and normal are not affected by object symmetry when doing symmetry - * passes, so there is no separate variables with the true_ prefix to store their original values - * without symmetry modifications. */ + * passes, so there is no separate variables with the `true_` prefix to store their original + * values without symmetry modifications. */ float world_space_view_origin[3]; float world_space_view_normal[3]; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index e2b21145c2d..f08771292a8 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -1307,7 +1307,7 @@ void ED_operatortypes_paint(void) WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect); WM_operatortype_append(BRUSH_OT_stencil_reset_transform); - /* note, particle uses a different system, can be added with existing operators in wm.py */ + /* NOTE: particle uses a different system, can be added with existing operators in `wm.py`. */ WM_operatortype_append(PAINT_OT_brush_select); /* image */ diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 2484f382ed4..709e04d807d 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -752,7 +752,7 @@ static int vert_select_ungrouped_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); Mesh *me = ob->data; - if (BLI_listbase_is_empty(&ob->defbase) || (me->dvert == NULL)) { + if (BLI_listbase_is_empty(&me->vertex_group_names) || (me->dvert == NULL)) { BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index fe36d62b832..9387b84f437 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -179,7 +179,7 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev, * (without evaluating modifiers) */ static bool vertex_paint_use_fast_update_check(Object *ob) { - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); if (me_eval != NULL) { Mesh *me = BKE_mesh_from_object(ob); @@ -996,7 +996,7 @@ static void do_weight_paint_vertex_multi( dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized); if (curw == 0.0f) { - /* note: no weight to assign to this vertex, could add all groups? */ + /* NOTE: no weight to assign to this vertex, could add all groups? */ return; } @@ -1607,13 +1607,13 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo /* check if we are attempting to paint onto a locked vertex group, * and other options disallow it from doing anything useful */ bDeformGroup *dg; - dg = BLI_findlink(&ob->defbase, vgroup_index.active); + dg = BLI_findlink(&me->vertex_group_names, vgroup_index.active); if (dg->flag & DG_LOCK_WEIGHT) { BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting"); return false; } if (vgroup_index.mirror != -1) { - dg = BLI_findlink(&ob->defbase, vgroup_index.mirror); + dg = BLI_findlink(&me->vertex_group_names, vgroup_index.mirror); if (dg->flag & DG_LOCK_WEIGHT) { BKE_report(op->reports, RPT_WARNING, "Mirror group is locked, aborting"); return false; @@ -1622,7 +1622,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo } /* check that multipaint groups are unlocked */ - defbase_tot = BLI_listbase_count(&ob->defbase); + defbase_tot = BLI_listbase_count(&me->vertex_group_names); defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_tot_sel); if (ts->multipaint && defbase_tot_sel > 1) { @@ -1636,7 +1636,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo for (i = 0; i < defbase_tot; i++) { if (defbase_sel[i]) { - dg = BLI_findlink(&ob->defbase, i); + dg = BLI_findlink(&me->vertex_group_names, i); if (dg->flag & DG_LOCK_WEIGHT) { BKE_report(op->reports, RPT_WARNING, "Multipaint group is locked, aborting"); MEM_freeN(defbase_sel); @@ -2025,7 +2025,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const Brush *brush = data->brush; const StrokeCache *cache = ss->cache; - /* note: normally `BKE_brush_weight_get(scene, brush)` is used, + /* NOTE: normally `BKE_brush_weight_get(scene, brush)` is used, * however in this case we calculate a new weight each time. */ const float paintweight = data->strength; float brush_size_pressure, brush_alpha_value, brush_alpha_pressure; @@ -2046,7 +2046,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Note: grids are 1:1 with corners (aka loops). + /* NOTE: grids are 1:1 with corners (aka loops). * For multires, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : @@ -2498,7 +2498,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) for (psys = ob->particlesystem.first; psys; psys = psys->next) { for (i = 0; i < PSYS_TOT_VG; i++) { - if (psys->vgroup[i] == ob->actdef) { + if (psys->vgroup[i] == BKE_object_defgroup_active_index_get(ob)) { psys->recalc |= ID_RECALC_PSYS_RESET; break; } @@ -2885,7 +2885,7 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Note: Grids are 1:1 with corners (aka loops). + /* NOTE: Grids are 1:1 with corners (aka loops). * For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : @@ -2912,7 +2912,7 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata, /* If we're painting with a texture, sample the texture color and alpha. */ float tex_alpha = 1.0; if (data->vpd->is_texbrush) { - /* Note: we may want to paint alpha as vertex color alpha. */ + /* NOTE: we may want to paint alpha as vertex color alpha. */ tex_alpha = tex_color_alpha_ubyte( data, data->vpd->vertexcosnos[v_index].co, &color_final); } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c index 96d22fe4a21..9f023dd6e63 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c @@ -149,7 +149,7 @@ static bool vertex_paint_from_weight(Object *ob) /* TODO: respect selection. */ /* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway. */ mp = me->mpoly; - vgroup_active = ob->actdef - 1; + vgroup_active = me->vertex_group_active_index - 1; for (int i = 0; i < me->totpoly; i++, mp++) { MLoopCol *lcol = &me->mloopcol[mp->loopstart]; uint j = 0; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index 7991987ae1f..cb8dc838422 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -183,7 +183,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); - if (me && me->dvert && vc.v3d && vc.rv3d && (vc.obact->actdef != 0)) { + if (me && me->dvert && vc.v3d && vc.rv3d && (me->vertex_group_active_index != 0)) { const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int v_idx_best = -1; uint index; @@ -213,9 +213,9 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even if (v_idx_best != -1) { /* should always be valid */ ToolSettings *ts = vc.scene->toolsettings; Brush *brush = BKE_paint_brush(&ts->wpaint->paint); - const int vgroup_active = vc.obact->actdef - 1; + const int vgroup_active = me->vertex_group_active_index - 1; float vgroup_weight = BKE_defvert_find_weight(&me->dvert[v_idx_best], vgroup_active); - const int defbase_tot = BLI_listbase_count(&vc.obact->defbase); + const int defbase_tot = BLI_listbase_count(&me->vertex_group_names); bool use_lock_relative = ts->wpaint_lock_relative; bool *defbase_locked = NULL, *defbase_unlocked = NULL; @@ -331,8 +331,8 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); - if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) { - const int defbase_tot = BLI_listbase_count(&vc.obact->defbase); + if (me && me->dvert && vc.v3d && vc.rv3d && me->vertex_group_names.first) { + const int defbase_tot = BLI_listbase_count(&me->vertex_group_names); const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups"); bool found = false; @@ -372,7 +372,7 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, int totitem = 0; int i = 0; bDeformGroup *dg; - for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) { + for (dg = me->vertex_group_names.first; dg && i < defbase_tot; i++, dg = dg->next) { if (groups[i]) { item_tmp.identifier = item_tmp.name = dg->name; item_tmp.value = i; @@ -401,14 +401,14 @@ static int weight_sample_group_exec(bContext *C, wmOperator *op) ED_view3d_viewcontext_init(C, &vc, depsgraph); BLI_assert(type + 1 >= 0); - vc.obact->actdef = type + 1; + BKE_object_defgroup_active_index_set(vc.obact, type + 1); DEG_id_tag_update(&vc.obact->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact); return OPERATOR_FINISHED; } -/* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active +/* TODO: we could make this a menu into OBJECT_OT_vertex_group_set_active * rather than its own operator */ void PAINT_OT_weight_sample_group(wmOperatorType *ot) { @@ -458,7 +458,7 @@ static bool weight_paint_set(Object *ob, float paintweight) return false; } - vgroup_active = ob->actdef - 1; + vgroup_active = BKE_object_defgroup_active_index_get(ob) - 1; /* if mirror painting, find the other group */ if (ME_USING_MIRROR_X_VERTEX_GROUPS(me)) { @@ -540,7 +540,7 @@ static int weight_paint_set_exec(bContext *C, wmOperator *op) } if (weight_paint_set(obact, vgroup_weight)) { - ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */ + ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */ return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; @@ -815,7 +815,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) data.sco_start = sco_start; data.sco_end = sco_end; data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end); - data.def_nr = ob->actdef - 1; + data.def_nr = BKE_object_defgroup_active_index_get(ob) - 1; data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0; data.vert_cache = vert_cache; data.vert_visit = NULL; @@ -863,7 +863,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) } if (scene->toolsettings->auto_normalize) { - const int vgroup_num = BLI_listbase_count(&ob->defbase); + const int vgroup_num = BLI_listbase_count(&me->vertex_group_names); bool *vgroup_validmap = BKE_object_defgroup_validmap_get(ob, vgroup_num); if (vgroup_validmap != NULL) { MDeformVert *dvert = me->dvert; @@ -891,7 +891,7 @@ static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEve if (ret & OPERATOR_RUNNING_MODAL) { struct ARegion *region = CTX_wm_region(C); if (region->regiontype == RGN_TYPE_WINDOW) { - /* TODO, hardcoded, extend WM_gesture_straightline_ */ + /* TODO: hard-coded, extend `WM_gesture_straightline_*`. */ if (event->type == LEFTMOUSE && event->val == KM_PRESS) { wmGesture *gesture = op->customdata; gesture->is_active = true; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c index d6a118bbd59..19ffa0c952d 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c @@ -79,8 +79,10 @@ bool ED_wpaint_ensure_data(bContext *C, WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } + const ListBase *defbase = BKE_object_defgroup_list(ob); + /* this happens on a Bone select, when no vgroup existed yet */ - if (ob->actdef <= 0) { + if (me->vertex_group_active_index <= 0) { Object *modob; if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) { Bone *actbone = ((bArmature *)modob->data)->act_bone; @@ -94,32 +96,33 @@ bool ED_wpaint_ensure_data(bContext *C, DEG_relations_tag_update(CTX_data_main(C)); } else { - int actdef = 1 + BLI_findindex(&ob->defbase, dg); + + int actdef = 1 + BLI_findindex(defbase, dg); BLI_assert(actdef >= 0); - ob->actdef = actdef; + me->vertex_group_active_index = actdef; } } } } } - if (BLI_listbase_is_empty(&ob->defbase)) { + if (BLI_listbase_is_empty(defbase)) { BKE_object_defgroup_add(ob); DEG_relations_tag_update(CTX_data_main(C)); } /* ensure we don't try paint onto an invalid group */ - if (ob->actdef <= 0) { + if (me->vertex_group_active_index <= 0) { BKE_report(reports, RPT_WARNING, "No active vertex group for painting, aborting"); return false; } if (vgroup_index) { - vgroup_index->active = ob->actdef - 1; + vgroup_index->active = me->vertex_group_active_index - 1; } if (flag & WPAINT_ENSURE_MIRROR) { if (ME_USING_MIRROR_X_VERTEX_GROUPS(me)) { - int mirror = ED_wpaint_mirror_vgroup_ensure(ob, ob->actdef - 1); + int mirror = ED_wpaint_mirror_vgroup_ensure(ob, me->vertex_group_active_index - 1); if (vgroup_index) { vgroup_index->mirror = mirror; } @@ -133,7 +136,8 @@ bool ED_wpaint_ensure_data(bContext *C, /* mirror_vgroup is set to -1 when invalid */ int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active) { - bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *defgroup = BLI_findlink(defbase, vgroup_active); if (defgroup) { int mirrdef; @@ -143,7 +147,7 @@ int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active) mirrdef = BKE_object_defgroup_name_index(ob, name_flip); if (mirrdef == -1) { if (BKE_object_defgroup_new(ob, name_flip)) { - mirrdef = BLI_listbase_count(&ob->defbase) - 1; + mirrdef = BLI_listbase_count(defbase) - 1; } } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index ab5c46f4bc5..83388c1aef2 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2394,7 +2394,7 @@ static float brush_strength(const Sculpt *sd, case BRUSH_MASK_SMOOTH: return alpha * pressure * feather; } - BLI_assert(!"Not supposed to happen"); + BLI_assert_msg(0, "Not supposed to happen"); return 0.0f; case SCULPT_TOOL_CREASE: @@ -3316,7 +3316,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, bstrength); - /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise + /* XXX: this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise * initialize before threads so they can do curve mapping. */ BKE_curvemapping_init(brush->curve); @@ -3395,7 +3395,7 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, bstrength); - /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise + /* XXX: this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise * initialize before threads so they can do curve mapping. */ BKE_curvemapping_init(brush->curve); @@ -5791,7 +5791,7 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) BKE_keyblock_update_from_vertcos(ob, kb, vertCos); } -/* Note: we do the topology update before any brush actions to avoid +/* NOTE: we do the topology update before any brush actions to avoid * issues with the proxies. The size of the proxy can't change, so * topology must be updated first. */ static void sculpt_topology_update(Sculpt *sd, @@ -6362,7 +6362,7 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used) MEM_SAFE_FREE(nodes); /* Modifiers could depend on mesh normals, so we should update them. - * Note, then if sculpting happens on locked key, normals should be re-calculate after applying + * NOTE: then if sculpting happens on locked key, normals should be re-calculate after applying * coords from key-block on base mesh. */ BKE_mesh_calc_normals(me); } @@ -7874,7 +7874,7 @@ static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2]) { /* Don't start the stroke until mouse goes over the mesh. - * note: mouse will only be null when re-executing the saved stroke. + * NOTE: mouse will only be null when re-executing the saved stroke. * We have exception for 'exec' strokes since they may not set 'mouse', * only 'location', see: T52195. */ if (((op->flag & OP_IS_INVOKE) == 0) || (mouse == NULL) || diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index 5f5fb51d75f..35f48400fe2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -209,7 +209,7 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au Brush *brush = BKE_paint_brush(&sd->paint); if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { - BLI_assert(!"Topology masking: pmap missing"); + BLI_assert_msg(0, "Topology masking: pmap missing"); return NULL; } @@ -248,7 +248,7 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a } if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { - BLI_assert(!"Face Sets automasking: pmap missing"); + BLI_assert_msg(0, "Face Sets automasking: pmap missing"); return NULL; } @@ -273,7 +273,7 @@ float *SCULPT_boundary_automasking_init(Object *ob, SculptSession *ss = ob->sculpt; if (!ss->pmap) { - BLI_assert(!"Boundary Edges masking: pmap missing"); + BLI_assert_msg(0, "Boundary Edges masking: pmap missing"); return NULL; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 43704c73faf..696c3332a2b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -704,7 +704,7 @@ typedef struct SculptThreadedTaskData { /* Data specific to some callbacks. */ - /* Note: even if only one or two of those are used at a time, + /* NOTE: even if only one or two of those are used at a time, * keeping them separated, names help figuring out * what it is, and memory overhead is ridiculous anyway. */ float flippedbstrength; diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 61984610a5a..eabbfe43e03 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -367,7 +367,7 @@ void SCULPT_smooth(Sculpt *sd, last = max_iterations * (bstrength - count * fract); if (type == PBVH_FACES && !ss->pmap) { - BLI_assert(!"sculpt smooth: pmap missing"); + BLI_assert_msg(0, "sculpt smooth: pmap missing"); return; } diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 71166b7c20c..501a1e53276 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -766,7 +766,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: - BLI_assert(!"Dynamic topology should've already been handled"); + BLI_assert_msg(0, "Dynamic topology should've already been handled"); break; } } @@ -1065,7 +1065,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: - BLI_assert(!"Dynamic topology should've already been handled"); + BLI_assert_msg(0, "Dynamic topology should've already been handled"); case SCULPT_UNDO_GEOMETRY: case SCULPT_UNDO_FACE_SETS: break; @@ -1355,7 +1355,7 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: - BLI_assert(!"Dynamic topology should've already been handled"); + BLI_assert_msg(0, "Dynamic topology should've already been handled"); case SCULPT_UNDO_GEOMETRY: case SCULPT_UNDO_FACE_SETS: break; @@ -1432,7 +1432,7 @@ void SCULPT_undo_push_end_ex(const bool use_nested_undo) typedef struct SculptUndoStep { UndoStep step; - /* Note: will split out into list for multi-object-sculpt-mode. */ + /* NOTE: will split out into list for multi-object-sculpt-mode. */ UndoSculpt data; } SculptUndoStep; @@ -1549,7 +1549,7 @@ static void sculpt_undosys_step_decode( ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); /* Sculpt needs evaluated state. - * Note: needs to be done here, as #ED_object_mode_generic_exit will usually invalidate + * NOTE: needs to be done here, as #ED_object_mode_generic_exit will usually invalidate * (some) evaluated data. */ BKE_scene_graph_evaluated_ensure(depsgraph, bmain); @@ -1608,7 +1608,7 @@ void ED_sculpt_undosys_type(UndoType *ut) ut->step_decode = sculpt_undosys_step_decode; ut->step_free = sculpt_undosys_step_free; - ut->flags = 0; + ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(SculptUndoStep); } diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 9e69b0a72db..d69c7ab8d48 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -813,7 +813,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) NlaTrack *act_track; Scene *scene = CTX_data_scene(C); - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* Get active track */ act_track = BKE_nlatrack_find_tweaked(adt); @@ -925,7 +925,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) NlaTrack *nlt; Scene *scene = CTX_data_scene(C); - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* Sanity Check */ if (adt == NULL) { diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index d305f7504f3..ce07b9c5fad 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -263,7 +263,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax); } else if (ac->datatype == ANIMCONT_MASK) { - /* TODO --- this is a copy of gpencil */ + /* TODO: this is a copy of gpencil. */ /* frames less than one get less saturated background */ uchar *color = sel ? col1 : col2; immUniformColor4ubv(color); diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index ae9d5445e1d..6f4e295cbb2 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -576,7 +576,7 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) } } else if (ac.datatype == ANIMCONT_MASK) { - /* FIXME... */ + /* FIXME: support this case. */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode"); return OPERATOR_CANCELLED; } @@ -629,7 +629,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op) } } else if (ac.datatype == ANIMCONT_MASK) { - /* FIXME... */ + /* FIXME: support this case. */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil or mask mode"); @@ -1454,7 +1454,7 @@ static void sethandles_action_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting flags for handles - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -1537,7 +1537,7 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting BezTriple interpolation - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index a51d9086dea..0d5b197ae93 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -933,8 +933,8 @@ static const EnumPropertyItem prop_column_select_types[] = { /* ------------------- */ /* Selects all visible keyframes between the specified markers */ -/* TODO, this is almost an _exact_ duplicate of a function of the same name in graph_select.c - * should de-duplicate - campbell */ +/* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in + * graph_select.c should de-duplicate. */ static void markers_selectkeys_between(bAnimContext *ac) { ListBase anim_data = {NULL, NULL}; diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 26b087168f9..28482faf6e3 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -530,7 +530,7 @@ static void action_listener(const wmSpaceTypeListenerParams *params) } break; case NC_ANIMATION: - /* for NLA tweakmode enter/exit, need complete refresh */ + /* For NLA tweak-mode enter/exit, need complete refresh. */ if (wmn->data == ND_NLA_ACTCHANGE) { saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC; ED_area_tag_refresh(area); diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index adb824b8934..b3b3eafb6e7 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -129,6 +129,8 @@ void ED_spacetypes_init(void) ED_screen_user_menu_register(); + ED_uilisttypes_ui(); + /* Gizmo types. */ ED_gizmotypes_button_2d(); ED_gizmotypes_dial_3d(); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index a2d9235cfb2..70b715e0119 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -126,7 +126,7 @@ static bool buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win return false; } -/* note: this function can return true without adding a world to the path +/* NOTE: this function can return true without adding a world to the path * so the buttons stay visible, but be sure to check the ID type if a ID_WO */ static bool buttons_context_path_world(ButsContextPath *path) { diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 7564fa4b930..9cb363ff0c9 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -34,8 +34,8 @@ struct Tex; struct bContext; struct bContextDataResult; struct bNode; -struct bNodeTree; struct bNodeSocket; +struct bNodeTree; struct wmOperatorType; struct SpaceProperties_Runtime { diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 97e3cb750c1..f1debcef5a9 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -451,7 +451,7 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg) /* set user as active */ if (user->node) { - ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL); + ED_node_set_active(CTX_data_main(C), NULL, user->ntree, user->node, NULL); ct->texture = NULL; /* Not totally sure if we should also change selection? */ diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 2da13646a8b..67b4fd61d38 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -1025,7 +1025,7 @@ static void prefetch_startjob(void *pjv, short *stop, short *do_update, float *p progress); } else { - BLI_assert(!"Unknown movie clip source when prefetching frames"); + BLI_assert_msg(0, "Unknown movie clip source when prefetching frames"); } } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index e0a524a79c1..326c221a2e3 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1214,7 +1214,7 @@ static void clip_header_region_listener(const wmRegionListenerParams *params) switch (wmn->data) { /* for proportional editmode only */ case ND_TOOLSETTINGS: - /* TODO - should do this when in mask mode only but no data available */ + /* TODO: should do this when in mask mode only but no data available. */ // if (sc->mode == SC_MODE_MASKEDIT) { ED_region_tag_redraw(region); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 9b4b020b276..bdb7c622cd2 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -415,7 +415,7 @@ static int console_insert_exec(bContext *C, wmOperator *op) static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - /* Note, the "text" property is always set from key-map, + /* NOTE: the "text" property is always set from key-map, * so we can't use #RNA_struct_property_is_set, check the length instead. */ if (!RNA_string_length(op->ptr, "text")) { /* if alt/ctrl/super are pressed pass through except for utf8 character event @@ -790,7 +790,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op) SpaceConsole *sc = CTX_wm_space_console(C); ARegion *region = CTX_wm_region(C); - /* TODO - stupid, just prevents crashes when no command line */ + /* TODO: stupid, just prevents crashes when no command line. */ ConsoleLine *ci = console_history_verify(C); const bool reverse = RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */ int prev_len = ci->len; @@ -1109,7 +1109,7 @@ typedef struct SetConsoleCursor { int sel_init; } SetConsoleCursor; -/* TODO, cursor placement without selection */ +/* TODO: cursor placement without selection. */ static void console_cursor_set_to_pos( SpaceConsole *sc, ARegion *region, SetConsoleCursor *scu, const int mval[2], int UNUSED(sel)) { diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 56a6204b385..3029eed1017 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -107,7 +107,7 @@ static SpaceLink *console_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ - /* TODO - duplicate?, then we also need to duplicate the py namespace */ + /* TODO: duplicate?, then we also need to duplicate the py namespace. */ BLI_listbase_clear(&sconsolen->scrollback); BLI_listbase_clear(&sconsolen->history); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index d947d361fdf..a314a85491d 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -110,7 +110,7 @@ void ED_file_path_button(bScreen *screen, UI_but_func_complete_set(but, autocomplete_directory, NULL); UI_but_funcN_set(but, file_directory_enter_handle, NULL, but); - /* TODO, directory editing is non-functional while a library is loaded + /* TODO: directory editing is non-functional while a library is loaded * until this is properly supported just disable it. */ if (sfile && sfile->files && filelist_lib(sfile->files)) { UI_but_flag_enable(but, UI_BUT_DISABLED); @@ -170,7 +170,7 @@ static void file_draw_icon(const SpaceFile *sfile, UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path), MEM_freeN); if (drag) { - /* TODO duplicated from file_draw_preview(). */ + /* TODO: duplicated from file_draw_preview(). */ ID *id; if ((id = filelist_file_get_id(file))) { @@ -523,6 +523,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) char orgname[FILE_MAX + 12]; char filename[FILE_MAX + 12]; wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); ARegion *region = CTX_wm_region(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); @@ -542,17 +543,15 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) else { /* If rename is successful, scroll to newly renamed entry. */ BLI_strncpy(params->renamefile, filename, sizeof(params->renamefile)); - params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; - - if (sfile->smoothscroll_timer != NULL) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - } - sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0); - sfile->scroll_offset = 0; + file_params_invoke_rename_postscroll(wm, win, sfile); } /* to make sure we show what is on disk */ - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); + } + else { + /* Renaming failed, reset the name for further renaming handling. */ + BLI_strncpy(params->renamefile, oldname, sizeof(params->renamefile)); } ED_region_tag_redraw(region); @@ -727,40 +726,45 @@ static void draw_columnheader_columns(const FileSelectParams *params, /** * Updates the stat string stored in file->entry if necessary. */ -static const char *filelist_get_details_column_string(FileAttributeColumnType column, - const FileDirEntry *file, - const bool small_size, - const bool update_stat_strings) +static const char *filelist_get_details_column_string( + FileAttributeColumnType column, + /* Generated string will be cached in the file, so non-const. */ + FileDirEntry *file, + const bool small_size, + const bool update_stat_strings) { switch (column) { case COLUMN_DATETIME: if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) { - if ((file->entry->datetime_str[0] == '\0') || update_stat_strings) { + if ((file->draw_data.datetime_str[0] == '\0') || update_stat_strings) { char date[FILELIST_DIRENTRY_DATE_LEN], time[FILELIST_DIRENTRY_TIME_LEN]; bool is_today, is_yesterday; BLI_filelist_entry_datetime_to_string( - NULL, file->entry->time, small_size, time, date, &is_today, &is_yesterday); + NULL, file->time, small_size, time, date, &is_today, &is_yesterday); if (is_today || is_yesterday) { BLI_strncpy(date, is_today ? N_("Today") : N_("Yesterday"), sizeof(date)); } - BLI_snprintf( - file->entry->datetime_str, sizeof(file->entry->datetime_str), "%s %s", date, time); + BLI_snprintf(file->draw_data.datetime_str, + sizeof(file->draw_data.datetime_str), + "%s %s", + date, + time); } - return file->entry->datetime_str; + return file->draw_data.datetime_str; } break; case COLUMN_SIZE: if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) || !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) { - if ((file->entry->size_str[0] == '\0') || update_stat_strings) { + if ((file->draw_data.size_str[0] == '\0') || update_stat_strings) { BLI_filelist_entry_size_to_string( - NULL, file->entry->size, small_size, file->entry->size_str); + NULL, file->size, small_size, file->draw_data.size_str); } - return file->entry->size_str; + return file->draw_data.size_str; } break; default: @@ -772,7 +776,7 @@ static const char *filelist_get_details_column_string(FileAttributeColumnType co static void draw_details_columns(const FileSelectParams *params, const FileLayout *layout, - const FileDirEntry *file, + FileDirEntry *file, const int pos_x, const int pos_y, const uchar text_col[4]) @@ -813,6 +817,8 @@ static void draw_details_columns(const FileSelectParams *params, void file_draw_list(const bContext *C, ARegion *region) { + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileLayout *layout = ED_fileselect_get_layout(sfile, region); @@ -883,12 +889,12 @@ void file_draw_list(const bContext *C, ARegion *region) // printf("%s: preview task: %d\n", __func__, previews_running); if (previews_running && !sfile->previews_timer) { sfile->previews_timer = WM_event_add_timer_notifier( - CTX_wm_manager(C), CTX_wm_window(C), NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01); + wm, win, NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01); } if (!previews_running && sfile->previews_timer) { /* Preview is not running, no need to keep generating update events! */ // printf("%s: Inactive preview task, sleeping!\n", __func__); - WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), sfile->previews_timer); + WM_event_remove_timer_notifier(wm, win, sfile->previews_timer); sfile->previews_timer = NULL; } } @@ -999,8 +1005,19 @@ void file_draw_list(const bContext *C, ARegion *region) UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ UI_but_flag_disable(but, UI_BUT_UNDO); if (false == UI_but_active_only(C, region, block, but)) { - file_selflag = filelist_entry_select_set( - sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL); + /* Note that this is the only place where we can also handle a cancelled renaming. */ + + file_params_rename_end(wm, win, sfile, file); + + /* After the rename button is removed, we need to make sure the view is redrawn once more, + * in case selection changed. Usually UI code would trigger that redraw, but the rename + * operator may have been called from a different region. + * Tagging regions for redrawing while drawing is rightfully prevented. However, this + * active button removing basically introduces handling logic to drawing code. So a + * notifier should be an acceptable workaround. */ + WM_event_add_notifier_ex(wm, win, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + + file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL); } } @@ -1088,7 +1105,7 @@ bool file_draw_hint_if_invalid(const SpaceFile *sfile, const ARegion *region) return false; } /* Check if the library exists. */ - if ((asset_params->asset_library.type == FILE_ASSET_LIBRARY_LOCAL) || + if ((asset_params->asset_library.type == ASSET_LIBRARY_LOCAL) || filelist_is_dir(sfile->files, asset_params->base_params.dir)) { return false; } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index a7c57459729..0bbed65671c 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -109,10 +109,22 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d, float file_string_width(const char *str); float file_font_pointsize(void); +void file_select_deselect_all(SpaceFile *sfile, uint flag); int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file); int autocomplete_directory(struct bContext *C, char *str, void *arg_v); int autocomplete_file(struct bContext *C, char *str, void *arg_v); +void file_params_smoothscroll_timer_clear(struct wmWindowManager *wm, + struct wmWindow *win, + SpaceFile *sfile); +void file_params_renamefile_clear(struct FileSelectParams *params); +void file_params_invoke_rename_postscroll(struct wmWindowManager *wm, + struct wmWindow *win, + SpaceFile *sfile); +void file_params_rename_end(struct wmWindowManager *wm, + struct wmWindow *win, + SpaceFile *sfile, + struct FileDirEntry *rename_file); void file_params_renamefile_activate(struct SpaceFile *sfile, struct FileSelectParams *params); typedef void *onReloadFnData; diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 0584e2ff938..995383d9d0e 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -104,15 +104,6 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, return sel; } -static void file_deselect_all(SpaceFile *sfile, uint flag) -{ - FileSelection sel; - sel.first = 0; - sel.last = filelist_files_ensure(sfile->files) - 1; - - filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL); -} - typedef enum FileSelect { FILE_SELECT_NOTHING = 0, FILE_SELECT_DIR = 1, @@ -239,7 +230,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) } /** - * \warning: loops over all files so better use cautiously + * \warning Loops over all files so better use cautiously. */ static bool file_is_any_selected(struct FileList *files) { @@ -444,7 +435,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) { int idx; - file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); + file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); filelist_entries_select_index_range_set( sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -472,7 +463,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve params->highlight_file = -1; params->sel_first = params->sel_last = -1; fileselect_file_set(sfile, params->active_file); - file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); + file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } @@ -491,7 +482,7 @@ static int file_box_select_exec(bContext *C, wmOperator *op) const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } ED_fileselect_layout_isect_rect(sfile->layout, ®ion->v2d, &rect, &rect); @@ -573,7 +564,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if ((idx >= 0) && (idx < numfiles)) { /* single select, deselect all selected first */ if (!extend) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } } } @@ -588,7 +579,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (ret == FILE_SELECT_NOTHING) { if (deselect_all) { - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); } } else if (ret == FILE_SELECT_DIR) { @@ -721,7 +712,7 @@ static bool file_walk_select_selection_set(wmWindow *win, } else { /* deselect all first */ - file_deselect_all(sfile, FILE_SEL_SELECTED); + file_select_deselect_all(sfile, FILE_SEL_SELECTED); /* highlight file under mouse pos */ params->highlight_file = -1; @@ -1023,7 +1014,7 @@ void FILE_OT_view_selected(wmOperatorType *ot) /* Note we could get rid of this one, but it's used by some addon so... * Does not hurt keeping it around for now. */ -/* TODO disallow bookmark editing in assets mode? */ +/* TODO: disallow bookmark editing in assets mode? */ static int bookmark_select_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1882,7 +1873,7 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) SpaceFile *sfile = CTX_wm_space_file(C); struct FSMenu *fsmenu = ED_fsmenu_get(); - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); /* refresh system directory menu */ fsmenu_refresh_system_category(fsmenu); @@ -2059,13 +2050,15 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w } } + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + /* if we are not editing, we are done */ if (edit_idx == -1) { /* Do not invalidate timer if filerename is still pending, * we might still be building the filelist and yet have to find edited entry. */ if (params->rename_flag == 0) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - sfile->smoothscroll_timer = NULL; + file_params_smoothscroll_timer_clear(wm, win, sfile); } return OPERATOR_PASS_THROUGH; } @@ -2073,8 +2066,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w /* we need the correct area for scrolling */ region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); if (!region || region->regiontype != RGN_TYPE_WINDOW) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - sfile->smoothscroll_timer = NULL; + file_params_smoothscroll_timer_clear(wm, win, sfile); return OPERATOR_PASS_THROUGH; } @@ -2093,7 +2085,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w sfile->layout, (int)region->v2d.cur.xmin, (int)-region->v2d.cur.ymax); const int last_visible_item = first_visible_item + numfiles_layout + 1; - /* Note: the special case for vertical layout is because filename is at the bottom of items then, + /* NOTE: the special case for vertical layout is because filename is at the bottom of items then, * so we artificially move current row back one step, to ensure we show bottom of * active item rather than its top (important in case visible height is low). */ const int middle_offset = max_ii( @@ -2131,13 +2123,11 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w (max_middle_offset - middle_offset < items_block_size)); if (is_ready && (is_centered || is_full_start || is_full_end)) { - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); - sfile->smoothscroll_timer = NULL; + file_params_smoothscroll_timer_clear(wm, win, sfile); /* Post-scroll (after rename has been validated by user) is done, * rename process is totally finished, cleanup. */ if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE) != 0) { - params->renamefile[0] = '\0'; - params->rename_flag = 0; + file_params_renamefile_clear(params); } return OPERATOR_FINISHED; } @@ -2346,21 +2336,20 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + eFileSel_Params_RenameFlag rename_flag = params->rename_flag; + /* If we don't enter the directory directly, remember file to jump into editing. */ if (do_diropen == false) { + BLI_assert(params->rename_id == NULL || !"File rename handling should immediately clear rename_id when done, because otherwise it will keep taking precedence over renamefile."); BLI_strncpy(params->renamefile, name, FILE_MAXFILE); - params->rename_flag = FILE_PARAMS_RENAME_PENDING; + rename_flag = FILE_PARAMS_RENAME_PENDING; } - /* Set timer to smoothly view newly generated file. */ - if (sfile->smoothscroll_timer != NULL) { - WM_event_remove_timer(wm, CTX_wm_window(C), sfile->smoothscroll_timer); - } - sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0); - sfile->scroll_offset = 0; + file_params_invoke_rename_postscroll(wm, CTX_wm_window(C), sfile); + params->rename_flag = rename_flag; /* reload dir to make sure we're seeing what's in the directory */ - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); if (do_diropen) { BLI_strncpy(params->dir, path, sizeof(params->dir)); @@ -2400,7 +2389,7 @@ void FILE_OT_directory_new(struct wmOperatorType *ot) /** \name Refresh File List Operator * \{ */ -/* TODO This should go to BLI_path_utils. */ +/* TODO: This should go to BLI_path_utils. */ static void file_expand_directory(bContext *C) { Main *bmain = CTX_data_main(C); @@ -2441,7 +2430,7 @@ static void file_expand_directory(bContext *C) } } -/* TODO check we still need this, it's annoying to have OS-specific code here... :/ */ +/* TODO: check we still need this, it's annoying to have OS-specific code here... :/. */ #if defined(WIN32) static bool can_create_dir(const char *dir) { @@ -2611,7 +2600,7 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused)) if (params) { params->flag ^= FILE_HIDE_DOT; - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -2804,6 +2793,11 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static bool file_rename_poll(bContext *C) +{ + return ED_operator_file_active(C) && !ED_fileselect_is_asset_browser(CTX_wm_space_file(C)); +} + void FILE_OT_rename(struct wmOperatorType *ot) { /* identifiers */ @@ -2814,7 +2808,7 @@ void FILE_OT_rename(struct wmOperatorType *ot) /* api callbacks */ ot->invoke = file_rename_invoke; ot->exec = file_rename_exec; - ot->poll = ED_operator_file_active; + ot->poll = file_rename_poll; } /** \} */ @@ -2908,7 +2902,7 @@ static int file_delete_exec(bContext *C, wmOperator *op) } } - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + ED_fileselect_clear(wm, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 40a7be0423e..492a189fc81 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -263,8 +263,7 @@ ListBase folder_history_list_duplicate(ListBase *listbase) typedef struct FileListInternEntry { struct FileListInternEntry *next, *prev; - /** ASSET_UUID_LENGTH */ - char uuid[16]; + FileUID uid; /** eFileSel_File_Types */ int typeflag; @@ -306,7 +305,7 @@ typedef struct FileListIntern { ListBase entries; FileListInternEntry **filtered; - char curr_uuid[16]; /* Used to generate uuid during internal listing. */ + FileUID curr_uid; /* Used to generate UID during internal listing. */ } FileListIntern; #define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */ @@ -315,7 +314,7 @@ typedef struct FileListEntryCache { int flags; - /* This one gathers all entries from both block and misc caches. Used for easy bulk-freing. */ + /* This one gathers all entries from both block and misc caches. Used for easy bulk-freeing. */ ListBase cached_entries; /* Block cache: all entries between start and end index. @@ -324,17 +323,18 @@ typedef struct FileListEntryCache { int block_start_index, block_end_index, block_center_index, block_cursor; /* Misc cache: random indices, FIFO behavior. - * Note: Not 100% sure we actually need that, time will say. */ + * NOTE: Not 100% sure we actually need that, time will say. */ int misc_cursor; int *misc_entries_indices; GHash *misc_entries; - /* Allows to quickly get a cached entry from its UUID. */ - GHash *uuids; + /* Allows to quickly get a cached entry from its UID. */ + GHash *uids; /* Previews handling. */ TaskPool *previews_pool; ThreadQueue *previews_done; + size_t previews_todo_count; } FileListEntryCache; /* FileListCache.flags */ @@ -1051,7 +1051,7 @@ static bool filelist_compare_asset_libraries(const FileSelectAssetLibraryUID *li if (library_a->type != library_b->type) { return false; } - if (library_a->type == FILE_ASSET_LIBRARY_CUSTOM) { + if (library_a->type == ASSET_LIBRARY_CUSTOM) { /* Don't only check the index, also check that it's valid. */ bUserAssetLibrary *library_ptr_a = BKE_preferences_asset_library_find_from_index( &U, library_a->custom_library_index); @@ -1154,7 +1154,7 @@ ImBuf *filelist_file_getimage(const FileDirEntry *file) return file->preview_icon_id ? BKE_icon_imbuf_get_buffer(file->preview_icon_id) : NULL; } -static ImBuf *filelist_geticon_image_ex(FileDirEntry *file) +ImBuf *filelist_geticon_image_ex(const FileDirEntry *file) { ImBuf *ibuf = NULL; @@ -1383,40 +1383,6 @@ static void filelist_entry_clear(FileDirEntry *entry) BKE_icon_delete(entry->preview_icon_id); entry->preview_icon_id = 0; } - /* For now, consider FileDirEntryRevision::poin as not owned here, - * so no need to do anything about it */ - - if (!BLI_listbase_is_empty(&entry->variants)) { - FileDirEntryVariant *var; - - for (var = entry->variants.first; var; var = var->next) { - if (var->name) { - MEM_freeN(var->name); - } - if (var->description) { - MEM_freeN(var->description); - } - - if (!BLI_listbase_is_empty(&var->revisions)) { - FileDirEntryRevision *rev; - - for (rev = var->revisions.first; rev; rev = rev->next) { - if (rev->comment) { - MEM_freeN(rev->comment); - } - } - - BLI_freelistN(&var->revisions); - } - } - - /* TODO: tags! */ - - BLI_freelistN(&entry->variants); - } - else if (entry->entry) { - MEM_freeN(entry->entry); - } } static void filelist_entry_free(FileDirEntry *entry) @@ -1529,6 +1495,7 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat /* That way task freeing function won't free th preview, since it does not own it anymore. */ atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL); BLI_thread_queue_push(cache->previews_done, preview); + atomic_fetch_and_sub_z(&cache->previews_todo_count, 1); } // printf("%s: End (%d)...\n", __func__, threadid); @@ -1555,6 +1522,7 @@ static void filelist_cache_preview_ensure_running(FileListEntryCache *cache) if (!cache->previews_pool) { cache->previews_pool = BLI_task_pool_create_background(cache, TASK_PRIORITY_LOW); cache->previews_done = BLI_thread_queue_init(); + cache->previews_todo_count = 0; IMB_thumb_locks_acquire(); } @@ -1588,6 +1556,7 @@ static void filelist_cache_previews_free(FileListEntryCache *cache) BLI_task_pool_free(cache->previews_pool); cache->previews_pool = NULL; cache->previews_done = NULL; + cache->previews_todo_count = 0; IMB_thumb_locks_release(); } @@ -1662,13 +1631,14 @@ static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size) copy_vn_i(cache->misc_entries_indices, cache_size, -1); cache->misc_cursor = 0; - /* XXX This assumes uint is 32 bits and uuid is 128 bits (char[16]), be careful! */ - cache->uuids = BLI_ghash_new_ex( - BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__, cache_size * 2); + cache->uids = BLI_ghash_new_ex( + BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__, cache_size * 2); cache->size = cache_size; cache->flags = FLC_IS_INIT; + cache->previews_todo_count = 0; + /* We cannot translate from non-main thread, so init translated strings once from here. */ IMB_thumb_ensure_translations(); } @@ -1688,7 +1658,7 @@ static void filelist_cache_free(FileListEntryCache *cache) BLI_ghash_free(cache->misc_entries, NULL, NULL); MEM_freeN(cache->misc_entries_indices); - BLI_ghash_free(cache->uuids, NULL, NULL); + BLI_ghash_free(cache->uids, NULL, NULL); for (entry = cache->cached_entries.first; entry; entry = entry_next) { entry_next = entry->next; @@ -1721,7 +1691,7 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size) } copy_vn_i(cache->misc_entries_indices, new_size, -1); - BLI_ghash_clear_ex(cache->uuids, NULL, NULL, new_size * 2); + BLI_ghash_clear_ex(cache->uids, NULL, NULL, new_size * 2); cache->size = new_size; @@ -1738,8 +1708,7 @@ FileList *filelist_new(short type) filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT); - p->selection_state = BLI_ghash_new( - BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__); + p->selection_state = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); p->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET; filelist_settype(p, type); @@ -1798,7 +1767,7 @@ void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const boo filelist_direntryarr_free(&filelist->filelist); if (do_selection && filelist->selection_state) { - BLI_ghash_clear(filelist->selection_state, MEM_freeN, NULL); + BLI_ghash_clear(filelist->selection_state, NULL, NULL); } } @@ -1819,7 +1788,7 @@ void filelist_free(struct FileList *filelist) filelist_cache_free(&filelist->filelist_cache); if (filelist->selection_state) { - BLI_ghash_free(filelist->selection_state, MEM_freeN, NULL); + BLI_ghash_free(filelist->selection_state, NULL, NULL); filelist->selection_state = NULL; } @@ -1957,16 +1926,12 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in FileListInternEntry *entry = filelist->filelist_intern.filtered[index]; FileListEntryCache *cache = &filelist->filelist_cache; FileDirEntry *ret; - FileDirEntryRevision *rev; ret = MEM_callocN(sizeof(*ret), __func__); - rev = MEM_callocN(sizeof(*rev), __func__); - - rev->size = (uint64_t)entry->st.st_size; - rev->time = (int64_t)entry->st.st_mtime; + ret->size = (uint64_t)entry->st.st_size; + ret->time = (int64_t)entry->st.st_mtime; - ret->entry = rev; ret->relpath = BLI_strdup(entry->relpath); if (entry->free_name) { ret->name = BLI_strdup(entry->name); @@ -1976,7 +1941,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in ret->name = entry->name; } ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath); - memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid)); + ret->uid = entry->uid; ret->blentype = entry->blentype; ret->typeflag = entry->typeflag; ret->attributes = entry->attributes; @@ -2034,11 +1999,11 @@ FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const ret = filelist_file_create_entry(filelist, index); old_index = cache->misc_entries_indices[cache->misc_cursor]; if ((old = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(old_index), NULL))) { - BLI_ghash_remove(cache->uuids, old->uuid, NULL, NULL); + BLI_ghash_remove(cache->uids, POINTER_FROM_UINT(old->uid), NULL, NULL); filelist_file_release_entry(filelist, old); } BLI_ghash_insert(cache->misc_entries, POINTER_FROM_INT(index), ret); - BLI_ghash_insert(cache->uuids, ret->uuid, ret); + BLI_ghash_insert(cache->uids, POINTER_FROM_UINT(ret->uid), ret); cache->misc_entries_indices[cache->misc_cursor] = index; cache->misc_cursor = (cache->misc_cursor + 1) % cache_size; @@ -2057,19 +2022,21 @@ FileDirEntry *filelist_file(struct FileList *filelist, int index) return filelist_file_ex(filelist, index, true); } -int filelist_file_findpath(struct FileList *filelist, const char *filename) +/** + * Find a file from a file name, or more precisely, its file-list relative path, inside the + * filtered items. \return The index of the found file or -1. + */ +int filelist_file_find_path(struct FileList *filelist, const char *filename) { - int fidx = -1; - if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { - return fidx; + return -1; } - /* XXX TODO Cache could probably use a ghash on paths too? Not really urgent though. - * This is only used to find again renamed entry, - * annoying but looks hairy to get rid of it currently. */ + /* XXX TODO: Cache could probably use a ghash on paths too? Not really urgent though. + * This is only used to find again renamed entry, + * annoying but looks hairy to get rid of it currently. */ - for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { + for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; if (STREQ(entry->relpath, filename)) { return fidx; @@ -2080,38 +2047,53 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename) } /** - * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET. + * Find a file representing \a id. + * \return The index of the found file or -1. */ -ID *filelist_file_get_id(const FileDirEntry *file) -{ - return file->id; -} - -FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]) +int filelist_file_find_id(const FileList *filelist, const ID *id) { if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { - return NULL; + return -1; } - if (filelist->filelist_cache.uuids) { - FileDirEntry *entry = BLI_ghash_lookup(filelist->filelist_cache.uuids, uuid); - if (entry) { - return entry; + for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { + FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; + if (entry->local_data.id == id) { + return fidx; } } - { - int fidx; + return -1; +} - for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) { - FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx]; - if (memcmp(entry->uuid, uuid, sizeof(entry->uuid)) == 0) { - return filelist_file(filelist, fidx); - } - } - } +/** + * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET. + */ +ID *filelist_file_get_id(const FileDirEntry *file) +{ + return file->id; +} - return NULL; +#define FILE_UID_UNSET 0 + +static FileUID filelist_uid_generate(FileList *filelist) +{ + /* Using an atomic operation to avoid having to lock thread... + * Note that we do not really need this here currently, since there is a single listing thread, + * but better remain consistent about threading! */ + return atomic_add_and_fetch_uint32(&filelist->filelist_intern.curr_uid, 1); +} + +bool filelist_uid_is_set(const FileUID uid) +{ + FileUID unset_uid; + filelist_uid_unset(&unset_uid); + return unset_uid != uid; +} + +void filelist_uid_unset(FileUID *r_uid) +{ + *r_uid = FILE_UID_UNSET; } void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_size) @@ -2147,7 +2129,7 @@ static bool filelist_file_cache_block_create(FileList *filelist, /* That entry might have already been requested and stored in misc cache... */ if ((entry = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(idx), NULL)) == NULL) { entry = filelist_file_create_entry(filelist, idx); - BLI_ghash_insert(cache->uuids, entry->uuid, entry); + BLI_ghash_insert(cache->uids, POINTER_FROM_UINT(entry->uid), entry); } cache->block_entries[cursor] = entry; } @@ -2173,7 +2155,7 @@ static void filelist_file_cache_block_release(struct FileList *filelist, __func__, cursor /*, cache->block_entries[cursor], cache->block_entries[cursor]->relpath*/); #endif - BLI_ghash_remove(cache->uuids, entry->uuid, NULL, NULL); + BLI_ghash_remove(cache->uids, POINTER_FROM_UINT(entry->uid), NULL, NULL); filelist_file_release_entry(filelist, entry); #ifndef NDEBUG cache->block_entries[cursor] = NULL; @@ -2305,7 +2287,7 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index) if (start_index < cache->block_start_index) { /* Add (request) needed entries before already cached ones. */ - /* Note: We need some index black magic to wrap around (cycle) + /* NOTE: We need some index black magic to wrap around (cycle) * inside our cache_size array... */ int size1 = cache->block_start_index - start_index; int size2 = 0; @@ -2337,7 +2319,7 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index) // printf("\tstart-extended...\n"); if (end_index > cache->block_end_index) { /* Add (request) needed entries after already cached ones. */ - /* Note: We need some index black magic to wrap around (cycle) + /* NOTE: We need some index black magic to wrap around (cycle) * inside our cache_size array... */ int size1 = end_index - cache->block_end_index; int size2 = 0; @@ -2408,7 +2390,8 @@ void filelist_cache_previews_set(FileList *filelist, const bool use_previews) if (use_previews && (filelist->flags & FL_IS_READY)) { cache->flags |= FLC_PREVIEWS_ACTIVE; - BLI_assert((cache->previews_pool == NULL) && (cache->previews_done == NULL)); + BLI_assert((cache->previews_pool == NULL) && (cache->previews_done == NULL) && + (cache->previews_todo_count == 0)); // printf("%s: Init Previews...\n", __func__); @@ -2481,6 +2464,18 @@ bool filelist_cache_previews_running(FileList *filelist) return (cache->previews_pool != NULL); } +bool filelist_cache_previews_done(FileList *filelist) +{ + FileListEntryCache *cache = &filelist->filelist_cache; + if ((cache->flags & FLC_PREVIEWS_ACTIVE) == 0) { + /* There are no previews. */ + return false; + } + + return (cache->previews_pool == NULL) || (cache->previews_done == NULL) || + (cache->previews_todo_count == (size_t)BLI_thread_queue_len(cache->previews_done)); +} + /* would recognize .blend as well */ static bool file_is_blend_backup(const char *str) { @@ -2635,7 +2630,7 @@ uint filelist_entry_select_set(const FileList *filelist, FileCheckType check) { /* Default NULL pointer if not found is fine here! */ - void **es_p = BLI_ghash_lookup_p(filelist->selection_state, entry->uuid); + void **es_p = BLI_ghash_lookup_p(filelist->selection_state, POINTER_FROM_UINT(entry->uid)); uint entry_flag = es_p ? POINTER_AS_UINT(*es_p) : 0; const uint org_entry_flag = entry_flag; @@ -2663,13 +2658,12 @@ uint filelist_entry_select_set(const FileList *filelist, *es_p = POINTER_FROM_UINT(entry_flag); } else { - BLI_ghash_remove(filelist->selection_state, entry->uuid, MEM_freeN, NULL); + BLI_ghash_remove(filelist->selection_state, POINTER_FROM_UINT(entry->uid), NULL, NULL); } } else if (entry_flag) { - void *key = MEM_mallocN(sizeof(entry->uuid), __func__); - memcpy(key, entry->uuid, sizeof(entry->uuid)); - BLI_ghash_insert(filelist->selection_state, key, POINTER_FROM_UINT(entry_flag)); + BLI_ghash_insert( + filelist->selection_state, POINTER_FROM_UINT(entry->uid), POINTER_FROM_UINT(entry_flag)); } } @@ -2707,7 +2701,8 @@ uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileChec if (((check == CHECK_ALL)) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) || ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) { /* Default NULL pointer if not found is fine here! */ - return POINTER_AS_UINT(BLI_ghash_lookup(filelist->selection_state, entry->uuid)); + return POINTER_AS_UINT( + BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid))); } return 0; @@ -2732,7 +2727,7 @@ bool filelist_entry_is_selected(FileList *filelist, const int index) /* BLI_ghash_lookup returns NULL if not found, which gets mapped to 0, which gets mapped to * "not selected". */ const uint selection_state = POINTER_AS_UINT( - BLI_ghash_lookup(filelist->selection_state, intern_entry->uuid)); + BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid))); return selection_state != 0; } @@ -2967,7 +2962,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) ListBase *lb; int a, fake, idcode, ok, totlib, totbl; - // filelist->type = FILE_MAIN; /* XXX TODO: add modes to filebrowser */ + // filelist->type = FILE_MAIN; /* XXX TODO: add modes to file-browser */ BLI_assert(filelist->filelist.entries == NULL); @@ -3073,7 +3068,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) files->entry->relpath = BLI_strdup(relname); } // files->type |= S_IFREG; -# if 0 /* XXX TODO show the selection status of the objects */ +# if 0 /* XXX TODO: show the selection status of the objects. */ if (!filelist->has_func) { /* F4 DATA BROWSE */ if (idcode == ID_OB) { if ( ((Object *)id)->flag & SELECT) { @@ -3202,14 +3197,7 @@ static void filelist_readjob_do(const bool do_lib, for (entry = entries.first; entry; entry = entry->next) { BLI_join_dirfile(dir, sizeof(dir), rel_subdir, entry->relpath); - /* Generate our entry uuid. Abusing uuid as an uint32, shall be more than enough here, - * things would crash way before we overflow that counter! - * Using an atomic operation to avoid having to lock thread... - * Note that we do not really need this here currently, - * since there is a single listing thread, but better - * remain consistent about threading! */ - *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32( - (uint32_t *)filelist->filelist_intern.curr_uuid, 1); + entry->uid = filelist_uid_generate(filelist); /* Only thing we change in direntry here, so we need to free it first. */ MEM_freeN(entry->relpath); @@ -3334,8 +3322,7 @@ static void filelist_readjob_main_assets(Main *current_main, entry->free_name = false; entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET; entry->blentype = GS(id_iter->name); - *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32( - (uint32_t *)filelist->filelist_intern.curr_uuid, 1); + entry->uid = filelist_uid_generate(filelist); entry->local_data.preview_image = BKE_asset_metadata_preview_get_from_id(id_iter->asset_data, id_iter); entry->local_data.id = id_iter; @@ -3381,9 +3368,7 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update flrj->tmp_filelist->filelist_intern.filtered = NULL; BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries); - memset(flrj->tmp_filelist->filelist_intern.curr_uuid, - 0, - sizeof(flrj->tmp_filelist->filelist_intern.curr_uuid)); + filelist_uid_unset(&flrj->tmp_filelist->filelist_intern.curr_uid); flrj->tmp_filelist->libfiledata = NULL; memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache)); @@ -3423,7 +3408,7 @@ static void filelist_readjob_update(void *flrjv) BLI_mutex_unlock(&flrj->lock); if (new_nbr_entries) { - /* Do not clear selection cache, we can assume already 'selected' uuids are still valid! */ + /* Do not clear selection cache, we can assume already 'selected' UIDs are still valid! */ filelist_clear_ex(flrj->filelist, true, false); flrj->filelist->flags |= (FL_NEED_SORTING | FL_NEED_FILTERING); @@ -3466,7 +3451,7 @@ static void filelist_readjob_free(void *flrjv) MEM_freeN(flrj); } -void filelist_readjob_start(FileList *filelist, const bContext *C) +void filelist_readjob_start(FileList *filelist, const int space_notifier, const bContext *C) { Main *bmain = CTX_data_main(C); wmJob *wm_job; @@ -3498,22 +3483,19 @@ void filelist_readjob_start(FileList *filelist, const bContext *C) filelist_readjob_endjob(flrj); filelist_readjob_free(flrj); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED, NULL); + WM_event_add_notifier(C, space_notifier | NA_JOB_FINISHED, NULL); return; } /* setup job */ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), - CTX_data_scene(C), + filelist, "Listing Dirs...", WM_JOB_PROGRESS, WM_JOB_TYPE_FILESEL_READDIR); WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free); - WM_jobs_timer(wm_job, - 0.01, - NC_SPACE | ND_SPACE_FILE_LIST, - NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED); + WM_jobs_timer(wm_job, 0.01, space_notifier, space_notifier | NA_JOB_FINISHED); WM_jobs_callbacks( wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob); @@ -3521,12 +3503,12 @@ void filelist_readjob_start(FileList *filelist, const bContext *C) WM_jobs_start(CTX_wm_manager(C), wm_job); } -void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene) +void filelist_readjob_stop(FileList *filelist, wmWindowManager *wm) { - WM_jobs_kill_type(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR); + WM_jobs_kill_type(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR); } -int filelist_readjob_running(wmWindowManager *wm, Scene *owner_scene) +int filelist_readjob_running(FileList *filelist, wmWindowManager *wm) { - return WM_jobs_test(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR); + return WM_jobs_test(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR); } diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 9eb70dd8437..cb98cf6e74a 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -35,6 +35,8 @@ struct wmWindowManager; struct FileDirEntry; +typedef uint32_t FileUID; + typedef enum FileSelType { FILE_SEL_REMOVE = 0, FILE_SEL_ADD = 1, @@ -77,6 +79,7 @@ void filelist_init_icons(void); void filelist_free_icons(void); struct ImBuf *filelist_getimage(struct FileList *filelist, const int index); struct ImBuf *filelist_file_getimage(const FileDirEntry *file); +struct ImBuf *filelist_geticon_image_ex(const FileDirEntry *file); struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index); int filelist_geticon(struct FileList *filelist, const int index, const bool is_main); @@ -95,9 +98,11 @@ int filelist_needs_reading(struct FileList *filelist); FileDirEntry *filelist_file(struct FileList *filelist, int index); FileDirEntry *filelist_file_ex(struct FileList *filelist, int index, bool use_request); -int filelist_file_findpath(struct FileList *filelist, const char *file); +int filelist_file_find_path(struct FileList *filelist, const char *file); +int filelist_file_find_id(const struct FileList *filelist, const struct ID *id); struct ID *filelist_file_get_id(const struct FileDirEntry *file); -FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]); +bool filelist_uid_is_set(const FileUID uid); +void filelist_uid_unset(FileUID *r_uid); void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size); bool filelist_file_cache_block(struct FileList *filelist, const int index); @@ -140,13 +145,16 @@ struct BlendHandle *filelist_lib(struct FileList *filelist); bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group); void filelist_freelib(struct FileList *filelist); -void filelist_readjob_start(struct FileList *filelist, const struct bContext *C); -void filelist_readjob_stop(struct wmWindowManager *wm, struct Scene *owner_scene); -int filelist_readjob_running(struct wmWindowManager *wm, struct Scene *owner_scene); +void filelist_readjob_start(struct FileList *filelist, + int space_notifier, + const struct bContext *C); +void filelist_readjob_stop(struct FileList *filelist, struct wmWindowManager *wm); +int filelist_readjob_running(struct FileList *filelist, struct wmWindowManager *wm); bool filelist_cache_previews_update(struct FileList *filelist); void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews); bool filelist_cache_previews_running(struct FileList *filelist); +bool filelist_cache_previews_done(struct FileList *filelist); #ifdef __cplusplus } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 8e3fc36aa71..7bc83e8fc79 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -118,7 +118,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile) asset_params = sfile->asset_params = MEM_callocN(sizeof(*asset_params), "FileAssetSelectParams"); asset_params->base_params.details_flags = U_default.file_space_data.details_flags; - asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL; + asset_params->asset_library.type = ASSET_LIBRARY_LOCAL; asset_params->asset_library.custom_library_index = -1; asset_params->import_type = FILE_ASSET_IMPORT_APPEND; } @@ -126,7 +126,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile) FileSelectParams *base_params = &asset_params->base_params; base_params->file[0] = '\0'; base_params->filter_glob[0] = '\0'; - /* TODO this way of using filters to form categories is notably slower than specifying a + /* TODO: this way of using filters to form categories is notably slower than specifying a * "group" to read. That's because all types are read and filtering is applied afterwards. Would * be nice if we could lazy-read individual groups. */ base_params->flag |= U_default.file_space_data.flag | FILE_ASSETS_ONLY | FILE_FILTER; @@ -378,7 +378,7 @@ FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile) return &sfile->asset_params->base_params; } - BLI_assert(!"Invalid browse mode set in file space."); + BLI_assert_msg(0, "Invalid browse mode set in file space."); return NULL; } @@ -399,7 +399,7 @@ FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) return (FileSelectParams *)sfile->asset_params; } - BLI_assert(!"Invalid browse mode set in file space."); + BLI_assert_msg(0, "Invalid browse mode set in file space."); return NULL; } @@ -420,26 +420,26 @@ static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params) bUserAssetLibrary *user_library = NULL; /* Ensure valid repository, or fall-back to local one. */ - if (library->type == FILE_ASSET_LIBRARY_CUSTOM) { + if (library->type == ASSET_LIBRARY_CUSTOM) { BLI_assert(library->custom_library_index >= 0); user_library = BKE_preferences_asset_library_find_from_index(&U, library->custom_library_index); if (!user_library) { - library->type = FILE_ASSET_LIBRARY_LOCAL; + library->type = ASSET_LIBRARY_LOCAL; } } switch (library->type) { - case FILE_ASSET_LIBRARY_LOCAL: + case ASSET_LIBRARY_LOCAL: base_params->dir[0] = '\0'; break; - case FILE_ASSET_LIBRARY_CUSTOM: + case ASSET_LIBRARY_CUSTOM: BLI_assert(user_library); BLI_strncpy(base_params->dir, user_library->path, sizeof(base_params->dir)); break; } - base_params->type = (library->type == FILE_ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB; + base_params->type = (library->type == ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB; } void fileselect_refresh_params(SpaceFile *sfile) @@ -1047,7 +1047,7 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *region) * Support updating the directory even when this isn't the active space * needed so RNA properties update function isn't context sensitive, see T70255. */ -void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) +void ED_file_change_dir_ex(bContext *C, ScrArea *area) { /* May happen when manipulating non-active spaces. */ if (UNLIKELY(area->spacetype != SPACE_FILE)) { @@ -1057,10 +1057,7 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params) { wmWindowManager *wm = CTX_wm_manager(C); - Scene *scene = WM_windows_scene_get_from_screen(wm, screen); - if (LIKELY(scene != NULL)) { - ED_fileselect_clear(wm, scene, sfile); - } + ED_fileselect_clear(wm, sfile); /* Clear search string, it is very rare to want to keep that filter while changing dir, * and usually very annoying to keep it actually! */ @@ -1085,9 +1082,17 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) void ED_file_change_dir(bContext *C) { - bScreen *screen = CTX_wm_screen(C); ScrArea *area = CTX_wm_area(C); - ED_file_change_dir_ex(C, screen, area); + ED_file_change_dir_ex(C, area); +} + +void file_select_deselect_all(SpaceFile *sfile, uint flag) +{ + FileSelection sel; + sel.first = 0; + sel.last = filelist_files_ensure(sfile->files) - 1; + + filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL); } int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file) @@ -1183,11 +1188,11 @@ int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) return match; } -void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile) +void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile) { /* only NULL in rare cases - T29734. */ if (sfile->files) { - filelist_readjob_stop(wm, owner_scene); + filelist_readjob_stop(sfile->files, wm); filelist_freelib(sfile->files); filelist_clear(sfile->files); } @@ -1197,7 +1202,7 @@ void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfi WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL); } -void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile) +void ED_fileselect_exit(wmWindowManager *wm, SpaceFile *sfile) { if (!sfile) { return; @@ -1224,13 +1229,72 @@ void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfil folder_history_list_free(sfile); if (sfile->files) { - ED_fileselect_clear(wm, owner_scene, sfile); + ED_fileselect_clear(wm, sfile); filelist_free(sfile->files); MEM_freeN(sfile->files); sfile->files = NULL; } } +void file_params_smoothscroll_timer_clear(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile) +{ + WM_event_remove_timer(wm, win, sfile->smoothscroll_timer); + sfile->smoothscroll_timer = NULL; +} + +/** + * Set the renaming-state to #FILE_PARAMS_RENAME_POSTSCROLL_PENDING and trigger the smooth-scroll + * timer. To be used right after a file was renamed. + * Note that the caller is responsible for setting the correct rename-file info + * (#FileSelectParams.renamefile or #FileSelectParams.rename_id). + */ +void file_params_invoke_rename_postscroll(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile) +{ + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; + + if (sfile->smoothscroll_timer != NULL) { + file_params_smoothscroll_timer_clear(wm, win, sfile); + } + sfile->smoothscroll_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 1000.0); + sfile->scroll_offset = 0; +} + +/** + * To be executed whenever renaming ends (successfully or not). + */ +void file_params_rename_end(wmWindowManager *wm, + wmWindow *win, + SpaceFile *sfile, + FileDirEntry *rename_file) +{ + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + filelist_entry_select_set( + sfile->files, rename_file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL); + + /* Ensure smooth-scroll timer is active, even if not needed, because that way rename state is + * handled properly. */ + file_params_invoke_rename_postscroll(wm, win, sfile); + /* Also always activate the rename file, even if renaming was cancelled. */ + file_params_renamefile_activate(sfile, params); +} + +void file_params_renamefile_clear(FileSelectParams *params) +{ + params->renamefile[0] = '\0'; + params->rename_id = NULL; + params->rename_flag = 0; +} + +static int file_params_find_renamed(const FileSelectParams *params, struct FileList *filelist) +{ + /* Find the file either through the local ID/asset it represents or its relative path. */ + return (params->rename_id != NULL) ? filelist_file_find_id(filelist, params->rename_id) : + filelist_file_find_path(filelist, params->renamefile); +} + /** * Helper used by both main update code, and smooth-scroll timer, * to try to enable rename editing from #FileSelectParams.renamefile name. @@ -1244,28 +1308,33 @@ void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params) return; } - BLI_assert(params->renamefile[0] != '\0'); + BLI_assert(params->renamefile[0] != '\0' || params->rename_id != NULL); - const int idx = filelist_file_findpath(sfile->files, params->renamefile); + const int idx = file_params_find_renamed(params, sfile->files); if (idx >= 0) { FileDirEntry *file = filelist_file(sfile->files, idx); BLI_assert(file != NULL); + params->active_file = idx; + filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); + if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) { filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL); params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; } else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) { - filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL); - params->renamefile[0] = '\0'; + file_select_deselect_all(sfile, FILE_SEL_SELECTED); + filelist_entry_select_set( + sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED | FILE_SEL_HIGHLIGHTED, CHECK_ALL); + params->active_file = idx; + file_params_renamefile_clear(params); params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE; } } /* File listing is now async, only reset renaming if matching entry is not found * when file listing is not done. */ else if (filelist_is_ready(sfile->files)) { - params->renamefile[0] = '\0'; - params->rename_flag = 0; + file_params_renamefile_clear(params); } } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 0418bb87768..31c7dee294b 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -32,6 +32,7 @@ #include "BKE_appdir.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_main.h" #include "BKE_screen.h" #include "RNA_access.h" @@ -206,7 +207,7 @@ static void file_exit(wmWindowManager *wm, ScrArea *area) sfile->previews_timer = NULL; } - ED_fileselect_exit(wm, NULL, sfile); + ED_fileselect_exit(wm, sfile); } static SpaceLink *file_duplicate(SpaceLink *sl) @@ -360,13 +361,13 @@ static void file_refresh(const bContext *C, ScrArea *area) sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir); if (filelist_needs_force_reset(sfile->files)) { - filelist_readjob_stop(wm, CTX_data_scene(C)); + filelist_readjob_stop(sfile->files, wm); filelist_clear(sfile->files); } if (filelist_needs_reading(sfile->files)) { if (!filelist_pending(sfile->files)) { - filelist_readjob_start(sfile->files, C); + filelist_readjob_start(sfile->files, NC_SPACE | ND_SPACE_FILE_LIST, C); } } @@ -429,10 +430,10 @@ static void file_reset_filelist_showing_main_data(ScrArea *area, SpaceFile *sfil } } -static void file_listener(const wmSpaceTypeListenerParams *params) +static void file_listener(const wmSpaceTypeListenerParams *listener_params) { - ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + ScrArea *area = listener_params->area; + wmNotifier *wmn = listener_params->notifier; SpaceFile *sfile = (SpaceFile *)area->spacedata.first; /* context changes */ @@ -469,10 +470,19 @@ static void file_listener(const wmSpaceTypeListenerParams *params) break; case NC_ID: { switch (wmn->action) { - case NA_RENAME: + case NA_RENAME: { + const ID *active_file_id = ED_fileselect_active_asset_get(sfile); + /* If a renamed ID is active in the file browser, update scrolling to keep it in view. */ + if (active_file_id && (wmn->reference == active_file_id)) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + params->rename_id = active_file_id; + file_params_invoke_rename_postscroll(G_MAIN->wm.first, listener_params->window, sfile); + } + /* Force list to update sorting (with a full reset for now). */ file_reset_filelist_showing_main_data(area, sfile); break; + } } break; } @@ -508,10 +518,10 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *region) WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); } -static void file_main_region_listener(const wmRegionListenerParams *params) +static void file_main_region_listener(const wmRegionListenerParams *listener_params) { - ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + ARegion *region = listener_params->region; + wmNotifier *wmn = listener_params->notifier; /* context changes */ switch (wmn->category) { @@ -716,14 +726,14 @@ static void file_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(params)) +static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(listener_params)) { } -static void file_tool_props_region_listener(const wmRegionListenerParams *params) +static void file_tool_props_region_listener(const wmRegionListenerParams *listener_params) { - const wmNotifier *wmn = params->notifier; - ARegion *region = params->region; + const wmNotifier *wmn = listener_params->notifier; + ARegion *region = listener_params->region; switch (wmn->category) { case NC_ID: @@ -789,10 +799,10 @@ static void file_execution_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_ui_region_listener(const wmRegionListenerParams *params) +static void file_ui_region_listener(const wmRegionListenerParams *listener_params) { - ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + ARegion *region = listener_params->region; + wmNotifier *wmn = listener_params->notifier; /* context changes */ switch (wmn->category) { @@ -858,7 +868,12 @@ static void file_space_subtype_item_extend(bContext *UNUSED(C), } } -static const char *file_context_dir[] = {"active_file", "id", NULL}; +static const char *file_context_dir[] = { + "active_file", + "asset_library", + "id", + NULL, +}; static int /*eContextResult*/ file_context(const bContext *C, const char *member, @@ -889,6 +904,23 @@ static int /*eContextResult*/ file_context(const bContext *C, CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file); return CTX_RESULT_OK; } + if (CTX_data_equals(member, "asset_library")) { + FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); + if (!asset_params) { + return CTX_RESULT_NO_DATA; + } + + BLI_STATIC_ASSERT(offsetof(FileSelectAssetLibraryUID, type) == + offsetof(AssetLibraryReference, type), + "Expected FileSelectAssetLibraryUID to match AssetLibraryReference"); + BLI_STATIC_ASSERT(offsetof(FileSelectAssetLibraryUID, custom_library_index) == + offsetof(AssetLibraryReference, custom_library_index), + "Expected FileSelectAssetLibraryUID to match AssetLibraryReference"); + + CTX_data_pointer_set( + result, &screen->id, &RNA_AssetLibraryReference, &asset_params->asset_library); + return CTX_RESULT_OK; + } if (CTX_data_equals(member, "id")) { const FileDirEntry *file = filelist_file(sfile->files, params->active_file); if (file == NULL) { diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 0d2a436902a..af88bbced9c 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -414,7 +414,7 @@ static bool draw_fcurve_handles_check(SpaceGraph *sipo, FCurve *fcu) } /* draw lines for F-Curve handles only (this is only done in EditMode) - * note: draw_fcurve_handles_check must be checked before running this. */ + * NOTE: draw_fcurve_handles_check must be checked before running this. */ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) { int sel, b; @@ -1259,14 +1259,15 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) immUniformColor3f(0.9f, 0.9f, 0.9f); immUniform1f("dash_width", 10.0f); immUniform1f("dash_factor", 0.5f); + GPU_line_width(1.0f); - immBegin(GPU_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2); + immBegin(GPU_PRIM_LINES, (y <= v2d->cur.ymax) ? 4 : 2); /* x-axis lookup */ co[0] = x; - if (y >= v2d->cur.ymin) { - co[1] = v2d->cur.ymin - 1.0f; + if (y <= v2d->cur.ymax) { + co[1] = v2d->cur.ymax + 1.0f; immVertex2fv(shdr_pos, co); co[1] = y; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index be577e9ab13..6f1b0bb0d7d 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1481,7 +1481,7 @@ static void setipo_graph_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting BezTriple interpolation - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -1558,7 +1558,7 @@ static void seteasing_graph_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting BezTriple easing. - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -1636,7 +1636,7 @@ static void sethandles_graph_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Loop through setting flags for handles. - * Note: we do not supply KeyframeEditData to the looper yet. + * NOTE: we do not supply KeyframeEditData to the looper yet. * Currently that's not necessary here. */ for (ale = anim_data.first; ale; ale = ale->next) { diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 2f4e1c1abbe..a853efb1ace 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -167,7 +167,7 @@ static void nearest_fcurve_vert_store(ListBase *matches, } } else if (fpt) { - /* TODO... */ + /* TODO: support #FPoint. */ } } @@ -257,7 +257,7 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L } } else if (fcu->fpt) { - /* TODO; do this for samples too */ + /* TODO: do this for samples too. */ } /* un-apply NLA mapping from all the keyframes */ @@ -736,7 +736,7 @@ static bool rectf_curve_intersection( * to select a curve by sampling it at various points instead of trying to select the * keyframes directly. * The selection actions done to a curve are actually done on all the keyframes of the curve. - * Note: This function is only called if no keyframe is in the selection area. + * NOTE: This function is only called if no keyframe is in the selection area. */ static void box_select_graphcurves(bAnimContext *ac, const rctf *rectf_view, @@ -859,7 +859,7 @@ static int graphkeys_box_select_exec(bContext *C, wmOperator *op) * as frame-range one is often used for tweaking timing when "blocking", * while channels is not that useful. */ - if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) { + if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) { mode = BEZT_OK_FRAMERANGE; } else { @@ -1131,8 +1131,8 @@ static const EnumPropertyItem prop_column_select_types[] = { /* ------------------- */ /* Selects all visible keyframes between the specified markers */ -/* TODO, this is almost an _exact_ duplicate of a function of the same name in action_select.c - * should de-duplicate - campbell */ +/* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in + * action_select.c should de-duplicate. */ static void markers_selectkeys_between(bAnimContext *ac) { ListBase anim_data = {NULL, NULL}; diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index ca14f7c5942..31c53cde62c 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -51,7 +51,7 @@ /* *************************** Calculate Range ************************** */ /* Get the min/max keyframes. */ -/* Note: it should return total boundbox, filter for selection only can be argument... */ +/* NOTE: it should return total boundbox, filter for selection only can be argument... */ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 32496cb8f1f..49966e880d3 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -229,7 +229,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *region) graph_draw_curves(&ac, sipo, region, 0); graph_draw_curves(&ac, sipo, region, 1); - /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */ + /* XXX(ton): the slow way to set tot rect... but for nice sliders needed. */ get_graph_keyframe_extents( &ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true); /* extra offset so that these items are visible */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index d909bfd1864..4779a82948d 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -511,7 +511,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt return false; } - /* note, this looks reversed, but matches menu direction */ + /* NOTE: this looks reversed, but matches menu direction. */ if (direction == -1) { RenderPass *rp; int rp_index = iuser->pass + 1; @@ -1013,14 +1013,14 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_ma uiLayoutRow(col, true), imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE); /* only display depth setting if multiple depths can be used */ - if ((ELEM(depth_ok, - R_IMF_CHAN_DEPTH_1, - R_IMF_CHAN_DEPTH_8, - R_IMF_CHAN_DEPTH_10, - R_IMF_CHAN_DEPTH_12, - R_IMF_CHAN_DEPTH_16, - R_IMF_CHAN_DEPTH_24, - R_IMF_CHAN_DEPTH_32)) == 0) { + if (ELEM(depth_ok, + R_IMF_CHAN_DEPTH_1, + R_IMF_CHAN_DEPTH_8, + R_IMF_CHAN_DEPTH_10, + R_IMF_CHAN_DEPTH_12, + R_IMF_CHAN_DEPTH_16, + R_IMF_CHAN_DEPTH_24, + R_IMF_CHAN_DEPTH_32) == 0) { uiItemR(uiLayoutRow(col, true), imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE); } diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index c26f92c5463..169dafcb8d0 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -51,7 +51,7 @@ #include "WM_api.h" #include "WM_types.h" -/* note; image_panel_properties() uses pointer to sima->image directly */ +/* NOTE: image_panel_properties() uses pointer to sima->image directly. */ Image *ED_space_image(SpaceImage *sima) { return sima->image; @@ -64,8 +64,6 @@ void ED_space_image_set(Main *bmain, SpaceImage *sima, Object *obedit, Image *im sima->pin = true; } - /* change the space ima after because uvedit_face_visible_test uses the space ima - * to check if the face is displayed in UV-localview */ sima->image = ima; if (ima == NULL || ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 193c35d10a2..dad354ba8ee 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1995,7 +1995,7 @@ static bool image_save_as_draw_check_prop(PointerRNA *ptr, return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") || STREQ(prop_id, "filename") || /* when saving a copy, relative path has no effect */ - ((STREQ(prop_id, "relative_path")) && RNA_boolean_get(ptr, "copy"))); + (STREQ(prop_id, "relative_path") && RNA_boolean_get(ptr, "copy"))); } static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) @@ -2712,10 +2712,10 @@ static int image_flip_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - const bool flip_horizontal = RNA_boolean_get(op->ptr, "use_flip_horizontal"); - const bool flip_vertical = RNA_boolean_get(op->ptr, "use_flip_vertical"); + const bool use_flip_x = RNA_boolean_get(op->ptr, "use_flip_x"); + const bool use_flip_y = RNA_boolean_get(op->ptr, "use_flip_y"); - if (!flip_horizontal && !flip_vertical) { + if (!use_flip_x && !use_flip_y) { BKE_image_release_ibuf(ima, ibuf, NULL); return OPERATOR_FINISHED; } @@ -2734,11 +2734,12 @@ static int image_flip_exec(bContext *C, wmOperator *op) float *orig_float_pixels = MEM_dupallocN(float_pixels); for (int x = 0; x < size_x; x++) { + const int source_pixel_x = use_flip_x ? size_x - x - 1 : x; for (int y = 0; y < size_y; y++) { - const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x; - const int source_pixel_y = flip_vertical ? size_y - y - 1 : y; + const int source_pixel_y = use_flip_y ? size_y - y - 1 : y; - float *source_pixel = &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + const float *source_pixel = + &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; float *target_pixel = &float_pixels[4 * (x + y * size_x)]; copy_v4_v4(target_pixel, source_pixel); @@ -2754,11 +2755,12 @@ static int image_flip_exec(bContext *C, wmOperator *op) char *char_pixels = (char *)ibuf->rect; char *orig_char_pixels = MEM_dupallocN(char_pixels); for (int x = 0; x < size_x; x++) { + const int source_pixel_x = use_flip_x ? size_x - x - 1 : x; for (int y = 0; y < size_y; y++) { - const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x; - const int source_pixel_y = flip_vertical ? size_y - y - 1 : y; + const int source_pixel_y = use_flip_y ? size_y - y - 1 : y; - char *source_pixel = &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + const char *source_pixel = + &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; char *target_pixel = &char_pixels[4 * (x + y * size_x)]; copy_v4_v4_char(target_pixel, source_pixel); @@ -2804,10 +2806,9 @@ void IMAGE_OT_flip(wmOperatorType *ot) /* properties */ PropertyRNA *prop; prop = RNA_def_boolean( - ot->srna, "use_flip_horizontal", false, "Horizontal", "Flip the image horizontally"); + ot->srna, "use_flip_x", false, "Horizontal", "Flip the image horizontally"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean( - ot->srna, "use_flip_vertical", false, "Vertical", "Flip the image vertically"); + prop = RNA_def_boolean(ot->srna, "use_flip_y", false, "Vertical", "Flip the image vertically"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); /* flags */ diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 082f66b57af..cc6effd0f71 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -1006,7 +1006,7 @@ void ED_image_undosys_type(UndoType *ut) * specific case, see `image_undosys_step_encode` code. We cannot specify * `UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE` though, as it can be called with a NULL context by * current code. */ - ut->flags = 0; + ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(ImageUndoStep); } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index aaf9852e212..94e53958524 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -564,12 +564,11 @@ void FILE_OT_find_missing_files(wmOperatorType *ot) /** \name Report Box Operator * \{ */ -/* Hard to decide whether to keep this as an operator, - * or turn it into a hardcoded ui control feature, - * handling TIMER events for all regions in interface_handlers.c +/* NOTE(matt): Hard to decide whether to keep this as an operator, + * or turn it into a hard_coded UI control feature, + * handling TIMER events for all regions in `interface_handlers.c`. * Not sure how good that is to be accessing UI data from - * inactive regions, so use this for now. --matt - */ + * inactive regions, so use this for now. */ #define INFO_TIMEOUT 5.0f #define ERROR_TIMEOUT 10.0f diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c index a3da50709df..1062b76b1df 100644 --- a/source/blender/editors/space_info/info_report.c +++ b/source/blender/editors/space_info/info_report.c @@ -102,7 +102,7 @@ int info_report_mask(const SpaceInfo *UNUSED(sinfo)) static int report_replay_exec(bContext *C, wmOperator *UNUSED(op)) { - /* TODO, get this working again! */ + /* TODO: get this working again! */ #if 0 SpaceInfo *sc = CTX_wm_space_info(C); ReportList *reports = CTX_wm_reports(C); diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 9e0973f5fde..d7671a372c6 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -96,7 +96,7 @@ typedef struct SceneStatsFmt { char totgpstroke[MAX_INFO_NUM_LEN], totgppoint[MAX_INFO_NUM_LEN]; } SceneStatsFmt; -static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats) +static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *stats) { if (me_eval == NULL) { return false; @@ -149,8 +149,8 @@ static void stats_object(Object *ob, switch (ob->type) { case OB_MESH: { /* we assume evaluated mesh is already built, this strictly does stats now. */ - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - if (!BLI_gset_add(objects_gset, me_eval)) { + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + if (!BLI_gset_add(objects_gset, (void *)me_eval)) { break; } stats_mesheval(me_eval, is_selected, stats); @@ -165,8 +165,8 @@ static void stats_object(Object *ob, case OB_SURF: case OB_CURVE: case OB_FONT: { - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - if ((me_eval != NULL) && !BLI_gset_add(objects_gset, me_eval)) { + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); + if ((me_eval != NULL) && !BLI_gset_add(objects_gset, (void *)me_eval)) { break; } @@ -179,7 +179,7 @@ static void stats_object(Object *ob, int totv = 0, totf = 0, tottri = 0; if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) { - /* Note: We only get the same curve_cache for instances of the same curve/font/... + /* NOTE: We only get the same curve_cache for instances of the same curve/font/... * For simple linked duplicated objects, each has its own dispList. */ if (!BLI_gset_add(objects_gset, ob->runtime.curve_cache)) { break; diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index aef59e89325..e656155fb13 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -353,7 +353,7 @@ int textview_draw(TextViewContext *tvc, tds.lheight = tvc->lheight; tds.row_vpadding = tvc->row_vpadding; tds.lofs = -BLF_descender(font_id); - /* Note, scroll bar must be already subtracted. */ + /* NOTE: scroll bar must be already subtracted. */ tds.columns = (tvc->draw_rect.xmax - tvc->draw_rect.xmin) / tds.cwidth; /* Avoid divide by zero on small windows. */ if (tds.columns < 1) { diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index f2cea23af76..0498964c549 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -288,14 +288,14 @@ static int mouse_nla_channels( /* button region... */ if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { if (nlaedit_is_tweakmode_on(ac) == 0) { - /* 'push-down' action - only usable when not in TweakMode */ + /* 'push-down' action - only usable when not in tweak-mode */ /* TODO: make this use the operator instead of calling the function directly * however, calling the operator requires that we supply the args, * and that works with proper buttons only */ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ale->id)); } else { - /* when in tweakmode, this button becomes the toggle for mapped editing */ + /* When in tweak-mode, this button becomes the toggle for mapped editing. */ adt->flag ^= ADT_NLA_EDIT_NOMAP; } @@ -308,13 +308,13 @@ static int mouse_nla_channels( /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block * - this is useful when there's no clear divider, and makes more sense in * the case of users trying to use this to change actions - * - in tweakmode, clicking here gets us out of tweakmode, as changing selection - * while in tweakmode is really evil! + * - in tweak-mode, clicking here gets us out of tweak-mode, as changing selection + * while in tweak-mode is really evil! * - we disable "solo" flags too, to make it easier to work with stashed actions * with less trouble */ if (nlaedit_is_tweakmode_on(ac)) { - /* exit tweakmode immediately */ + /* Exit tweak-mode immediately. */ nlaedit_disable_tweakmode(ac, true); /* changes to NLA-Action occurred */ @@ -515,7 +515,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* 'push-down' action - only usable when not in TweakMode */ + /* 'push-down' action - only usable when not in Tweak-mode. */ BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id)); struct Main *bmain = CTX_data_main(C); @@ -874,7 +874,7 @@ static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op)) /* operate on selected objects... */ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { /* ensure that object has AnimData... that's all */ - BKE_animdata_add_id(&ob->id); + BKE_animdata_ensure_id(&ob->id); } CTX_DATA_END; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 0fd1a1318e8..f9fb386095d 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -127,8 +127,8 @@ static void nla_action_draw_keyframes( immRectf(pos_id, f1, ymin + 2, f2, ymax - 2); immUnbindProgram(); - /* count keys before drawing */ - /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */ + /* Count keys before drawing. */ + /* NOTE: It's safe to cast #DLRBT_Tree, as it's designed to degrade down to a #ListBase. */ uint key_len = BLI_listbase_count((ListBase *)&keys); if (key_len > 0) { diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 3ca3aa15cd3..56efcd8571f 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -65,7 +65,7 @@ #include "UI_view2d.h" #include "nla_intern.h" /* own include */ -#include "nla_private.h" /* FIXME... maybe this shouldn't be included? */ +#include "nla_private.h" /* FIXME: maybe this shouldn't be included? */ /* -------------------------------------------------------------------- */ /** \name Public Utilities @@ -135,7 +135,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ale->data; - /* try entering tweakmode if valid */ + /* Try entering tweak-mode if valid. */ ok |= BKE_nla_tweakmode_enter(adt); /* mark the active track as being "solo"? */ @@ -154,9 +154,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) ANIM_animdata_update(&ac, &anim_data); ANIM_animdata_freelist(&anim_data); - /* if we managed to enter tweakmode on at least one AnimData block, - * set the flag for this in the active scene and send notifiers - */ + /* If we managed to enter tweak-mode on at least one AnimData block, + * set the flag for this in the active scene and send notifiers. */ if (ac.scene && ok) { /* set editing flag */ ac.scene->flag |= SCE_NLA_EDIT_ON; @@ -206,7 +205,7 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot) /** \name Disable Tweak-Mode Operator * \{ */ -/* NLA Editor internal API function for exiting tweakmode */ +/* NLA Editor internal API function for exiting tweak-mode. */ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) { ListBase anim_data = {NULL, NULL}; @@ -232,7 +231,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) BKE_nlatrack_solo_toggle(adt, NULL); } - /* to be sure that we're doing everything right, just exit tweakmode... */ + /* To be sure that we're doing everything right, just exit tweak-mode. */ BKE_nla_tweakmode_exit(adt); ale->update |= ANIM_UPDATE_DEPS; @@ -242,7 +241,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) ANIM_animdata_update(ac, &anim_data); ANIM_animdata_freelist(&anim_data); - /* if we managed to enter tweakmode on at least one AnimData block, + /* if we managed to enter tweak-mode on at least one AnimData block, * set the flag for this in the active scene and send notifiers */ if (ac->scene) { @@ -257,7 +256,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) return true; } -/* exit tweakmode operator callback */ +/* Exit tweak-mode operator callback. */ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op) { bAnimContext ac; @@ -1157,7 +1156,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) NlaStrip *strip, *nstrip, *next; NlaTrack *track; - /* Note: We allow this operator in override context because it is almost always (from possible + /* NOTE: We allow this operator in override context because it is almost always (from possible * default user interactions) paired with the transform one, which will ensure that the new * strip ends up in a valid (local) track. */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 631dc2e550c..28f194877fa 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -39,17 +39,16 @@ /* ************************** poll callbacks for operators **********************************/ -/* tweakmode is NOT enabled */ +/* Tweak-mode is NOT enabled. */ bool nlaop_poll_tweakmode_off(bContext *C) { Scene *scene; /* for now, we check 2 things: * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag + * 2) tweak-mode is currently set as a 'per-scene' flag * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons + * but not all AnimData blocks will be in tweak-mode for various reasons. */ if (ED_operator_nla_active(C) == 0) { return 0; @@ -63,17 +62,16 @@ bool nlaop_poll_tweakmode_off(bContext *C) return 1; } -/* tweakmode IS enabled */ +/* Tweak-mode IS enabled. */ bool nlaop_poll_tweakmode_on(bContext *C) { Scene *scene; /* for now, we check 2 things: * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag + * 2) tweak-mode is currently set as a 'per-scene' flag * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons + * but not all AnimData blocks will be in tweak-mode for various reasons. */ if (ED_operator_nla_active(C) == 0) { return 0; @@ -87,7 +85,7 @@ bool nlaop_poll_tweakmode_on(bContext *C) return 1; } -/* is tweakmode enabled - for use in NLA operator code */ +/* is tweak-mode enabled - for use in NLA operator code */ bool nlaedit_is_tweakmode_on(bAnimContext *ac) { if (ac && ac->scene) { diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index dc95a01a021..246c3e0156a 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -453,7 +453,7 @@ static void nlaedit_select_leftright(bContext *C, Scene *scene = ac->scene; float xmin, xmax; - /* if currently in tweakmode, exit tweakmode first */ + /* if currently in tweak-mode, exit tweak-mode first */ if (scene->flag & SCE_NLA_EDIT_ON) { WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); } @@ -612,7 +612,7 @@ static int mouse_nla_strips(bContext *C, nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip); - /* if currently in tweakmode, exit tweakmode before changing selection states + /* if currently in tweak-mode, exit tweak-mode before changing selection states * now that we've found our target... */ if (scene->flag & SCE_NLA_EDIT_ON) { diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 6e234c5b2ce..80d3b43bf6b 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../compositor ../../depsgraph ../../draw + ../../functions ../../gpu ../../imbuf ../../makesdna @@ -39,7 +40,6 @@ set(INC set(SRC drawnode.cc node_add.cc - node_buttons.c node_draw.cc node_edit.cc node_geometry_attribute_search.cc @@ -78,4 +78,20 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() +if(WITH_TBB) + add_definitions(-DWITH_TBB) + if(WIN32) + # TBB includes Windows.h which will define min/max macros + # that will collide with the stl versions. + add_definitions(-DNOMINMAX) + endif() + list(APPEND INC_SYS + ${TBB_INCLUDE_DIRS} + ) + + list(APPEND LIB + ${TBB_LIBRARIES} + ) +endif() + blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index d99433b47a8..8da67bbd21b 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -758,7 +758,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA uiItemR(layout, ptr, "extension", DEFAULT_FLAGS, "", ICON_NONE); - /* note: image user properties used directly here, unlike compositor image node, + /* NOTE: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. */ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false, true); @@ -1953,8 +1953,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi 0, 0, 0, - false, - false); + UI_TEMPLATE_LIST_FLAG_NONE); RNA_property_collection_lookup_int( ptr, RNA_struct_find_property(ptr, "layer_slots"), active_index, &active_input_ptr); } @@ -1972,8 +1971,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi 0, 0, 0, - false, - false); + UI_TEMPLATE_LIST_FLAG_NONE); RNA_property_collection_lookup_int( ptr, RNA_struct_find_property(ptr, "file_slots"), active_index, &active_input_ptr); } @@ -4029,8 +4027,10 @@ static struct { GPUVertBuf *inst_vbo; uint p0_id, p1_id, p2_id, p3_id; uint colid_id, muted_id; + uint dim_factor_id; GPUVertBufRaw p0_step, p1_step, p2_step, p3_step; GPUVertBufRaw colid_step, muted_step; + GPUVertBufRaw dim_factor_step; uint count; bool enabled; } g_batch_link; @@ -4045,6 +4045,8 @@ static void nodelink_batch_reset() g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step); GPU_vertbuf_attr_get_raw_data( g_batch_link.inst_vbo, g_batch_link.muted_id, &g_batch_link.muted_step); + GPU_vertbuf_attr_get_raw_data( + g_batch_link.inst_vbo, g_batch_link.dim_factor_id, &g_batch_link.dim_factor_step); g_batch_link.count = 0; } @@ -4162,6 +4164,8 @@ static void nodelink_batch_init() &format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT); g_batch_link.muted_id = GPU_vertformat_attr_add( &format_inst, "domuted", GPU_COMP_U8, 2, GPU_FETCH_INT); + g_batch_link.dim_factor_id = GPU_vertformat_attr_add( + &format_inst, "dim_factor", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM); /* Alloc max count but only draw the range we need. */ GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); @@ -4237,7 +4241,8 @@ static void nodelink_batch_add_link(const SpaceNode *snode, int th_col2, int th_col3, bool drawarrow, - bool drawmuted) + bool drawmuted, + float dim_factor) { /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */ BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); @@ -4256,6 +4261,7 @@ static void nodelink_batch_add_link(const SpaceNode *snode, colid[3] = drawarrow; char *muted = (char *)GPU_vertbuf_raw_step(&g_batch_link.muted_step); muted[0] = drawmuted; + *(float *)GPU_vertbuf_raw_step(&g_batch_link.dim_factor_step) = dim_factor; if (g_batch_link.count == NODELINK_GROUP_SIZE) { nodelink_batch_draw(snode); @@ -4270,6 +4276,8 @@ void node_draw_link_bezier(const View2D *v2d, int th_col2, int th_col3) { + const float dim_factor = node_link_dim_factor(v2d, link); + float vec[4][2]; const bool highlighted = link->flag & NODE_LINK_TEMP_HIGHLIGHT; if (node_link_bezier_handles(v2d, snode, link, vec)) { @@ -4282,8 +4290,17 @@ void node_draw_link_bezier(const View2D *v2d, if (g_batch_link.enabled && !highlighted) { /* Add link to batch. */ - nodelink_batch_add_link( - snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow, drawmuted); + nodelink_batch_add_link(snode, + vec[0], + vec[1], + vec[2], + vec[3], + th_col1, + th_col2, + th_col3, + drawarrow, + drawmuted, + dim_factor); } else { /* Draw single link. */ @@ -4308,12 +4325,13 @@ void node_draw_link_bezier(const View2D *v2d, GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE); GPU_batch_uniform_1i(batch, "doArrow", drawarrow); GPU_batch_uniform_1i(batch, "doMuted", drawmuted); + GPU_batch_uniform_1f(batch, "dim_factor", dim_factor); GPU_batch_draw(batch); } } } -/* note; this is used for fake links in groups too */ +/* NOTE: this is used for fake links in groups too. */ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) { int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE; diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index 6143af8ed70..9264c9d3572 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -90,7 +90,7 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx nodeSetSelected(node, true); ntreeUpdateTree(bmain, snode->edittree); - ED_node_set_active(bmain, snode->edittree, node, nullptr); + ED_node_set_active(bmain, snode, snode->edittree, node, nullptr); snode_update(snode, node); @@ -260,7 +260,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op) BLI_listbase_clear(&input_links); for (link = (bNodeLink *)ntree->links.first; link; link = link->next) { - if (nodeLinkIsHidden(link)) { + if (node_link_is_hidden_or_dimmed(®ion->v2d, link)) { continue; } if (add_reroute_intersect_check(link, mcoords, i, insert_point)) { diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c deleted file mode 100644 index 336b0c46a81..00000000000 --- a/source/blender/editors/space_node/node_buttons.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spnode - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_node_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" - -#include "BLT_translation.h" - -#include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_node.h" -#include "BKE_screen.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "RNA_access.h" - -#include "ED_screen.h" - -#include "UI_resources.h" - -#include "node_intern.h" /* own include */ - -/* ******************* node space & buttons ************** */ - -#if 0 -/* poll for active nodetree */ -static bool active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->nodetree); -} -#endif - -static bool node_sockets_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->nodetree && G.debug_value == 777); -} - -static void node_sockets_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - bNode *node = nodeGetActive(ntree); - if (node == NULL) { - return; - } - - LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { - char name[UI_MAX_NAME_STR]; - BLI_snprintf(name, sizeof(name), "%s:", socket->name); - - uiLayout *split = uiLayoutSplit(panel->layout, 0.35f, false); - uiItemL(split, name, ICON_NONE); - uiTemplateNodeLink(split, (bContext *)C, ntree, node, socket); - } -} - -static bool node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - return (snode && snode->edittree && - (snode->edittree->inputs.first || snode->edittree->outputs.first)); -} - -static bNodeSocket *node_tree_find_active_socket(bNodeTree *ntree, const eNodeSocketInOut in_out) -{ - ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; - LISTBASE_FOREACH (bNodeSocket *, socket, sockets) { - if (socket->flag & SELECT) { - return socket; - } - } - return NULL; -} - -static void draw_socket_list(const bContext *C, - uiLayout *layout, - bNodeTree *ntree, - const eNodeSocketInOut in_out) -{ - PointerRNA tree_ptr; - RNA_id_pointer_create((ID *)ntree, &tree_ptr); - - uiLayout *split = uiLayoutRow(layout, false); - uiLayout *list_col = uiLayoutColumn(split, true); - uiTemplateList(list_col, - (bContext *)C, - "NODE_UL_interface_sockets", - (in_out == SOCK_IN) ? "inputs" : "outputs", - &tree_ptr, - (in_out == SOCK_IN) ? "inputs" : "outputs", - &tree_ptr, - (in_out == SOCK_IN) ? "active_input" : "active_output", - NULL, - 0, - 0, - 0, - 0, - false, - false); - PointerRNA opptr; - uiLayout *ops_col = uiLayoutColumn(split, false); - uiLayout *add_remove_col = uiLayoutColumn(ops_col, true); - wmOperatorType *ot = WM_operatortype_find("NODE_OT_tree_socket_add", false); - uiItemFullO_ptr(add_remove_col, ot, "", ICON_ADD, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "in_out", in_out); - ot = WM_operatortype_find("NODE_OT_tree_socket_remove", false); - uiItemFullO_ptr(add_remove_col, ot, "", ICON_REMOVE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "in_out", in_out); - - uiItemS(ops_col); - - uiLayout *up_down_col = uiLayoutColumn(ops_col, true); - ot = WM_operatortype_find("NODE_OT_tree_socket_move", false); - uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "direction", 1); - RNA_enum_set(&opptr, "in_out", in_out); - uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); - RNA_enum_set(&opptr, "direction", 2); - RNA_enum_set(&opptr, "in_out", in_out); - - bNodeSocket *socket = node_tree_find_active_socket(ntree, in_out); - if (socket != NULL) { - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - PointerRNA socket_ptr; - RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, socket, &socket_ptr); - uiItemR(layout, &socket_ptr, "name", 0, NULL, ICON_NONE); - - /* Display descriptions only for Geometry Nodes, since it's only used in the modifier panel. */ - if (ntree->type == NTREE_GEOMETRY) { - uiItemR(layout, &socket_ptr, "description", 0, NULL, ICON_NONE); - } - - if (socket->typeinfo->interface_draw) { - socket->typeinfo->interface_draw((bContext *)C, layout, &socket_ptr); - } - } -} - -static void node_tree_interface_inputs_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - - draw_socket_list(C, panel->layout, ntree, SOCK_IN); -} - -static void node_tree_interface_outputs_panel(const bContext *C, Panel *panel) -{ - SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */ - bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */ - - draw_socket_list(C, panel->layout, ntree, SOCK_OUT); -} - -/* ******************* node buttons registration ************** */ - -void node_buttons_register(ARegionType *art) -{ - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_sockets"); - strcpy(pt->category, N_("Node")); - strcpy(pt->label, N_("Sockets")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_sockets_panel; - pt->poll = node_sockets_poll; - pt->flag |= PANEL_TYPE_DEFAULT_CLOSED; - BLI_addtail(&art->paneltypes, pt); - } - - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_node_tree_interface_inputs"); - strcpy(pt->category, N_("Group")); - strcpy(pt->label, N_("Inputs")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_tree_interface_inputs_panel; - pt->poll = node_tree_interface_poll; - BLI_addtail(&art->paneltypes, pt); - } - { - PanelType *pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "NODE_PT_node_tree_interface_outputs"); - strcpy(pt->category, N_("Group")); - strcpy(pt->label, N_("Outputs")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = node_tree_interface_outputs_panel; - pt->poll = node_tree_interface_poll; - BLI_addtail(&art->paneltypes, pt); - } -} diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 8599b159cca..ed88489c63e 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -45,10 +45,10 @@ #include "BLT_translation.h" #include "BKE_context.h" +#include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -76,6 +76,8 @@ #include "RNA_access.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "node_intern.h" /* own include */ #ifdef WITH_COMPOSITOR @@ -86,6 +88,9 @@ using blender::Map; using blender::Set; using blender::Span; using blender::Vector; +using blender::fn::CPPType; +using blender::fn::GPointer; +namespace geo_log = blender::nodes::geometry_nodes_eval_log; extern "C" { /* XXX interface.h */ @@ -833,6 +838,149 @@ void node_socket_color_get(bContext *C, } } +struct SocketTooltipData { + bNodeTree *ntree; + bNode *node; + bNodeSocket *socket; +}; + +static void create_inspection_string_for_generic_value(const geo_log::GenericValueLog &value_log, + std::stringstream &ss) +{ + auto id_to_inspection_string = [&](ID *id) { + ss << (id ? id->name + 2 : TIP_("None")) << " (" << BKE_idtype_idcode_to_name(GS(id->name)) + << ")"; + }; + + const GPointer value = value_log.value(); + if (value.is_type<int>()) { + ss << *value.get<int>() << TIP_(" (Integer)"); + } + else if (value.is_type<float>()) { + ss << *value.get<float>() << TIP_(" (Float)"); + } + else if (value.is_type<blender::float3>()) { + ss << *value.get<blender::float3>() << TIP_(" (Vector)"); + } + else if (value.is_type<bool>()) { + ss << (*value.get<bool>() ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)"); + } + else if (value.is_type<std::string>()) { + ss << *value.get<std::string>() << TIP_(" (String)"); + } + else if (value.is_type<Object *>()) { + id_to_inspection_string((ID *)*value.get<Object *>()); + } + else if (value.is_type<Material *>()) { + id_to_inspection_string((ID *)*value.get<Material *>()); + } + else if (value.is_type<Tex *>()) { + id_to_inspection_string((ID *)*value.get<Tex *>()); + } + else if (value.is_type<Collection *>()) { + id_to_inspection_string((ID *)*value.get<Collection *>()); + } +} + +static void create_inspection_string_for_geometry(const geo_log::GeometryValueLog &value_log, + std::stringstream &ss) +{ + Span<GeometryComponentType> component_types = value_log.component_types(); + if (component_types.is_empty()) { + ss << TIP_("Empty Geometry"); + return; + } + + auto to_string = [](int value) { + char str[16]; + BLI_str_format_int_grouped(str, value); + return std::string(str); + }; + + ss << TIP_("Geometry:\n"); + for (GeometryComponentType type : component_types) { + const char *line_end = (type == component_types.last()) ? "" : ".\n"; + switch (type) { + case GEO_COMPONENT_TYPE_MESH: { + const geo_log::GeometryValueLog::MeshInfo &mesh_info = *value_log.mesh_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Mesh: %s vertices, %s edges, %s faces"), + to_string(mesh_info.tot_verts).c_str(), + to_string(mesh_info.tot_edges).c_str(), + to_string(mesh_info.tot_faces).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_POINT_CLOUD: { + const geo_log::GeometryValueLog::PointCloudInfo &pointcloud_info = + *value_log.pointcloud_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Point Cloud: %s points"), + to_string(pointcloud_info.tot_points).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_CURVE: { + const geo_log::GeometryValueLog::CurveInfo &curve_info = *value_log.curve_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Curve: %s splines"), + to_string(curve_info.tot_splines).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_INSTANCES: { + const geo_log::GeometryValueLog::InstancesInfo &instances_info = *value_log.instances_info; + char line[256]; + BLI_snprintf(line, + sizeof(line), + TIP_("\u2022 Instances: %s"), + to_string(instances_info.tot_instances).c_str()); + ss << line << line_end; + break; + } + case GEO_COMPONENT_TYPE_VOLUME: { + ss << TIP_("\u2022 Volume") << line_end; + break; + } + } + } +} + +static std::optional<std::string> create_socket_inspection_string(bContext *C, + bNodeTree &UNUSED(ntree), + bNode &node, + bNodeSocket &socket) +{ + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::SocketLog *socket_log = geo_log::ModifierLog::find_socket_by_node_editor_context( + *snode, node, socket); + if (socket_log == nullptr) { + return {}; + } + const geo_log::ValueLog *value_log = socket_log->value(); + if (value_log == nullptr) { + return {}; + } + + std::stringstream ss; + if (const geo_log::GenericValueLog *generic_value_log = + dynamic_cast<const geo_log::GenericValueLog *>(value_log)) { + create_inspection_string_for_generic_value(*generic_value_log, ss); + } + else if (const geo_log::GeometryValueLog *geo_value_log = + dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) { + create_inspection_string_for_geometry(*geo_value_log, ss); + } + + return ss.str(); +} + static void node_socket_draw_nested(const bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, @@ -863,6 +1011,55 @@ static void node_socket_draw_nested(const bContext *C, shape_id, size_id, outline_col_id); + + if (ntree->type != NTREE_GEOMETRY) { + /* Only geometry nodes has socket value tooltips currently. */ + return; + } + + bNode *node = (bNode *)node_ptr->data; + uiBlock *block = node->block; + + /* Ideally sockets themselves should be buttons, but they aren't currently. So add an invisible + * button on top of them for the tooltip. */ + const eUIEmbossType old_emboss = UI_block_emboss_get(block); + UI_block_emboss_set(block, UI_EMBOSS_NONE); + uiBut *but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_NONE, + sock->locx - size / 2, + sock->locy - size / 2, + size, + size, + nullptr, + 0, + 0, + 0, + 0, + nullptr); + + SocketTooltipData *data = (SocketTooltipData *)MEM_mallocN(sizeof(SocketTooltipData), __func__); + data->ntree = ntree; + data->node = (bNode *)node_ptr->data; + data->socket = sock; + + UI_but_func_tooltip_set( + but, + [](bContext *C, void *argN, const char *UNUSED(tip)) { + SocketTooltipData *data = (SocketTooltipData *)argN; + std::optional<std::string> str = create_socket_inspection_string( + C, *data->ntree, *data->node, *data->socket); + if (str.has_value()) { + return BLI_strdup(str->c_str()); + } + return BLI_strdup(TIP_("The socket value has not been computed yet")); + }, + data, + MEM_freeN); + /* Disable the button so that clicks on it are ignored the the link operator still works. */ + UI_but_flag_enable(but, UI_BUT_DISABLED); + UI_block_emboss_set(block, old_emboss); } /** @@ -1203,14 +1400,14 @@ void node_draw_sockets(const View2D *v2d, } } -static int node_error_type_to_icon(const NodeWarningType type) +static int node_error_type_to_icon(const geo_log::NodeWarningType type) { switch (type) { - case NodeWarningType::Error: + case geo_log::NodeWarningType::Error: return ICON_ERROR; - case NodeWarningType::Warning: + case geo_log::NodeWarningType::Warning: return ICON_ERROR; - case NodeWarningType::Info: + case geo_log::NodeWarningType::Info: return ICON_INFO; } @@ -1218,14 +1415,14 @@ static int node_error_type_to_icon(const NodeWarningType type) return ICON_ERROR; } -static uint8_t node_error_type_priority(const NodeWarningType type) +static uint8_t node_error_type_priority(const geo_log::NodeWarningType type) { switch (type) { - case NodeWarningType::Error: + case geo_log::NodeWarningType::Error: return 3; - case NodeWarningType::Warning: + case geo_log::NodeWarningType::Warning: return 2; - case NodeWarningType::Info: + case geo_log::NodeWarningType::Info: return 1; } @@ -1233,11 +1430,11 @@ static uint8_t node_error_type_priority(const NodeWarningType type) return 0; } -static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings) +static geo_log::NodeWarningType node_error_highest_priority(Span<geo_log::NodeWarning> warnings) { uint8_t highest_priority = 0; - NodeWarningType highest_priority_type = NodeWarningType::Info; - for (const NodeWarning &warning : warnings) { + geo_log::NodeWarningType highest_priority_type = geo_log::NodeWarningType::Info; + for (const geo_log::NodeWarning &warning : warnings) { const uint8_t priority = node_error_type_priority(warning.type); if (priority > highest_priority) { highest_priority = priority; @@ -1247,15 +1444,17 @@ static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings) return highest_priority_type; } +struct NodeErrorsTooltipData { + Span<geo_log::NodeWarning> warnings; +}; + static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char *UNUSED(tip)) { - const NodeUIStorage **storage_pointer_alloc = static_cast<const NodeUIStorage **>(argN); - const NodeUIStorage *node_ui_storage = *storage_pointer_alloc; - Span<NodeWarning> warnings = node_ui_storage->warnings; + NodeErrorsTooltipData &data = *(NodeErrorsTooltipData *)argN; std::string complete_string; - for (const NodeWarning &warning : warnings.drop_back(1)) { + for (const geo_log::NodeWarning &warning : data.warnings.drop_back(1)) { complete_string += warning.message; /* Adding the period is not ideal for multi-line messages, but it is consistent * with other tooltip implementations in Blender, so it is added here. */ @@ -1264,7 +1463,7 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char } /* Let the tooltip system automatically add the last period. */ - complete_string += warnings.last().message; + complete_string += data.warnings.last().message; return BLI_strdupn(complete_string.c_str(), complete_string.size()); } @@ -1272,20 +1471,26 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char #define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit) static void node_add_error_message_button( - const bContext *C, bNodeTree &ntree, bNode &node, const rctf &rect, float &icon_offset) + const bContext *C, bNodeTree &UNUSED(ntree), bNode &node, const rctf &rect, float &icon_offset) { - const NodeUIStorage *node_ui_storage = BKE_node_tree_ui_storage_get_from_context(C, ntree, node); - if (node_ui_storage == nullptr || node_ui_storage->warnings.is_empty()) { + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(*snode, + node); + if (node_log == nullptr) { + return; + } + + Span<geo_log::NodeWarning> warnings = node_log->warnings(); + + if (warnings.is_empty()) { return; } - /* The UI API forces us to allocate memory for each error button, because the - * ownership of #UI_but_func_tooltip_set's argument is transferred to the button. */ - const NodeUIStorage **storage_pointer_alloc = (const NodeUIStorage **)MEM_mallocN( - sizeof(NodeUIStorage *), __func__); - *storage_pointer_alloc = node_ui_storage; + NodeErrorsTooltipData *tooltip_data = (NodeErrorsTooltipData *)MEM_mallocN( + sizeof(NodeErrorsTooltipData), __func__); + tooltip_data->warnings = warnings; - const NodeWarningType display_type = node_error_highest_priority(node_ui_storage->warnings); + const geo_log::NodeWarningType display_type = node_error_highest_priority(warnings); icon_offset -= NODE_HEADER_ICON_SIZE; UI_block_emboss_set(node.block, UI_EMBOSS_NONE); @@ -1303,7 +1508,7 @@ static void node_add_error_message_button( 0, 0, nullptr); - UI_but_func_tooltip_set(but, node_errors_tooltip_fn, storage_pointer_alloc, MEM_freeN); + UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, MEM_freeN); UI_block_emboss_set(node.block, UI_EMBOSS); } @@ -1423,28 +1628,6 @@ static void node_draw_basis(const bContext *C, ""); UI_block_emboss_set(node->block, UI_EMBOSS); } - if (ntree->type == NTREE_GEOMETRY) { - /* Active preview toggle. */ - iconofs -= iconbutw; - UI_block_emboss_set(node->block, UI_EMBOSS_NONE); - int icon = (node->flag & NODE_ACTIVE_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON; - uiBut *but = uiDefIconBut(node->block, - UI_BTYPE_BUT_TOGGLE, - 0, - icon, - iconofs, - rct->ymax - NODE_DY, - iconbutw, - UI_UNIT_Y, - nullptr, - 0, - 0, - 0, - 0, - "Show this node's geometry output in the spreadsheet"); - UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_active_preview_toggle"); - UI_block_emboss_set(node->block, UI_EMBOSS); - } node_add_error_message_button(C, *ntree, *node, *rct, iconofs); diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 0cf47ed35fa..af9c888cbf7 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -21,6 +21,8 @@ * \ingroup spnode */ +#include <algorithm> + #include "MEM_guardedalloc.h" #include "DNA_light_types.h" @@ -54,6 +56,7 @@ #include "ED_render.h" #include "ED_screen.h" #include "ED_select_utils.h" +#include "ED_spreadsheet.h" #include "RNA_access.h" #include "RNA_define.h" @@ -662,7 +665,8 @@ void snode_update(SpaceNode *snode, bNode *node) } } -void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed) +void ED_node_set_active( + Main *bmain, SpaceNode *snode, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed) { const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0; if (r_active_texture_changed) { @@ -782,6 +786,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti } #endif } + else if (ntree->type == NTREE_GEOMETRY) { + if (node->type == GEO_NODE_VIEWER) { + if ((node->flag & NODE_DO_OUTPUT) == 0) { + LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) { + if (node_iter->type == GEO_NODE_VIEWER) { + node_iter->flag &= ~NODE_DO_OUTPUT; + } + } + node->flag |= NODE_DO_OUTPUT; + ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node); + } + } + } } } @@ -1211,6 +1228,32 @@ int node_find_indicated_socket( return 0; } +/* ****************** Link Dimming *********************** */ + +float node_link_dim_factor(const View2D *v2d, const bNodeLink *link) +{ + if (link->fromsock == nullptr || link->tosock == nullptr) { + return 1.0f; + } + + const float min_endpoint_distance = std::min( + std::max(BLI_rctf_length_x(&v2d->cur, link->fromsock->locx), + BLI_rctf_length_y(&v2d->cur, link->fromsock->locy)), + std::max(BLI_rctf_length_x(&v2d->cur, link->tosock->locx), + BLI_rctf_length_y(&v2d->cur, link->tosock->locy))); + + if (min_endpoint_distance == 0.0f) { + return 1.0f; + } + const float viewport_width = BLI_rctf_size_x(&v2d->cur); + return std::clamp(1.0f - min_endpoint_distance / viewport_width * 10.0f, 0.05f, 1.0f); +} + +bool node_link_is_hidden_or_dimmed(const View2D *v2d, const bNodeLink *link) +{ + return nodeLinkIsHidden(link) || node_link_dim_factor(v2d, link) < 0.5f; +} + /* ****************** Duplicate *********************** */ static void node_duplicate_reparent_recursive(bNode *node) @@ -1318,7 +1361,6 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) nodeSetSelected(node, false); node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE); nodeSetSelected(newnode, true); - newnode->flag &= ~NODE_ACTIVE_PREVIEW; do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode)); } @@ -2313,7 +2355,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) // nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr); } else { - /* XXX TODO define default socket type for a tree! */ + /* XXX TODO: define default socket type for a tree! */ sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name); } @@ -2400,6 +2442,109 @@ void NODE_OT_tree_socket_remove(wmOperatorType *ot) RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", ""); } +/********************** Change interface socket type operator *********************/ + +static int ntree_socket_change_type_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out"); + const bNodeSocketType *socket_type = rna_node_socket_type_from_enum( + RNA_enum_get(op->ptr, "socket_type")); + ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; + + Main *main = CTX_data_main(C); + + bNodeSocket *iosock = ntree_get_active_interface_socket(sockets); + if (iosock == nullptr) { + return OPERATOR_CANCELLED; + } + + /* The type remains the same, so we don't need to change anything. */ + if (iosock->typeinfo == socket_type) { + return OPERATOR_FINISHED; + } + + /* Don't handle subtypes for now. */ + nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname); + + /* Need the extra update here because the loop above does not check for valid links in the node + * group we're currently editing. */ + ntree->update |= NTREE_UPDATE_GROUP | NTREE_UPDATE_LINKS; + + /* Deactivate sockets. */ + LISTBASE_FOREACH (bNodeSocket *, socket_iter, sockets) { + socket_iter->flag &= ~SELECT; + } + /* Make the new socket active. */ + iosock->flag |= SELECT; + + ntreeUpdateTree(main, ntree); + + snode_notify(C, snode); + snode_dag_update(C, snode); + + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); + + return OPERATOR_FINISHED; +} + +static bool socket_change_poll_type(void *userdata, bNodeSocketType *socket_type) +{ + /* Check if the node tree supports the socket type. */ + bNodeTreeType *ntreetype = (bNodeTreeType *)userdata; + if (ntreetype->valid_socket_type && !ntreetype->valid_socket_type(ntreetype, socket_type)) { + return false; + } + + /* Only use basic socket types for this enum. */ + if (socket_type->subtype != PROP_NONE) { + return false; + } + + return true; +} + +static const EnumPropertyItem *socket_change_type_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + if (!C) { + return DummyRNA_NULL_items; + } + + SpaceNode *snode = CTX_wm_space_node(C); + if (!snode || !snode->edittree) { + return DummyRNA_NULL_items; + } + + return rna_node_socket_type_itemf(snode->edittree->typeinfo, socket_change_poll_type, r_free); +} + +void NODE_OT_tree_socket_change_type(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Change Node Tree Interface Socket Type"; + ot->description = "Change the type of a socket of the current node tree"; + ot->idname = "NODE_OT_tree_socket_change_type"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = ntree_socket_change_type_exec; + ot->poll = ED_operator_node_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", ""); + prop = RNA_def_enum(ot->srna, "socket_type", DummyRNA_DEFAULT_items, 0, "Socket Type", ""); + RNA_def_enum_funcs(prop, socket_change_type_itemf); + ot->prop = prop; +} + /********************** Move interface socket operator *********************/ static const EnumPropertyItem move_direction_items[] = { diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index e92449e3535..af35f9692ae 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -27,7 +27,6 @@ #include "DNA_space_types.h" #include "BKE_context.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "RNA_access.h" @@ -40,17 +39,21 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "node_intern.h" using blender::IndexRange; using blender::Map; using blender::Set; using blender::StringRef; +namespace geo_log = blender::nodes::geometry_nodes_eval_log; +using geo_log::GeometryAttributeInfo; struct AttributeSearchData { - AvailableAttributeInfo &dummy_info_for_search; - const NodeUIStorage &ui_storage; - bNodeSocket &socket; + const bNodeTree *tree; + const bNode *node; + bNodeSocket *socket; }; /* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */ @@ -73,7 +76,7 @@ static StringRef attribute_domain_string(const AttributeDomain domain) /* Unicode arrow. */ #define MENU_SEP "\xe2\x96\xb6" -static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttributeInfo &item) +static bool attribute_search_item_add(uiSearchItems *items, const GeometryAttributeInfo &item) { const StringRef data_type_name = attribute_data_type_string(item.data_type); const StringRef domain_name = attribute_domain_string(item.domain); @@ -84,31 +87,47 @@ static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttri items, search_item_text.c_str(), (void *)&item, ICON_NONE, UI_BUT_HAS_SEP_CHAR, 0); } -static void attribute_search_update_fn(const bContext *UNUSED(C), - void *arg, - const char *str, - uiSearchItems *items, - const bool is_first) +static GeometryAttributeInfo &get_dummy_item_info() +{ + static GeometryAttributeInfo info; + return info; +} + +static void attribute_search_update_fn( + const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) { AttributeSearchData *data = static_cast<AttributeSearchData *>(arg); - const Set<AvailableAttributeInfo> &attribute_hints = data->ui_storage.attribute_hints; + SpaceNode *snode = CTX_wm_space_node(C); + const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( + *snode, *data->node); + if (node_log == nullptr) { + return; + } + blender::Vector<const GeometryAttributeInfo *> infos = node_log->lookup_available_attributes(); + + GeometryAttributeInfo &dummy_info = get_dummy_item_info(); /* Any string may be valid, so add the current search string along with the hints. */ if (str[0] != '\0') { - /* Note that the attribute domain and data type are dummies, since - * #AvailableAttributeInfo equality is only based on the string. */ - if (!attribute_hints.contains(AvailableAttributeInfo{str, ATTR_DOMAIN_AUTO, CD_PROP_BOOL})) { - data->dummy_info_for_search.name = std::string(str); - UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_ADD, 0, 0); + bool contained = false; + for (const GeometryAttributeInfo *attribute_info : infos) { + if (attribute_info->name == str) { + contained = true; + break; + } + } + if (!contained) { + dummy_info.name = str; + UI_search_item_add(items, str, &dummy_info, ICON_ADD, 0, 0); } } if (str[0] == '\0' && !is_first) { /* Allow clearing the text field when the string is empty, but not on the first pass, * or opening an attribute field for the first time would show this search item. */ - data->dummy_info_for_search.name = std::string(str); - UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_X, 0, 0); + dummy_info.name = str; + UI_search_item_add(items, str, &dummy_info, ICON_X, 0, 0); } /* Don't filter when the menu is first opened, but still run the search @@ -116,15 +135,15 @@ static void attribute_search_update_fn(const bContext *UNUSED(C), const char *string = is_first ? "" : str; StringSearch *search = BLI_string_search_new(); - for (const AvailableAttributeInfo &item : attribute_hints) { - BLI_string_search_add(search, item.name.c_str(), (void *)&item); + for (const GeometryAttributeInfo *item : infos) { + BLI_string_search_add(search, item->name.c_str(), (void *)item); } - AvailableAttributeInfo **filtered_items; + GeometryAttributeInfo **filtered_items; const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items); for (const int i : IndexRange(filtered_amount)) { - const AvailableAttributeInfo *item = filtered_items[i]; + const GeometryAttributeInfo *item = filtered_items[i]; if (!attribute_search_item_add(items, *item)) { break; } @@ -136,10 +155,13 @@ static void attribute_search_update_fn(const bContext *UNUSED(C), static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v) { + if (item_v == nullptr) { + return; + } AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v); - AvailableAttributeInfo *item = static_cast<AvailableAttributeInfo *>(item_v); + GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v; - bNodeSocket &socket = data->socket; + bNodeSocket &socket = *data->socket; switch (socket.type) { case SOCK_STRING: { bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value); @@ -157,23 +179,13 @@ static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v) ED_undo_push(C, "Assign Attribute Name"); } -void node_geometry_add_attribute_search_button(const bContext *C, +void node_geometry_add_attribute_search_button(const bContext *UNUSED(C), const bNodeTree *node_tree, const bNode *node, PointerRNA *socket_ptr, const char *propname, uiLayout *layout) { - const NodeUIStorage *ui_storage = BKE_node_tree_ui_storage_get_from_context( - C, *node_tree, *node); - - if (ui_storage == nullptr) { - uiItemR(layout, socket_ptr, propname, 0, "", 0); - return; - } - - const NodeTreeUIStorage *tree_ui_storage = node_tree->ui_storage; - uiBlock *block = uiLayoutGetBlock(layout); uiBut *but = uiDefIconTextButR(block, UI_BTYPE_SEARCH_MENU, @@ -193,10 +205,8 @@ void node_geometry_add_attribute_search_button(const bContext *C, 0.0f, ""); - AttributeSearchData *data = OBJECT_GUARDED_NEW(AttributeSearchData, - {tree_ui_storage->dummy_info_for_search, - *ui_storage, - *static_cast<bNodeSocket *>(socket_ptr->data)}); + AttributeSearchData *data = OBJECT_GUARDED_NEW( + AttributeSearchData, {node_tree, node, (bNodeSocket *)socket_ptr->data}); UI_but_func_search_set_results_are_suggestions(but, true); UI_but_func_search_set_sep_string(but, MENU_SEP); diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.c index 8547c825230..e1deca54890 100644 --- a/source/blender/editors/space_node/node_gizmo.c +++ b/source/blender/editors/space_node/node_gizmo.c @@ -155,7 +155,7 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup * WM_gizmo_set_matrix_location(cage, origin); WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ SpaceNode *snode = CTX_wm_space_node(C); #if 0 PointerRNA nodeptr; @@ -492,7 +492,7 @@ static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgr SpaceNode *snode = CTX_wm_space_node(C); bNode *node = nodeGetActive(snode->edittree); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ PointerRNA nodeptr; RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr); WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1); @@ -604,7 +604,7 @@ static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup SpaceNode *snode = CTX_wm_space_node(C); bNode *node = nodeGetActive(snode->edittree); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ int i = 0; for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) { if (sock->type == SOCK_VECTOR) { diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 73de87b8c14..385bf8ab4a8 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -52,7 +52,7 @@ typedef struct bNodeLinkDrag { struct bNodeLinkDrag *next, *prev; /* List of links dragged by the operator. - * Note: This is a list of LinkData structs on top of the actual bNodeLinks. + * NOTE: This is a list of LinkData structs on top of the actual bNodeLinks. * This way the links can be added to the node tree while being stored in this list. */ ListBase links; @@ -141,9 +141,6 @@ void node_to_view(const struct bNode *node, float x, float y, float *rx, float * void node_to_updated_rect(const struct bNode *node, rctf *r_rect); void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); -/* node_buttons.c */ -void node_buttons_register(struct ARegionType *art); - /* node_toolbar.c */ void node_toolbar_register(struct ARegionType *art); @@ -269,6 +266,8 @@ int node_find_indicated_socket(struct SpaceNode *snode, struct bNodeSocket **sockp, const float cursor[2], int in_out); +float node_link_dim_factor(const struct View2D *v2d, const struct bNodeLink *link); +bool node_link_is_hidden_or_dimmed(const struct View2D *v2d, const struct bNodeLink *link); void NODE_OT_duplicate(struct wmOperatorType *ot); void NODE_OT_delete(struct wmOperatorType *ot); @@ -280,7 +279,6 @@ void NODE_OT_hide_toggle(struct wmOperatorType *ot); void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot); void NODE_OT_preview_toggle(struct wmOperatorType *ot); void NODE_OT_options_toggle(struct wmOperatorType *ot); -void NODE_OT_active_preview_toggle(struct wmOperatorType *ot); void NODE_OT_node_copy_color(struct wmOperatorType *ot); void NODE_OT_read_viewlayers(struct wmOperatorType *ot); @@ -292,12 +290,13 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot); void NODE_OT_switch_view_update(struct wmOperatorType *ot); -/* Note: clipboard_cut is a simple macro of copy + delete */ +/* NOTE: clipboard_cut is a simple macro of copy + delete. */ void NODE_OT_clipboard_copy(struct wmOperatorType *ot); void NODE_OT_clipboard_paste(struct wmOperatorType *ot); void NODE_OT_tree_socket_add(struct wmOperatorType *ot); void NODE_OT_tree_socket_remove(struct wmOperatorType *ot); +void NODE_OT_tree_socket_change_type(struct wmOperatorType *ot); void NODE_OT_tree_socket_move(struct wmOperatorType *ot); void NODE_OT_shader_script_update(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index e35b444aa11..610c2889e7a 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -119,6 +119,7 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_tree_socket_add); WM_operatortype_append(NODE_OT_tree_socket_remove); + WM_operatortype_append(NODE_OT_tree_socket_change_type); WM_operatortype_append(NODE_OT_tree_socket_move); WM_operatortype_append(NODE_OT_cryptomatte_layer_add); @@ -157,7 +158,7 @@ void ED_operatormacros_node(void) WM_operatortype_macro_define(ot, "NODE_OT_attach"); WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); - /* Note: Currently not in a default keymap or menu due to messy keymaps + /* NOTE: Currently not in a default keymap or menu due to messy keymaps * and tricky invoke functionality. * Kept around in case users want to make own shortcuts. */ diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 5c251b47746..4e6e8937bb4 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -36,15 +36,19 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_screen.h" #include "ED_node.h" /* own include */ #include "ED_render.h" #include "ED_screen.h" +#include "ED_spreadsheet.h" #include "ED_util.h" #include "RNA_access.h" #include "RNA_define.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -160,6 +164,11 @@ bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node) return true; } } + if (current_node->type == GEO_NODE_VIEWER) { + if (ntree_check_nodes_connected(ntree, node, current_node)) { + return true; + } + } } return false; } @@ -610,14 +619,14 @@ static int node_link_viewer(const bContext *C, bNode *tonode) if (tonode == nullptr || BLI_listbase_is_empty(&tonode->outputs)) { return OPERATOR_CANCELLED; } - if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) { return OPERATOR_CANCELLED; } /* get viewer */ bNode *viewer_node = nullptr; LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) { if (node->flag & NODE_DO_OUTPUT) { viewer_node = node; break; @@ -627,7 +636,7 @@ static int node_link_viewer(const bContext *C, bNode *tonode) /* no viewer, we make one active */ if (viewer_node == nullptr) { LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) { node->flag |= NODE_DO_OUTPUT; viewer_node = node; break; @@ -686,7 +695,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode) /* add a new viewer if none exists yet */ if (!viewer_node) { /* XXX location is a quick hack, just place it next to the linked socket */ - viewer_node = node_add_node(C, nullptr, CMP_NODE_VIEWER, sock->locx + 100, sock->locy); + const int viewer_type = ED_node_is_compositor(snode) ? CMP_NODE_VIEWER : GEO_NODE_VIEWER; + viewer_node = node_add_node(C, nullptr, viewer_type, sock->locx + 100, sock->locy); if (!viewer_node) { return OPERATOR_CANCELLED; } @@ -712,8 +722,13 @@ static int node_link_viewer(const bContext *C, bNode *tonode) /* make sure the dependency sorting is updated */ snode->edittree->update |= NTREE_UPDATE_LINKS; } + if (ED_node_is_geometry(snode)) { + ED_spreadsheet_context_paths_set_geometry_node(CTX_data_main(C), snode, viewer_node); + } + ntreeUpdateTree(CTX_data_main(C), snode->edittree); snode_update(snode, viewer_node); + DEG_id_tag_update(&snode->edittree->id, 0); } return OPERATOR_FINISHED; @@ -739,6 +754,15 @@ static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static bool node_active_link_viewer_poll(bContext *C) +{ + if (!ED_operator_node_editable(C)) { + return false; + } + SpaceNode *snode = CTX_wm_space_node(C); + return ED_node_is_compositor(snode) || ED_node_is_geometry(snode); +} + void NODE_OT_link_viewer(wmOperatorType *ot) { /* identifiers */ @@ -748,7 +772,7 @@ void NODE_OT_link_viewer(wmOperatorType *ot) /* api callbacks */ ot->exec = node_active_link_viewer_exec; - ot->poll = composite_node_editable; + ot->poll = node_active_link_viewer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1309,7 +1333,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), bmain); LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &snode->edittree->links) { - if (nodeLinkIsHidden(link)) { + if (node_link_is_hidden_or_dimmed(®ion->v2d, link)) { continue; } @@ -1406,7 +1430,7 @@ static int mute_links_exec(bContext *C, wmOperator *op) /* Count intersected links and clear test flag. */ int tot = 0; LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - if (nodeLinkIsHidden(link)) { + if (node_link_is_hidden_or_dimmed(®ion->v2d, link)) { continue; } link->flag &= ~NODE_LINK_TEST; @@ -1420,7 +1444,7 @@ static int mute_links_exec(bContext *C, wmOperator *op) /* Mute links. */ LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - if (nodeLinkIsHidden(link) || (link->flag & NODE_LINK_TEST)) { + if (node_link_is_hidden_or_dimmed(®ion->v2d, link) || (link->flag & NODE_LINK_TEST)) { continue; } @@ -1435,7 +1459,7 @@ static int mute_links_exec(bContext *C, wmOperator *op) /* Clear remaining test flags. */ LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - if (nodeLinkIsHidden(link)) { + if (node_link_is_hidden_or_dimmed(®ion->v2d, link)) { continue; } link->flag &= ~NODE_LINK_TEST; @@ -1871,9 +1895,11 @@ static bool ed_node_link_conditions(ScrArea *area, return false; } + ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); + /* test node for links */ LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - if (nodeLinkIsHidden(link)) { + if (node_link_is_hidden_or_dimmed(®ion->v2d, link)) { continue; } @@ -1904,13 +1930,15 @@ void ED_node_link_intersect_test(ScrArea *area, int test) return; } + ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); + /* find link to select/highlight */ bNodeLink *selink = nullptr; float dist_best = FLT_MAX; LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { float coord_array[NODE_LINK_RESOL + 1][2]; - if (nodeLinkIsHidden(link)) { + if (node_link_is_hidden_or_dimmed(®ion->v2d, link)) { continue; } diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 41820cd813c..a081cc83481 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -44,6 +44,7 @@ #include "ED_node.h" /* own include */ #include "ED_screen.h" #include "ED_select_utils.h" +#include "ED_spreadsheet.h" #include "ED_view3d.h" #include "RNA_access.h" @@ -330,7 +331,7 @@ static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bo pref_len_act = BLI_str_partition_ex_utf8( node_act->name, nullptr, delims, &sep, &suf_act, from_right); - /* Note: in case we are searching for suffix, and found none, use whole name as suffix. */ + /* NOTE: in case we are searching for suffix, and found none, use whole name as suffix. */ if (from_right && !(sep && suf_act)) { pref_len_act = 0; suf_act = node_act->name; @@ -469,7 +470,7 @@ void node_select_single(bContext *C, bNode *node) } nodeSetSelected(node, true); - ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed); + ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed); ED_node_set_active_viewer_key(snode); ED_node_sort(snode->edittree); @@ -606,12 +607,18 @@ static int node_mouse_select(bContext *C, /* update node order */ if (ret_value != OPERATOR_CANCELLED) { bool active_texture_changed = false; + bool viewer_node_changed = false; if (node != nullptr && ret_value != OPERATOR_RUNNING_MODAL) { - ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed); + viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; + ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed); + } + else if (node != nullptr && node->type == GEO_NODE_VIEWER) { + ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node); } ED_node_set_active_viewer_key(snode); ED_node_sort(snode->edittree); - if (active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) { + if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) || + viewer_node_changed) { DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE); } diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc index 93599bc3c2a..10ad83e4fe9 100644 --- a/source/blender/editors/space_node/node_templates.cc +++ b/source/blender/editors/space_node/node_templates.cc @@ -364,7 +364,7 @@ static void ui_node_link_items(NodeLinkArg *arg, NodeLinkItem *item = &items[i]; item->socket_index = index; - /* note: int stemp->type is not fully reliable, not used for node group + /* NOTE: int stemp->type is not fully reliable, not used for node group * interface sockets. use the typeinfo->type instead. */ item->socket_type = stemp->typeinfo->type; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index f20a9409d90..ff848a7bb95 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -345,7 +345,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params) ScrArea *area = params->area; wmNotifier *wmn = params->notifier; - /* note, ED_area_tag_refresh will re-execute compositor */ + /* NOTE: #ED_area_tag_refresh will re-execute compositor. */ SpaceNode *snode = area->spacedata.first; /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ short shader_type = snode->shaderfrom; @@ -563,7 +563,7 @@ static SpaceLink *node_duplicate(SpaceLink *sl) BLI_listbase_clear(&snoden->runtime->linkdrag); } - /* Note: no need to set node tree user counts, + /* NOTE: no need to set node tree user counts, * the editor only keeps at least 1 (id_us_ensure_real), * which is already done by the original SpaceNode. */ @@ -651,6 +651,10 @@ static void node_main_region_init(wmWindowManager *wm, ARegion *region) lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); WM_event_add_dropbox_handler(®ion->handlers, lb); + + /* The backdrop image gizmo needs to change together with the view. So always refresh gizmos on + * region size changes. */ + WM_gizmomap_tag_refresh(region->gizmo_map); } static void node_main_region_draw(const bContext *C, ARegion *region) @@ -1094,8 +1098,6 @@ void ED_spacetype_node(void) art->draw = node_buttons_region_draw; BLI_addhead(&st->regiontypes, art); - node_buttons_register(art); - /* regions: toolbar */ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); art->regionid = RGN_TYPE_TOOLS; diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c index 4293d8da73e..d61bb17f661 100644 --- a/source/blender/editors/space_outliner/outliner_context.c +++ b/source/blender/editors/space_outliner/outliner_context.c @@ -64,7 +64,7 @@ int /*eContextResult*/ outliner_context(const bContext *C, outliner_context_selected_ids(space_outliner, result); return CTX_RESULT_OK; } - /* Note: Querying non-ID selection could also work if tree elements stored their matching RNA + /* NOTE: Querying non-ID selection could also work if tree elements stored their matching RNA * struct type. */ return CTX_RESULT_MEMBER_NOT_FOUND; diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 8021b45ac77..86aab86db10 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -1325,7 +1325,7 @@ static TreeElement *outliner_item_drag_element_find(SpaceOutliner *space_outline ARegion *region, const wmEvent *event) { - /* note: using EVT_TWEAK_ events to trigger dragging is fine, + /* NOTE: using EVT_TWEAK_ events to trigger dragging is fine, * it sends coordinates from where dragging was started */ const float my = UI_view2d_region_to_view_y(®ion->v2d, event->mval[1]); return outliner_find_item_at_y(space_outliner, &space_outliner->tree, my); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 4fe29d4e9bd..db37c8c1c8c 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -355,7 +355,7 @@ static void outliner_base_or_object_pointer_create( } } -/* Note: Collection is only valid when we want to change the collection data, otherwise we get it +/* NOTE: Collection is only valid when we want to change the collection data, otherwise we get it * from layer collection. Layer collection is valid whenever we are looking at a view layer. */ static void outliner_collection_set_flag_recursive(Scene *scene, ViewLayer *view_layer, @@ -374,7 +374,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene, /* Set the same flag for the nested objects as well. */ if (base_or_object_prop) { - /* Note: We can't use BKE_collection_object_cache_get() + /* NOTE: We can't use BKE_collection_object_cache_get() * otherwise we would not take collection exclusion into account. */ LISTBASE_FOREACH (CollectionObject *, cob, &layer_collection->collection->gobject) { @@ -414,7 +414,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene, * A collection is isolated if all its parents and children are "visible". * All the other collections must be "invisible". * - * Note: We could/should boost performance by iterating over the tree twice. + * NOTE: We could/should boost performance by iterating over the tree twice. * First tagging all the children/parent collections, then getting their values and comparing. * To run BKE_collection_has_collection() so many times is silly and slow. */ @@ -2356,6 +2356,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case eGpencilModifierType_Texture: data.icon = ICON_TEXTURE; break; + case eGpencilModifierType_Weight: + data.icon = ICON_MOD_VERTEX_WEIGHT; + break; /* Default */ default: @@ -2961,7 +2964,8 @@ static void outliner_draw_iconrow(bContext *C, te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED); /* object hierarchy always, further constrained on level */ - if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) { + if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) || + ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL)) { /* active blocks get white circle */ if (tselem->type == TSE_SOME_ID) { if (te->idcode == ID_OB) { @@ -3728,7 +3732,7 @@ static void outliner_update_viewable_area(ARegion *region, } /* ****************************************************** */ -/* Main Entrypoint - Draw contents of Outliner editor */ +/* Main Entry-point - Draw contents of Outliner editor */ void draw_outliner(const bContext *C) { diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 4a070590d55..5be6c69363e 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -966,7 +966,7 @@ void OUTLINER_OT_lib_relocate(wmOperatorType *ot) /* XXX This does not work with several items * (it is only called once in the end, due to the 'deferred' - * filebrowser invocation through event system...). */ + * file-browser invocation through event system...). */ void lib_relocate_fn(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index fea5ddae16b..5336376b576 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -191,7 +191,7 @@ typedef enum { #define OL_RNA_COL_SPACEX (UI_UNIT_X * 2.5f) /* The outliner display modes that support the filter system. - * Note: keep it synced with space_outliner.py */ + * NOTE: keep it synced with `space_outliner.py`. */ #define SUPPORT_FILTER_OUTLINER(space_outliner_) \ (ELEM((space_outliner_)->outlinevis, SO_VIEW_LAYER, SO_OVERRIDES_LIBRARY)) diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index b14a3cdb91d..35015356f0b 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -42,6 +42,7 @@ #include "BKE_collection.h" #include "BKE_constraint.h" #include "BKE_context.h" +#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_layer.h" @@ -450,7 +451,7 @@ static void tree_element_defgroup_activate(bContext *C, TreeElement *te, TreeSto /* id in tselem is object */ Object *ob = (Object *)tselem->id; BLI_assert(te->index + 1 >= 0); - ob->actdef = te->index + 1; + BKE_object_defgroup_active_index_set(ob, te->index + 1); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); @@ -830,7 +831,7 @@ static eOLDrawState tree_element_defgroup_state_get(const ViewLayer *view_layer, { const Object *ob = (const Object *)tselem->id; if (ob == OBACT(view_layer)) { - if (ob->actdef == te->index + 1) { + if (BKE_object_defgroup_active_index_get(ob) == te->index + 1) { return OL_DRAWSEL_NORMAL; } } @@ -1654,7 +1655,7 @@ static int outliner_item_do_activate_from_cursor(bContext *C, return OPERATOR_FINISHED; } -/* event can enterkey, then it opens/closes */ +/* Event can enter-key, then it opens/closes. */ static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { const bool extend = RNA_boolean_get(op->ptr, "extend"); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index d59d04b6ac2..8a3ba9a24c2 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -168,7 +168,7 @@ static void get_element_operation_type( case ID_WM: case ID_SCR: /* Those are ignored here. */ - /* Note: while Screens should be manageable here, deleting a screen used by a workspace + /* NOTE: while Screens should be manageable here, deleting a screen used by a workspace * will cause crashes when trying to use that workspace, so for now let's play minimal, * safe change. */ break; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index ae455d957cf..c5ec656080a 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1,4 +1,4 @@ -/* +/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -62,6 +62,7 @@ #include "BLT_translation.h" #include "BKE_armature.h" +#include "BKE_deform.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -552,17 +553,20 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } /* vertex groups */ - if (!BLI_listbase_is_empty(&ob->defbase)) { - TreeElement *tenla = outliner_add_element( - space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); - tenla->name = IFACE_("Vertex Groups"); + if (ELEM(ob->type, OB_MESH, OB_GPENCIL, OB_LATTICE)) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + if (!BLI_listbase_is_empty(defbase)) { + TreeElement *tenla = outliner_add_element( + space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); + tenla->name = IFACE_("Vertex Groups"); - int index; - LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, &ob->defbase, index) { - TreeElement *ten = outliner_add_element( - space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index); - ten->name = defgroup->name; - ten->directdata = defgroup; + int index; + LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, defbase, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index); + ten->name = defgroup->name; + ten->directdata = defgroup; + } } } @@ -588,7 +592,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, switch (GS(id->name)) { case ID_LI: case ID_SCE: - BLI_assert(!"ID type expected to be expanded through new tree-element design"); + BLI_assert_msg(0, "ID type expected to be expanded through new tree-element design"); break; case ID_OB: { outliner_add_object_contents(space_outliner, te, tselem, (Object *)id); @@ -901,12 +905,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } else if (type == TSE_SOME_ID) { if (!te->type) { - BLI_assert(!"Expected this ID type to be ported to new Outliner tree-element design"); + BLI_assert_msg(0, "Expected this ID type to be ported to new Outliner tree-element design"); } } else if (ELEM(type, TSE_LIBRARY_OVERRIDE_BASE, TSE_LIBRARY_OVERRIDE)) { if (!te->type) { - BLI_assert(!"Expected override types to be ported to new Outliner tree-element design"); + BLI_assert_msg(0, + "Expected override types to be ported to new Outliner tree-element design"); } } else { @@ -1320,7 +1325,7 @@ static void outliner_sort(ListBase *lb) } TreeStoreElem *tselem = TREESTORE(te); - /* sorting rules; only object lists, ID lists, or deformgroups */ + /* Sorting rules; only object lists, ID lists, or deform-groups. */ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) { int totelem = BLI_listbase_count(lb); diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index a2032fa1dc0..205f0117e6a 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -179,7 +179,7 @@ static void outliner_main_region_listener(const wmRegionListenerParams *params) } break; case NC_GROUP: - /* all actions now, todo: check outliner view mode? */ + /* All actions now, TODO: check outliner view mode? */ ED_region_tag_redraw(region); break; case NC_LAMP: diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index f089a149805..96af8258010 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -86,7 +86,7 @@ class TreeDisplayViewLayer final : public AbstractTreeDisplay { ListBase buildTree(const TreeSourceData &source_data) override; private: - void add_view_layer(ListBase &, TreeElement &); + void add_view_layer(Scene &, ListBase &, TreeElement *); void add_layer_collections_recursive(ListBase &, ListBase &, TreeElement &); void add_layer_collection_objects(ListBase &, LayerCollection &, TreeElement &); void add_layer_collection_objects_children(TreeElement &); diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc index 3059f8bfe0c..a17bf174a74 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc @@ -150,27 +150,25 @@ TreeElement *TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar, } /* Create data-block list parent element on demand. */ - if (id != nullptr) { - TreeElement *ten; + TreeElement *ten; - if (filter_id_type) { - ten = tenlib; - } - else { - ten = outliner_add_element( - &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0); - ten->directdata = lbarray[a]; - ten->name = outliner_idcode_to_plural(GS(id->name)); - } + if (filter_id_type) { + ten = tenlib; + } + else { + ten = outliner_add_element( + &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0); + ten->directdata = lbarray[a]; + ten->name = outliner_idcode_to_plural(GS(id->name)); + } - for (ID *id : List<ID>(lbarray[a])) { - if (override_library_id_filter_poll(lib, id)) { - TreeElement *override_tree_element = outliner_add_element( - &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0); + for (ID *id : List<ID>(lbarray[a])) { + if (override_library_id_filter_poll(lib, id)) { + TreeElement *override_tree_element = outliner_add_element( + &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0); - if (BLI_listbase_is_empty(&override_tree_element->subtree)) { - outliner_free_tree_element(override_tree_element, &ten->subtree); - } + if (BLI_listbase_is_empty(&override_tree_element->subtree)) { + outliner_free_tree_element(override_tree_element, &ten->subtree); } } } diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc index 402526bbe8d..c3d0aecd3cb 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc @@ -70,74 +70,69 @@ TreeDisplayViewLayer::TreeDisplayViewLayer(SpaceOutliner &space_outliner) ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data) { ListBase tree = {nullptr}; - Scene *scene = source_data.scene; show_objects_ = !(space_outliner_.filter & SO_FILTER_NO_OBJECT); - const bool show_children = (space_outliner_.filter & SO_FILTER_NO_CHILDREN) == 0; - for (auto *view_layer : ListBaseWrapper<ViewLayer>(scene->view_layers)) { + view_layer_ = view_layer; + if (space_outliner_.filter & SO_FILTER_NO_VIEW_LAYERS) { if (view_layer != source_data.view_layer) { continue; } - } - TreeElement &te_view_layer = *outliner_add_element( - &space_outliner_, &tree, scene, nullptr, TSE_R_LAYER, 0); - TREESTORE(&te_view_layer)->flag &= ~TSE_CLOSED; - te_view_layer.name = view_layer->name; - te_view_layer.directdata = view_layer; - view_layer_ = view_layer; - - if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) { - /* Show objects in the view layer. */ - for (Base *base : List<Base>(view_layer_->object_bases)) { - TreeElement *te_object = outliner_add_element(&space_outliner_, - &te_view_layer.subtree, - base->object, - &te_view_layer, - TSE_SOME_ID, - 0); - te_object->directdata = base; - } - - if (show_children) { - outliner_make_object_parent_hierarchy(&tree); - } + add_view_layer(*scene, tree, (TreeElement *)nullptr); } else { - /* Show collections in the view layer. */ - TreeElement &ten = *outliner_add_element(&space_outliner_, - &te_view_layer.subtree, - source_data.scene, - &te_view_layer, - TSE_VIEW_COLLECTION_BASE, - 0); - ten.name = IFACE_("Scene Collection"); - TREESTORE(&ten)->flag &= ~TSE_CLOSED; - - add_view_layer(ten.subtree, ten); - if (show_children) { - add_layer_collection_objects_children(ten); - } + TreeElement &te_view_layer = *outliner_add_element( + &space_outliner_, &tree, scene, nullptr, TSE_R_LAYER, 0); + TREESTORE(&te_view_layer)->flag &= ~TSE_CLOSED; + te_view_layer.name = view_layer->name; + te_view_layer.directdata = view_layer; + + add_view_layer(*scene, te_view_layer.subtree, &te_view_layer); } } return tree; } -void TreeDisplayViewLayer::add_view_layer(ListBase &tree, TreeElement &parent) +void TreeDisplayViewLayer::add_view_layer(Scene &scene, ListBase &tree, TreeElement *parent) { - /* First layer collection is for master collection, don't show it. */ - LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first); - if (lc == nullptr) { - return; + const bool show_children = (space_outliner_.filter & SO_FILTER_NO_CHILDREN) == 0; + + if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) { + /* Show objects in the view layer. */ + for (Base *base : List<Base>(view_layer_->object_bases)) { + TreeElement *te_object = outliner_add_element( + &space_outliner_, &tree, base->object, parent, TSE_SOME_ID, 0); + te_object->directdata = base; + } + + if (show_children) { + outliner_make_object_parent_hierarchy(&tree); + } } + else { + /* Show collections in the view layer. */ + TreeElement &ten = *outliner_add_element( + &space_outliner_, &tree, &scene, parent, TSE_VIEW_COLLECTION_BASE, 0); + ten.name = IFACE_("Scene Collection"); + TREESTORE(&ten)->flag &= ~TSE_CLOSED; + + /* First layer collection is for master collection, don't show it. */ + LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first); + if (lc == nullptr) { + return; + } - add_layer_collections_recursive(tree, lc->layer_collections, parent); - if (show_objects_) { - add_layer_collection_objects(tree, *lc, parent); + add_layer_collections_recursive(ten.subtree, lc->layer_collections, ten); + if (show_objects_) { + add_layer_collection_objects(ten.subtree, *lc, ten); + } + if (show_children) { + add_layer_collection_objects_children(ten); + } } } diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.cc b/source/blender/editors/space_outliner/tree/tree_element_id.cc index ce99b954204..7ff5a3285f1 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_id.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_id.cc @@ -85,7 +85,7 @@ TreeElementID *TreeElementID::createFromID(TreeElement &legacy_te, ID &id) return new TreeElementID(legacy_te, id); /* Deprecated */ case ID_IP: - BLI_assert(!"Outliner trying to build tree-element for deprecated ID type"); + BLI_assert_msg(0, "Outliner trying to build tree-element for deprecated ID type"); return nullptr; } diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 897af9ae931..11bee36e914 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -156,7 +156,7 @@ static void script_header_region_draw(const bContext *C, ARegion *region) static void script_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { -/* XXX - Todo, need the ScriptSpace accessible to get the python script to run. */ +/* XXX: Todo, need the ScriptSpace accessible to get the python script to run. */ #if 0 BPY_run_script_space_listener() #endif diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index ac31e0e7c37..1239286d4da 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -260,7 +260,7 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm RNA_PROP_BEGIN (op->ptr, itemptr, prop) { char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); BLI_strncpy(load_data->name, filename, sizeof(load_data->name)); - BLI_snprintf(load_data->path, sizeof(load_data->path), "%s%s", directory, filename); + BLI_join_dirfile(load_data->path, sizeof(load_data->path), directory, filename); MEM_freeN(filename); break; } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 8341dbe6014..cdbe5bc63ce 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -101,7 +101,7 @@ #define SEQ_SCROLLER_TEXT_OFFSET 8 #define MUTE_ALPHA 120 -/* Note, Don't use SEQ_ALL_BEGIN/SEQ_ALL_END while drawing! +/* NOTE: Don't use SEQ_ALL_BEGIN/SEQ_ALL_END while drawing! * it messes up transform. */ #undef SEQ_ALL_BEGIN #undef SEQ_ALL_END @@ -453,13 +453,13 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, GPU_blend(GPU_BLEND_NONE); } -/* Get handle width in pixels. */ +/* Get handle width in 2d-View space. */ float sequence_handle_size_get_clamped(Sequence *seq, const float pixelx) { const float maxhandle = (pixelx * SEQ_HANDLE_SIZE) * U.pixelsize; - /* Ensure that handle is not wider, than half of strip. */ - return min_ff(maxhandle, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx); + /* Ensure that handle is not wider, than quarter of strip. */ + return min_ff(maxhandle, ((float)(seq->enddisp - seq->startdisp) / 4.0f)); } /* Draw a handle, on left or right side of strip. */ @@ -1556,7 +1556,7 @@ static void *sequencer_OCIO_transform_ibuf(const bContext *C, *r_format = GPU_RGB16F; } else { - BLI_assert(!"Incompatible number of channels for float buffer in sequencer"); + BLI_assert_msg(0, "Incompatible number of channels for float buffer in sequencer"); *r_format = GPU_RGBA16F; display_buffer = NULL; } @@ -2479,10 +2479,12 @@ void draw_timeline_seq_display(const bContext *C, ARegion *region) const SpaceSeq *sseq = CTX_wm_space_seq(C); View2D *v2d = ®ion->v2d; - if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { + if (scene->ed != NULL) { UI_view2d_view_ortho(v2d); draw_cache_view(C); - draw_overlap_frame_indicator(scene, v2d); + if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { + draw_overlap_frame_indicator(scene, v2d); + } UI_view2d_view_restore(C); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 48b8a1b87a3..4b26469aad3 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2258,7 +2258,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) break; } - /* XXX - Should be a generic function. */ + /* XXX: Should be a generic function. */ for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) { if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { @@ -2414,6 +2414,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) (LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_FREE_NO_MAIN)); seqbase_clipboard_frame = scene->r.cfra; + SEQ_clipboard_active_seq_name_store(scene); /* Remove anything that references the current scene. */ LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) { @@ -2504,6 +2505,10 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) BLI_movelisttolist(ed->seqbasep, &nseqbase); for (iseq = iseq_first; iseq; iseq = iseq->next) { + if (SEQ_clipboard_pasted_seq_was_active(iseq)) { + SEQ_select_active_set(scene, iseq); + } + /* Make sure, that pasted strips have unique names. */ SEQ_ensure_unique_name(iseq, scene); /* Translate after name has been changed, otherwise this will affect animdata of original @@ -2804,9 +2809,9 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "directory", directory); if (is_relative_path) { - /* TODO, shouldn't this already be relative from the filesel? + /* TODO(campbell): shouldn't this already be relative from the filesel? * (as the 'filepath' is) for now just make relative here, - * but look into changing after 2.60 - campbell */ + * but look into changing after 2.60. */ BLI_path_rel(directory, BKE_main_blendfile_path(bmain)); } BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir)); @@ -2929,6 +2934,23 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot) /** \name Export Subtitles Operator * \{ */ +/** Comparison function suitable to be used with BLI_listbase_sort(). */ +static int seq_cmp_time_startdisp_channel(const void *a, const void *b) +{ + Sequence *seq_a = (Sequence *)a; + Sequence *seq_b = (Sequence *)b; + + int seq_a_start = SEQ_transform_get_left_handle_frame(seq_a); + int seq_b_start = SEQ_transform_get_left_handle_frame(seq_b); + + /** If strips have the same start frame favor the one with a higher channel. **/ + if (seq_a_start == seq_b_start) { + return seq_a->machine > seq_b->machine; + } + + return (seq_a_start > seq_b_start); +} + static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -2998,7 +3020,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BLI_listbase_sort(&text_seq, SEQ_time_cmp_time_startdisp); + BLI_listbase_sort(&text_seq, seq_cmp_time_startdisp_channel); /* Open and write file. */ file = BLI_fopen(filepath, "w"); @@ -3008,7 +3030,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) char timecode_str_start[32]; char timecode_str_end[32]; - /* Write timecode relative to start frame of scene. Don't allow negative timecodes. */ + /* Write time-code relative to start frame of scene. Don't allow negative time-codes. */ BLI_timecode_string_from_time(timecode_str_start, sizeof(timecode_str_start), -2, diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 16768e09cb8..5d857f62b47 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -32,8 +32,8 @@ #include "sequencer_intern.h" -/* XXX, why is this function better than BLI_math version? - * only difference is it does some normalize after, need to double check on this - campbell */ +/* XXX(campbell): why is this function better than BLI_math version? + * only difference is it does some normalize after, need to double check on this. */ static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3]) { yuv[0] = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2]; @@ -624,8 +624,6 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i { float rgb[3], yuv[3]; char *p; - int x = 0; - int y = 0; rgb[0] = (float)r / 255.0f; rgb[1] = (float)g / 255.0f; @@ -638,8 +636,8 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i r = 255; } - for (y = -size; y <= size; y++) { - for (x = -size; x <= size; x++) { + for (int y = -size; y <= size; y++) { + for (int x = -size; x <= size; x++) { char *q = p + 4 * (y * w + x); q[0] = r; q[1] = g; diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 7e515271b13..5980bfe37cd 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -534,7 +534,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) seq = find_nearest_seq(scene, v2d, &hand, mval); - /* XXX - not nice, Ctrl+RMB needs to do side_of_frame only when not over a strip */ + /* XXX: not nice, Ctrl+RMB needs to do side_of_frame only when not over a strip. */ if (seq && linked_time) { side_of_frame = false; } diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt index 1ea6593588a..e903feeec1b 100644 --- a/source/blender/editors/space_spreadsheet/CMakeLists.txt +++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../../gpu ../../makesdna ../../makesrna + ../../nodes ../../windowmanager ../../../../intern/glew-mx ../../../../intern/guardedalloc @@ -34,8 +35,8 @@ set(INC set(SRC space_spreadsheet.cc - spreadsheet_context.cc spreadsheet_column.cc + spreadsheet_context.cc spreadsheet_data_source.cc spreadsheet_data_source_geometry.cc spreadsheet_dataset_draw.cc @@ -46,10 +47,10 @@ set(SRC spreadsheet_row_filter.cc spreadsheet_row_filter_ui.cc - spreadsheet_context.hh spreadsheet_cell_value.hh spreadsheet_column.hh spreadsheet_column_values.hh + spreadsheet_context.hh spreadsheet_data_source.hh spreadsheet_data_source_geometry.hh spreadsheet_dataset_draw.hh diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 07517f9e60f..fcc92345bea 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -222,24 +222,11 @@ ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet) static void update_pinned_context_path_if_outdated(const bContext *C) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - - /* Currently, this only checks if the object has been deleted. In the future we can have a more - * sophisticated check for the entire context (including modifier and nodes). */ - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { - if (context->type == SPREADSHEET_CONTEXT_OBJECT) { - SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context; - if (object_context->object == nullptr) { - ED_spreadsheet_context_path_clear(sspreadsheet); - break; - } - } - } - if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { - Object *active_object = CTX_data_active_object(C); - if (active_object != nullptr) { - SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT); - ((SpreadsheetContextObject *)new_context)->object = active_object; - BLI_addtail(&sspreadsheet->context_path, new_context); + Main *bmain = CTX_data_main(C); + if (!ED_spreadsheet_context_path_exists(bmain, sspreadsheet)) { + ED_spreadsheet_context_path_guess(C, sspreadsheet); + if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) { + ED_area_tag_redraw(CTX_wm_area(C)); } } @@ -252,25 +239,12 @@ static void update_pinned_context_path_if_outdated(const bContext *C) static void update_context_path_from_context(const bContext *C) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); - Object *active_object = CTX_data_active_object(C); - if (active_object == nullptr) { - ED_spreadsheet_context_path_clear(sspreadsheet); - return; - } - if (!BLI_listbase_is_empty(&sspreadsheet->context_path)) { - SpreadsheetContext *root_context = (SpreadsheetContext *)sspreadsheet->context_path.first; - if (root_context->type == SPREADSHEET_CONTEXT_OBJECT) { - SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)root_context; - if (object_context->object != active_object) { - ED_spreadsheet_context_path_clear(sspreadsheet); - } + if (!ED_spreadsheet_context_path_is_active(C, sspreadsheet)) { + ED_spreadsheet_context_path_guess(C, sspreadsheet); + if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) { + ED_area_tag_redraw(CTX_wm_area(C)); } } - if (BLI_listbase_is_empty(&sspreadsheet->context_path)) { - SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT); - ((SpreadsheetContextObject *)new_context)->object = active_object; - BLI_addtail(&sspreadsheet->context_path, new_context); - } } void spreadsheet_update_context_path(const bContext *C) diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh index c9b73aabf96..680da9b6794 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh @@ -22,8 +22,8 @@ #include "BLI_float2.hh" #include "BLI_float3.hh" -struct Object; struct Collection; +struct Object; namespace blender::ed::spreadsheet { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc index af6ab5d1b92..1ac2075e281 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc @@ -24,16 +24,28 @@ #include "BLI_utildefines.h" #include "BLI_vector.hh" +#include "ED_screen.h" #include "ED_spreadsheet.h" #include "DEG_depsgraph.h" +#include "BKE_context.h" #include "BKE_main.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_object.h" +#include "BKE_workspace.h" + +#include "DNA_modifier_types.h" +#include "DNA_windowmanager_types.h" #include "spreadsheet_context.hh" +using blender::IndexRange; +using blender::Span; +using blender::StringRef; +using blender::Vector; + namespace blender::ed::spreadsheet { static SpreadsheetContextObject *spreadsheet_context_object_new() @@ -206,28 +218,30 @@ void spreadsheet_context_free(SpreadsheetContext *context) /** * Tag any data relevant to the spreadsheet's context for recalculation in order to collect * information to display in the editor, which may be cached during evaluation. + * \return True when any data has been tagged for update. */ -static void spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet) +static bool spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet) { using namespace blender; Vector<const SpreadsheetContext *> context_path = sspreadsheet->context_path; if (context_path.is_empty()) { - return; + return false; } if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { - return; + return false; } SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0]; Object *object = object_context->object; if (object == nullptr) { - return; + return false; } if (context_path.size() == 1) { /* No need to reevaluate, when the final or original object is viewed. */ - return; + return false; } DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); + return true; } } // namespace blender::ed::spreadsheet @@ -250,9 +264,9 @@ void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet) BLI_listbase_clear(&sspreadsheet->context_path); } -void ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet) +bool ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet) { - blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet); + return blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet); } uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet) @@ -265,15 +279,32 @@ uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet) return BLI_hash_mm2a_end(&mm2); } -void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet, - struct SpaceNode *snode, - struct bNode *node) +void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet, + struct SpaceNode *snode, + struct bNode *node) { using namespace blender::ed::spreadsheet; - ED_spreadsheet_context_path_clear(sspreadsheet); Object *object = (Object *)snode->id; + /* Try to find the modifier the node tree belongs to. */ ModifierData *modifier = BKE_object_active_modifier(object); + if (modifier && modifier->type != eModifierType_Nodes) { + modifier = nullptr; + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Nodes) { + NodesModifierData *nmd = (NodesModifierData *)md; + if (nmd->node_group == snode->nodetree) { + modifier = md; + break; + } + } + } + } + if (modifier == nullptr) { + return; + } + + ED_spreadsheet_context_path_clear(sspreadsheet); { SpreadsheetContextObject *context = spreadsheet_context_object_new(); @@ -302,5 +333,251 @@ void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsh BLI_addtail(&sspreadsheet->context_path, context); } - sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED; + sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE; +} + +void ED_spreadsheet_context_paths_set_geometry_node(Main *bmain, SpaceNode *snode, bNode *node) +{ + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + if (wm == nullptr) { + return; + } + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = (SpaceLink *)area->spacedata.first; + if (sl->spacetype == SPACE_SPREADSHEET) { + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; + if ((sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) == 0) { + const uint64_t context_hash_before = ED_spreadsheet_context_path_hash(sspreadsheet); + ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node); + const uint64_t context_hash_after = ED_spreadsheet_context_path_hash(sspreadsheet); + if (context_hash_before != context_hash_after) { + ED_spreadsheet_context_path_update_tag(sspreadsheet); + } + ED_area_tag_redraw(area); + } + } + } + } +} + +void ED_spreadsheet_context_path_set_evaluated_object(SpaceSpreadsheet *sspreadsheet, + Object *object) +{ + using namespace blender::ed::spreadsheet; + ED_spreadsheet_context_path_clear(sspreadsheet); + + SpreadsheetContextObject *context = spreadsheet_context_object_new(); + context->object = object; + BLI_addtail(&sspreadsheet->context_path, context); +} + +void ED_spreadsheet_context_path_guess(const bContext *C, SpaceSpreadsheet *sspreadsheet) +{ + ED_spreadsheet_context_path_clear(sspreadsheet); + + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + if (wm == nullptr) { + return; + } + + if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = (SpaceLink *)area->spacedata.first; + if (sl->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + if (snode->edittree != nullptr) { + if (snode->edittree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { + if (node->type == GEO_NODE_VIEWER) { + if (node->flag & NODE_DO_OUTPUT) { + ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node); + return; + } + } + } + } + } + } + } + } + } + + Object *active_object = CTX_data_active_object(C); + if (active_object != nullptr) { + ED_spreadsheet_context_path_set_evaluated_object(sspreadsheet, active_object); + return; + } +} + +bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet *sspreadsheet) +{ + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + if (wm == nullptr) { + return false; + } + Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path; + if (context_path.is_empty()) { + return false; + } + if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { + return false; + } + Object *object = ((SpreadsheetContextObject *)context_path[0])->object; + if (object == nullptr) { + return false; + } + if (context_path.size() == 1) { + if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + return false; + } + Object *active_object = CTX_data_active_object(C); + return object == active_object; + } + if (sspreadsheet->object_eval_state != SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { + return false; + } + if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) { + return false; + } + const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name; + const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name); + if (modifier == nullptr) { + return false; + } + if (!(modifier->flag & eModifierFlag_Active)) { + return false; + } + if (modifier->type != eModifierType_Nodes) { + return false; + } + bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group; + if (root_node_tree == nullptr) { + return false; + } + const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2); + if (node_context_path.is_empty()) { + return false; + } + + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = (SpaceLink *)area->spacedata.first; + if (sl->spacetype != SPACE_NODE) { + continue; + } + SpaceNode *snode = (SpaceNode *)sl; + if (snode->nodetree != root_node_tree) { + continue; + } + if (snode->id != &object->id) { + continue; + } + Vector<bNodeTreePath *> tree_path = snode->treepath; + if (node_context_path.size() != tree_path.size()) { + continue; + } + int valid_count = 0; + for (const int i : IndexRange(tree_path.size() - 1)) { + if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) { + break; + } + SpreadsheetContextNode *node_context = (SpreadsheetContextNode *)node_context_path[i]; + if (!STREQ(node_context->node_name, tree_path[i]->node_name)) { + break; + } + valid_count++; + } + if (valid_count != tree_path.size() - 1) { + continue; + } + SpreadsheetContext *last_context = node_context_path.last(); + if (last_context->type != SPREADSHEET_CONTEXT_NODE) { + return false; + } + const char *node_name = ((SpreadsheetContextNode *)last_context)->node_name; + bNode *node = nodeFindNodebyName(snode->edittree, node_name); + if (node == nullptr) { + return false; + } + if (node->type != GEO_NODE_VIEWER) { + return false; + } + if (!(node->flag & NODE_DO_OUTPUT)) { + return false; + } + return true; + } + } + return false; +} + +bool ED_spreadsheet_context_path_exists(Main *UNUSED(bmain), SpaceSpreadsheet *sspreadsheet) +{ + Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path; + if (context_path.is_empty()) { + return false; + } + if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { + return false; + } + Object *object = ((SpreadsheetContextObject *)context_path[0])->object; + if (object == nullptr) { + return false; + } + if (context_path.size() == 1) { + return true; + } + if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) { + return false; + } + const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name; + const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name); + if (modifier == nullptr) { + return false; + } + if (modifier->type != eModifierType_Nodes) { + return false; + } + bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group; + if (root_node_tree == nullptr) { + return false; + } + const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2); + if (node_context_path.is_empty()) { + return false; + } + bNodeTree *node_tree = root_node_tree; + for (const int i : node_context_path.index_range()) { + if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) { + return false; + } + const char *node_name = ((SpreadsheetContextNode *)node_context_path[i])->node_name; + bNode *node = nodeFindNodebyName(node_tree, node_name); + if (node == nullptr) { + return false; + } + if (node->type == GEO_NODE_VIEWER) { + if (i == node_context_path.index_range().last()) { + return true; + } + return false; + } + if (node->id != nullptr) { + if (GS(node->id->name) != ID_NT) { + return false; + } + node_tree = (bNodeTree *)node->id; + } + else { + return false; + } + } + return false; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index 6d244a1bda6..e38c70afd0f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -31,11 +31,15 @@ #include "ED_spreadsheet.h" +#include "NOD_geometry_nodes_eval_log.hh" + #include "bmesh.h" #include "spreadsheet_data_source_geometry.hh" #include "spreadsheet_intern.hh" +namespace geo_log = blender::nodes::geometry_nodes_eval_log; + namespace blender::ed::spreadsheet { void GeometryDataSource::foreach_default_column_ids( @@ -410,7 +414,6 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread Mesh *mesh = (Mesh *)object_orig->data; mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); } - mesh_component.copy_vertex_group_names_from_object(*object_orig); } else if (object_orig->type == OB_POINTCLOUD) { PointCloud *pointcloud = (PointCloud *)object_orig->data; @@ -419,7 +422,7 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly); } } - else if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED) { + else { if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) { Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false); if (mesh == nullptr) { @@ -428,7 +431,6 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread BKE_mesh_wrapper_ensure_mdata(mesh); MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); - mesh_component.copy_vertex_group_names_from_object(*object_eval); } else { if (BLI_listbase_count(&sspreadsheet->context_path) == 1) { @@ -438,13 +440,18 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread } } else { - if (object_eval->runtime.geometry_set_previews != nullptr) { - GHash *ghash = (GHash *)object_eval->runtime.geometry_set_previews; - const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet); - GeometrySet *geometry_set_preview = (GeometrySet *)BLI_ghash_lookup_default( - ghash, POINTER_FROM_UINT(key), nullptr); - if (geometry_set_preview != nullptr) { - geometry_set = *geometry_set_preview; + const geo_log::NodeLog *node_log = + geo_log::ModifierLog::find_node_by_spreadsheet_editor_context(*sspreadsheet); + if (node_log != nullptr) { + for (const geo_log::SocketLog &input_log : node_log->input_logs()) { + if (const geo_log::GeometryValueLog *geo_value_log = + dynamic_cast<const geo_log::GeometryValueLog *>(input_log.value())) { + const GeometrySet *full_geometry = geo_value_log->full_geometry(); + if (full_geometry != nullptr) { + geometry_set = *full_geometry; + break; + } + } } } } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh index d9e6d882c2a..19906d73e7f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh @@ -23,9 +23,9 @@ #include "spreadsheet_dataset_layout.hh" struct ARegion; -struct uiBlock; struct View2D; struct bContext; +struct uiBlock; namespace blender::ed::spreadsheet { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc index 5b5c5ed0b04..abbad8c7088 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc @@ -38,9 +38,9 @@ namespace blender::ed::spreadsheet { * Definition for the component->attribute-domain hierarchy. * Constructed at compile time. * - * \warning: Order of attribute-domains matters! It __must__ match the #AttributeDomain definition - * and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use array - * designators for this (which C++ doesn't support). + * \warning Order of attribute-domains matters! It __must__ match the #AttributeDomain + * definition and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use + * array designators for this (which C++ doesn't support). */ constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = { { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh index 647587ec8b0..9accd1d3d09 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh @@ -18,9 +18,9 @@ #include "BLI_vector.hh" -struct uiBlock; -struct bContext; struct ARegion; +struct bContext; +struct uiBlock; namespace blender::ed::spreadsheet { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc index dbd2ef157af..219d03c1dcd 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc @@ -267,20 +267,20 @@ static void spreadsheet_row_filters_layout(const bContext *C, Panel *panel) } else { /* Assuming there's only one group of instanced panels, update the custom data pointers. */ - Panel *panel = (Panel *)region->panels.first; + Panel *panel_iter = (Panel *)region->panels.first; LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, row_filters) { /* Move to the next instanced panel corresponding to the next filter. */ - while ((panel->type == nullptr) || !(panel->type->flag & PANEL_TYPE_INSTANCED)) { - panel = panel->next; - BLI_assert(panel != nullptr); /* There shouldn't be fewer panels than filters. */ + while ((panel_iter->type == nullptr) || !(panel_iter->type->flag & PANEL_TYPE_INSTANCED)) { + panel_iter = panel_iter->next; + BLI_assert(panel_iter != nullptr); /* There shouldn't be fewer panels than filters. */ } PointerRNA *filter_ptr = (PointerRNA *)MEM_mallocN(sizeof(PointerRNA), "panel customdata"); RNA_pointer_create(&screen->id, &RNA_SpreadsheetRowFilter, row_filter, filter_ptr); - UI_panel_custom_data_set(panel, filter_ptr); + UI_panel_custom_data_set(panel_iter, filter_ptr); - panel = panel->next; + panel_iter = panel_iter->next; } } } diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c index 16eb66624ce..0cd2d9baa0b 100644 --- a/source/blender/editors/space_text/text_format_lua.c +++ b/source/blender/editors/space_text/text_format_lua.c @@ -165,9 +165,9 @@ static char txtfmt_lua_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_lua_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_lua_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_lua_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_lua_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c index 1a024779a83..97d9ec546ca 100644 --- a/source/blender/editors/space_text/text_format_osl.c +++ b/source/blender/editors/space_text/text_format_osl.c @@ -189,11 +189,11 @@ static char txtfmt_osl_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_osl_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_osl_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else if ((txtfmt_osl_find_reserved(str)) != -1) { fmt = FMT_TYPE_RESERVED; - } else if ((txtfmt_osl_find_preprocessor(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_osl_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_osl_find_builtinfunc(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else if (txtfmt_osl_find_reserved(str) != -1) { fmt = FMT_TYPE_RESERVED; + } else if (txtfmt_osl_find_preprocessor(str) != -1) { fmt = FMT_TYPE_DIRECTIVE; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c index 1200dda7533..ea3d0ec1478 100644 --- a/source/blender/editors/space_text/text_format_pov.c +++ b/source/blender/editors/space_text/text_format_pov.c @@ -762,11 +762,11 @@ static char txtfmt_pov_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_pov_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_pov_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) { fmt = FMT_TYPE_RESERVED; - } else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_pov_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_pov_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else if (txtfmt_pov_find_reserved_keywords(str) != -1) { fmt = FMT_TYPE_RESERVED; + } else if (txtfmt_pov_find_reserved_builtins(str) != -1) { fmt = FMT_TYPE_DIRECTIVE; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c index 1c6a93d2d7a..259ad02a6b7 100644 --- a/source/blender/editors/space_text/text_format_pov_ini.c +++ b/source/blender/editors/space_text/text_format_pov_ini.c @@ -347,10 +347,10 @@ static int txtfmt_ini_find_bool(const char *string) static char txtfmt_pov_ini_format_identifier(const char *str) { char fmt; - if ((txtfmt_ini_find_keyword(str)) != -1) { + if (txtfmt_ini_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD; } - else if ((txtfmt_ini_find_reserved(str)) != -1) { + else if (txtfmt_ini_find_reserved(str) != -1) { fmt = FMT_TYPE_RESERVED; } else { diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c index 31177c53d6a..e2a01a8d85d 100644 --- a/source/blender/editors/space_text/text_format_py.c +++ b/source/blender/editors/space_text/text_format_py.c @@ -290,7 +290,7 @@ static int txtfmt_py_literal_numeral(const char *string, char prev_fmt) return 1 + txtfmt_py_find_numeral_inner(string + 1); } /* Previous was a number; if immediately followed by '.' it's a floating point decimal number. - * Note: keep the decimal point, it's needed to allow leading zeros. */ + * NOTE: keep the decimal point, it's needed to allow leading zeros. */ if (first == '.') { return txtfmt_py_find_numeral_inner(string); } @@ -315,10 +315,10 @@ static char txtfmt_py_format_identifier(const char *str) /* Keep aligned args for readability. */ /* clang-format off */ - if ((txtfmt_py_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL; - } else if ((txtfmt_py_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD; - } else if ((txtfmt_py_find_decorator(str)) != -1) { fmt = FMT_TYPE_RESERVED; - } else { fmt = FMT_TYPE_DEFAULT; + if (txtfmt_py_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL; + } else if (txtfmt_py_find_builtinfunc(str) != -1) { fmt = FMT_TYPE_KEYWORD; + } else if (txtfmt_py_find_decorator(str) != -1) { fmt = FMT_TYPE_RESERVED; + } else { fmt = FMT_TYPE_DEFAULT; } /* clang-format on */ diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 6ca89250cd7..b98dae0cd57 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -745,7 +745,7 @@ void TEXT_OT_save_as(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_DEFAULT); /* XXX TODO, relative_path. */ + FILE_SORT_DEFAULT); /* XXX TODO: relative_path. */ } /** \} */ @@ -3468,7 +3468,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int ret; - /* Note, the "text" property is always set from key-map, + /* NOTE: the "text" property is always set from key-map, * so we can't use #RNA_struct_property_is_set, check the length instead. */ if (!RNA_string_length(op->ptr, "text")) { /* if alt/ctrl/super are pressed pass through except for utf8 character event diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c index f55db8c3cc9..80af7d8c9f6 100644 --- a/source/blender/editors/space_text/text_undo.c +++ b/source/blender/editors/space_text/text_undo.c @@ -265,7 +265,7 @@ void ED_text_undosys_type(UndoType *ut) ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref; - ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE; + ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE | UNDOTYPE_FLAG_DECODE_ACTIVE_STEP; ut->step_size = sizeof(TextUndoStep); } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 660ae9da506..6b9da431510 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -117,10 +117,10 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, return; } - Mesh *me = ob->data; + const Mesh *me = ob->data; { Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); if (me_eval != NULL) { me = me_eval; } @@ -160,7 +160,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, const MPoly *mp; int i; if (me->runtime.looptris.array) { - MLoopTri *mlt = me->runtime.looptris.array; + const MLoopTri *mlt = me->runtime.looptris.array; for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { if (facemap_data[i] == facemap) { for (int j = 2; j < mp->totloop; j++) { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 6ce13f83cf3..54f10e259f9 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1096,7 +1096,7 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP ScrArea *area = params->area; ARegion *region = params->region; - /* Developer note: there are many properties that impact 3D view drawing, + /* Developer NOTE: there are many properties that impact 3D view drawing, * so instead of subscribing to individual properties, just subscribe to types * accepting some redundant redraws. * diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 60e1c780b9e..3428a738dde 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -39,6 +39,8 @@ #include "BLT_translation.h" +#include "BLI_array_utils.h" +#include "BLI_bitmap.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -112,10 +114,94 @@ typedef struct { float ob_dims[3]; /* Floats only (treated as an array). */ TransformMedian ve_median, median; + bool tag_for_update; } TransformProperties; #define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float)) +static TransformProperties *v3d_transform_props_ensure(View3D *v3d); + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh Partial Updates + * \{ */ + +static void *editmesh_partial_update_begin_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *params, + void *arg1) +{ + const int retval_test = B_TRANSFORM_PANEL_MEDIAN; + if (BLI_array_findindex( + params->unique_retval_ids, params->unique_retval_ids_len, &retval_test) == -1) { + return NULL; + } + + BMEditMesh *em = arg1; + + int verts_mask_count = 0; + BMIter iter; + BMVert *eve; + int i; + + BLI_bitmap *verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + continue; + } + BLI_BITMAP_ENABLE(verts_mask, i); + verts_mask_count += 1; + } + + BMPartialUpdate *bmpinfo = BM_mesh_partial_create_from_verts_group_single( + em->bm, + &(BMPartialUpdate_Params){ + .do_tessellate = true, + .do_normals = true, + }, + verts_mask, + verts_mask_count); + + MEM_freeN(verts_mask); + + return bmpinfo; +} + +static void editmesh_partial_update_end_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *UNUSED(params), + void *UNUSED(arg1), + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + BM_mesh_partial_destroy(bmpinfo); +} + +static void editmesh_partial_update_update_fn( + struct bContext *C, + const struct uiBlockInteraction_Params *UNUSED(params), + void *arg1, + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + + View3D *v3d = CTX_wm_view3d(C); + TransformProperties *tfp = v3d_transform_props_ensure(v3d); + if (tfp->tag_for_update == false) { + return; + } + tfp->tag_for_update = false; + + BMEditMesh *em = arg1; + + BKE_editmesh_looptri_and_normals_calc_with_partial(em, bmpinfo); +} + +/** \} */ + /* Helper function to compute a median changed value, * when the value should be clamped in [0.0, 1.0]. * Returns either 0.0, 1.0 (both can be applied directly), a positive scale factor @@ -840,6 +926,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } UI_block_align_end(block); + + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + if (em != NULL) { + UI_block_interaction_set(block, + &(uiBlockInteraction_CallbackData){ + .begin_fn = editmesh_partial_update_begin_fn, + .end_fn = editmesh_partial_update_end_fn, + .update_fn = editmesh_partial_update_update_fn, + .arg1 = em, + }); + } + } } else { /* apply */ memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); @@ -927,9 +1027,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (apply_vcos) { - /* TODO: use the #BKE_editmesh_looptri_and_normals_calc_with_partial - * This requires begin/end states for UI interaction (which currently aren't supported). */ - BKE_editmesh_looptri_and_normals_calc(em); + /* Tell the update callback to run. */ + tfp->tag_for_update = true; } /* Edges */ @@ -1152,7 +1251,7 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = view_layer->basact->object; ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); } @@ -1211,7 +1310,9 @@ static void view3d_panel_vgroup(const bContext *C, Panel *panel) vgroup_validmap = BKE_object_defgroup_subset_from_select_type( ob, subset_type, &vgroup_tot, &subset_count); - for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) { + const ListBase *defbase = BKE_object_defgroup_list(ob); + + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0; if (vgroup_validmap[i]) { MDeformWeight *dw = BKE_defvert_find_index(dv, i); @@ -1237,7 +1338,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *panel) but_ptr = UI_but_operator_ptr_get(but); RNA_int_set(but_ptr, "weight_group", i); UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT); - if (ob->actdef != i + 1) { + if (BKE_object_defgroup_active_index_get(ob) != i + 1) { UI_but_flag_enable(but, UI_BUT_INACTIVE); } xco += x; @@ -1464,7 +1565,7 @@ static void v3d_posearmature_buts(uiLayout *layout, Object *ob) /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.) * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers? - * Maybe needs RNA/ui options to display rotations as different types... */ + * Maybe needs RNA/UI options to display rotations as different types. */ v3d_transform_butsR(col, &pchanptr); } @@ -1568,7 +1669,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event case B_TRANSFORM_PANEL_MEDIAN: if (ob) { v3d_editvertex_buts(NULL, v3d, ob, 1.0); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); } break; case B_TRANSFORM_PANEL_DIMS: diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2e46deea0e8..c97ba7ba7e9 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -140,7 +140,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)region->winx; rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)region->winy; } - /* note: calls BKE_object_where_is_calc for camera... */ + /* NOTE: calls BKE_object_where_is_calc for camera... */ view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL); } /* update utility matrices */ @@ -167,7 +167,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, /* Calculate pixel-size factor once, this is used for lights and object-centers. */ { - /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' + /* NOTE: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' * because of float point precision problems at large values T23908. */ float v1[3], v2[3]; float len_px, len_sc; @@ -563,10 +563,10 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, /* apply offsets so the real 3D camera shows through */ - /* note: quite un-scientific but without this bit extra + /* NOTE: quite un-scientific but without this bit extra * 0.0001 on the lower left the 2D border sometimes * obscures the 3D camera border */ - /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable + /* NOTE: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable * but keep it here in case we need to remove the workaround */ x1i = (int)(x1 - 1.0001f); y1i = (int)(y1 - 1.0001f); @@ -780,7 +780,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, /* draw */ immUniformThemeColorShadeAlpha(TH_VIEW_OVERLAY, 100, 255); - /* TODO Was using: + /* TODO: Was using: * UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color); * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the * 2.0f round corner effect was nearly not visible anyway... */ @@ -1159,7 +1159,7 @@ static void view3d_draw_border(const bContext *C, ARegion *region) */ static void view3d_draw_grease_pencil(const bContext *UNUSED(C)) { - /* TODO viewport */ + /* TODO: viewport. */ } /** @@ -1404,7 +1404,7 @@ static void draw_selected_name( /* color depends on whether there is a keyframe */ if (id_frame_has_keyframe( - (ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { + (ID *)ob, /* BKE_scene_ctime_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); } else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) { @@ -2262,7 +2262,7 @@ void view3d_depths_rect_create(ARegion *region, rcti *rect, ViewDepths *r_d) } } -/* Note, with nouveau drivers the glReadPixels() is very slow. T24339. */ +/* NOTE: with nouveau drivers the glReadPixels() is very slow. T24339. */ static ViewDepths *view3d_depths_create(ARegion *region) { ViewDepths *d = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 50e9a9fb805..651ae8a3000 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -392,9 +392,9 @@ enum eViewOpsFlag { /** When enabled, use the depth under the cursor for navigation. */ VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1), /** - * When enabled run #ED_view3d_persp_ensure this may switch out of - * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled. - * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common + * When enabled run #ED_view3d_persp_ensure this may switch out of camera view + * when orbiting or switch from orthographic to perspective when auto-perspective is enabled. + * Some operations don't require this (view zoom/pan or NDOF where subtle rotation is common * so we don't want it to trigger auto-perspective). */ VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2), /** When set, ignore any options that depend on initial cursor location. */ @@ -813,7 +813,6 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2]) viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat); } else { - /* New turntable view code by John Aughey */ float quat_local_x[4], quat_global_z[4]; float m[3][3]; float m_inv[3][3]; @@ -894,8 +893,8 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2]) * rotation back into the view we calculate with */ copy_qt_qt(rv3d->viewquat, vod->curr.viewquat); - /* check for view snap, - * note: don't apply snap to vod->viewquat so the view won't jam up */ + /* Check for view snap, + * NOTE: don't apply snap to `vod->viewquat` so the view won't jam up. */ if (vod->axis_snap) { viewrotate_apply_snap(vod); } @@ -1201,7 +1200,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, if (U.ndof_flag & NDOF_TURNTABLE) { float rot[3]; - /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ + /* Turntable view code adapted for 3D mouse use. */ float angle, quat[4]; float xvec[3] = {1, 0, 0}; @@ -1506,7 +1505,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } } else { - /* Note: based on feedback from T67579, users want to have pan and orbit enabled at once. + /* NOTE: based on feedback from T67579, users want to have pan and orbit enabled at once. * It's arguable that orbit shouldn't pan (since we have a pan only operator), * so if there are users who like to separate orbit/pan operations - it can be a preference. */ const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) || @@ -2955,7 +2954,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) if (!changed) { ED_region_tag_redraw(region); - /* TODO - should this be cancel? + /* TODO: should this be cancel? * I think no, because we always move the cursor, with or without * object, but in this case there is no change in the scene, * only the cursor so I choice a ED_region_tag like @@ -3604,7 +3603,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) float depth_close = FLT_MAX; float cent[2], p[3]; - /* note; otherwise opengl won't work */ + /* NOTE: otherwise opengl won't work. */ view3d_operator_needs_opengl(C); /* get box select values using rna */ @@ -4788,7 +4787,7 @@ static bool background_image_add_poll(bContext *C) void VIEW3D_OT_background_image_add(wmOperatorType *ot) { /* identifiers */ - /* note: having key shortcut here is bad practice, + /* NOTE: having key shortcut here is bad practice, * but for now keep because this displays when dragging an image over the 3D viewport */ ot->name = "Add Background Image"; ot->description = "Add a new background image"; @@ -4957,7 +4956,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) * \{ */ /* cursor position in vec, result in vec, mval in region coords */ -/* note: cannot use event->mval here (called by object_add() */ +/* NOTE: cannot use `event->mval` here, called by #object_add(). */ void ED_view3d_cursor3d_position(bContext *C, const int mval[2], const bool use_depth, diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c index 16c83b45924..83d3286c8b3 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c @@ -199,7 +199,7 @@ static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); copy_m4_m4(gz->matrix_space, mat); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ WM_gizmo_target_property_def_func(gz, "offset", &(const struct wmGizmoPropertyFnParams){ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c index 20d766357e8..e1d439bef15 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c @@ -153,7 +153,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize); WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false); - /* Need to set property here for undo. TODO would prefer to do this in _init */ + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ PointerRNA camera_dof_ptr; RNA_pointer_create(&ca->id, &RNA_CameraDOFSettings, &ca->dof, &camera_dof_ptr); WM_gizmo_target_property_def_rna( @@ -163,7 +163,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true); } - /* TODO - make focal length/ortho ob_scale_inv widget optional */ + /* TODO: make focal length/ortho ob_scale_inv widget optional. */ const Scene *scene = CTX_data_scene(C); const float aspx = (float)scene->r.xsch * scene->r.xasp; const float aspy = (float)scene->r.ysch * scene->r.yasp; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c index 5bf105b6775..d92ebfd57a8 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_light.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c @@ -99,7 +99,7 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir); WM_gizmo_set_matrix_location(gz, ob->obmat[3]); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ PointerRNA lamp_ptr; const char *propname = "spot_size"; RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr); @@ -212,7 +212,7 @@ static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgr } RNA_enum_set(gz->ptr, "transform", flag); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* need to set property here for undo. TODO: would prefer to do this in _init. */ WM_gizmo_target_property_def_func(gz, "matrix", &(const struct wmGizmoPropertyFnParams){ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index 0d568363b00..49299d73337 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -580,7 +580,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) UI_GetThemeColor3ubv(TH_TEXT, color_text); UI_GetThemeColor3ubv(TH_WIRE, color_wire); - /* Avoid white on white text. (TODO Fix by using theme) */ + /* Avoid white on white text. (TODO: Fix by using theme). */ if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) { copy_v3_fl(color_back, 0.0f); } diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c index e2fa0fdc6a5..5752837c40f 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_fly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c @@ -122,7 +122,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf) {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"}, - {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"}, + {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction (toggle)"}, {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""}, {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""}, diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 33cb6aad400..09936b41a74 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -98,9 +98,10 @@ enum { WALK_MODAL_JUMP, WALK_MODAL_JUMP_STOP, WALK_MODAL_TELEPORT, - WALK_MODAL_TOGGLE, + WALK_MODAL_GRAVITY_TOGGLE, WALK_MODAL_ACCELERATE, WALK_MODAL_DECELERATE, + WALK_MODAL_AXIS_LOCK_Z, }; enum { @@ -129,6 +130,18 @@ typedef enum eWalkGravityState { WALK_GRAVITY_STATE_ON, } eWalkGravityState; +/* Relative view axis z axis locking. */ +typedef enum eWalkLockState { + /* Disabled. */ + WALK_AXISLOCK_STATE_OFF = 0, + + /* Moving. */ + WALK_AXISLOCK_STATE_ACTIVE = 2, + + /* Done moving, it cannot be activated again. */ + WALK_AXISLOCK_STATE_DONE = 3, +} eWalkLockState; + /* Called in transform_ops.c, on each regeneration of key-maps. */ void walk_modal_keymap(wmKeyConfig *keyconf) { @@ -164,7 +177,9 @@ void walk_modal_keymap(wmKeyConfig *keyconf) {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, - {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + {WALK_MODAL_GRAVITY_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + + {WALK_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction"}, {0, NULL, 0, NULL, NULL}, }; @@ -292,6 +307,10 @@ typedef struct WalkInfo { /** To use for fast/slow speeds. */ float speed_factor; + eWalkLockState zlock; + /** Nicer dynamics. */ + float zlock_momentum; + struct SnapObjectContext *snap_context; struct View3DCameraControl *v3d_camera_control; @@ -540,6 +559,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->jump_height = U.walk_navigation.jump_height; walk->speed = U.walk_navigation.walk_speed; walk->speed_factor = U.walk_navigation.walk_speed_factor; + walk->zlock = WALK_AXISLOCK_STATE_OFF; walk->gravity_state = WALK_GRAVITY_STATE_OFF; @@ -694,7 +714,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk->is_cursor_first = false; } else { - /* note, its possible the system isn't giving us the warp event + /* NOTE: its possible the system isn't giving us the warp event * ideally we shouldn't have to worry about this, see: T45361 */ wmWindow *win = CTX_wm_window(C); WM_cursor_warp(win, @@ -708,8 +728,6 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk->is_cursor_absolute = true; copy_v2_v2_int(walk->prev_mval, event->mval); copy_v2_v2_int(walk->center_mval, event->mval); - /* Without this we can't turn 180d with the default speed of 1.0. */ - walk->mouse_speed *= 4.0f; } #endif /* USE_TABLET_SUPPORT */ @@ -941,7 +959,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) #undef JUMP_TIME_MAX #undef JUMP_SPEED_MIN - case WALK_MODAL_TOGGLE: + case WALK_MODAL_GRAVITY_TOGGLE: if (walk->navigation_mode == WALK_MODE_GRAVITY) { walk_navigation_mode_set(walk, WALK_MODE_FREE); } @@ -949,6 +967,13 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk_navigation_mode_set(walk, WALK_MODE_GRAVITY); } break; + + case WALK_MODAL_AXIS_LOCK_Z: + if (walk->zlock != WALK_AXISLOCK_STATE_DONE) { + walk->zlock = WALK_AXISLOCK_STATE_ACTIVE; + walk->zlock_momentum = 0.0f; + } + break; } } } @@ -982,12 +1007,14 @@ static float getVelocityZeroTime(const float gravity, const float velocity) static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) { -#define WALK_ROTATE_RELATIVE_FAC 2.2f /* More is faster, relative to region size. */ -#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* More is faster, radians per-pixel. */ +#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */ +#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* Higher is faster, radians per-pixel. */ #define WALK_TOP_LIMIT DEG2RADF(85.0f) #define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f) #define WALK_MOVE_SPEED base_speed #define WALK_BOOST_FACTOR ((void)0, walk->speed_factor) +#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */ +#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */ RegionView3D *rv3d = walk->rv3d; ARegion *region = walk->region; @@ -1022,20 +1049,25 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) /* Should we redraw? */ if ((walk->active_directions) || moffset[0] || moffset[1] || - walk->teleport.state == WALK_TELEPORT_STATE_ON || - walk->gravity_state != WALK_GRAVITY_STATE_OFF || is_confirm) { + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE || + walk->gravity_state != WALK_GRAVITY_STATE_OFF || + walk->teleport.state == WALK_TELEPORT_STATE_ON || is_confirm) { float dvec_tmp[3]; /* time how fast it takes for us to redraw, * this is so simple scenes don't walk too fast */ double time_current; float time_redraw; + float time_redraw_clamped; #ifdef NDOF_WALK_DRAW_TOOMUCH walk->redraw = 1; #endif time_current = PIL_check_seconds_timer(); time_redraw = (float)(time_current - walk->time_lastdraw); + /* Clamp redraw time to avoid jitter in roll correction. */ + time_redraw_clamped = min_ff(0.05f, time_redraw); + walk->time_lastdraw = time_current; /* base speed in m/s */ @@ -1064,7 +1096,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { y /= region->winy; - y *= WALK_ROTATE_RELATIVE_FAC; + y *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1113,7 +1145,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { x /= region->winx; - x *= WALK_ROTATE_RELATIVE_FAC; + x *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1128,6 +1160,32 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) axis_angle_to_quat_single(tmp_quat, 'Z', x); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); } + + if (walk->zlock == WALK_AXISLOCK_STATE_ACTIVE) { + float upvec[3]; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + + /* Make sure we have some z rolling. */ + if (fabsf(upvec[2]) > 0.00001f) { + float roll = upvec[2] * 5.0f; + /* Rotate the view about this axis. */ + copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec. */ + axis_angle_to_quat(tmp_quat, + upvec, + roll * time_redraw_clamped * walk->zlock_momentum * + WALK_ZUP_CORRECT_FAC); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + walk->zlock_momentum += WALK_ZUP_CORRECT_ACCEL; + } + else { + /* Lock fixed, don't need to check it ever again. */ + walk->zlock = WALK_AXISLOCK_STATE_DONE; + } + } } /* WASD - 'move' translation code */ @@ -1318,7 +1376,8 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) add_v3_v3(rv3d->ofs, dvec_tmp); if (rv3d->persp == RV3D_CAMOB) { - walk->need_rotation_keyframe |= (moffset[0] || moffset[1]); + walk->need_rotation_keyframe |= (moffset[0] || moffset[1] || + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE); walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON); walkMoveCamera( C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm); @@ -1333,7 +1392,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) } return OPERATOR_FINISHED; -#undef WALK_ROTATE_RELATIVE_FAC +#undef WALK_ROTATE_TABLET_FAC #undef WALK_TOP_LIMIT #undef WALK_BOTTOM_LIMIT #undef WALK_MOVE_SPEED diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 1ea7993572d..aa3bf46d2e5 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -1610,7 +1610,7 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) ot->cancel = view3d_interactive_add_cancel; ot->poll = view3d_interactive_add_poll; - /* Note, let the operator we call handle undo and registering itself. */ + /* NOTE: let the operator we call handle undo and registering itself. */ /* flags */ ot->flag = 0; diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 8a900a4e898..d926ea84e0f 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -561,7 +561,7 @@ void ED_view3d_win_to_3d(const View3D *v3d, copy_v3_v3(ray_origin, rv3d->viewinv[3]); ED_view3d_win_to_vector(region, mval, ray_direction); - /* Note: we could use #isect_line_plane_v3() + /* NOTE: we could use #isect_line_plane_v3() * however we want the intersection to be in front of the view no matter what, * so apply the unsigned factor instead. */ plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 0e5df3a0cdd..ecf43c734e2 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1378,7 +1378,7 @@ static bool view3d_lasso_select(bContext *C, changed = do_lasso_select_meta(vc, mcoords, mcoords_len, sel_op); break; default: - BLI_assert(!"lasso select on incorrect object type"); + BLI_assert_msg(0, "lasso select on incorrect object type"); break; } @@ -2291,7 +2291,7 @@ static bool ed_object_select_pick(bContext *C, /* In edit-mode do not activate. */ if (obcenter) { - /* note; shift+alt goes to group-flush-selecting */ + /* NOTE: shift+alt goes to group-flush-selecting. */ if (enumerate) { basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend, deselect, toggle); } @@ -2354,10 +2354,10 @@ static bool ed_object_select_pick(bContext *C, // TIMEIT_END(select_time); if (hits > 0) { - /* note: bundles are handling in the same way as bones */ + /* NOTE: bundles are handling in the same way as bones. */ const bool has_bones = object ? false : selectbuffer_has_bones(buffer, hits); - /* note; shift+alt goes to group-flush-selecting */ + /* NOTE: shift+alt goes to group-flush-selecting. */ if (enumerate) { if (has_bones && bone_mouse_select_menu(C, buffer, hits, false, extend, deselect, toggle)) { @@ -3604,7 +3604,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } break; default: - BLI_assert(!"box select on incorrect object type"); + BLI_assert_msg(0, "box select on incorrect object type"); break; } changed_multi |= changed; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 6dec3cc818a..4482e5897ca 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -511,47 +511,47 @@ static int snap_selected_to_location(bContext *C, for (int ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; + if (ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) { + continue; + } - if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { - - float cursor_parent[3]; /* parent-relative */ - - if (use_offset) { - add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); - } - else { - copy_v3_v3(cursor_parent, snap_target_global); - } + float cursor_parent[3]; /* parent-relative */ - sub_v3_v3(cursor_parent, ob->obmat[3]); + if (use_offset) { + add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); + } + else { + copy_v3_v3(cursor_parent, snap_target_global); + } - if (ob->parent) { - float originmat[3][3], parentmat[4][4]; - /* Use the evaluated object here because sometimes - * `ob->parent->runtime.curve_cache` is required. */ - BKE_scene_graph_evaluated_ensure(depsgraph, bmain); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + sub_v3_v3(cursor_parent, ob->obmat[3]); - BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); - mul_m3_m4m4(originmat, parentmat, ob->parentinv); - invert_m3_m3(imat, originmat); - mul_m3_v3(imat, cursor_parent); - } - if ((ob->protectflag & OB_LOCK_LOCX) == 0) { - ob->loc[0] += cursor_parent[0]; - } - if ((ob->protectflag & OB_LOCK_LOCY) == 0) { - ob->loc[1] += cursor_parent[1]; - } - if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { - ob->loc[2] += cursor_parent[2]; - } + if (ob->parent) { + float originmat[3][3], parentmat[4][4]; + /* Use the evaluated object here because sometimes + * `ob->parent->runtime.curve_cache` is required. */ + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + + BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); + mul_m3_m4m4(originmat, parentmat, ob->parentinv); + invert_m3_m3(imat, originmat); + mul_m3_v3(imat, cursor_parent); + } + if ((ob->protectflag & OB_LOCK_LOCX) == 0) { + ob->loc[0] += cursor_parent[0]; + } + if ((ob->protectflag & OB_LOCK_LOCY) == 0) { + ob->loc[1] += cursor_parent[1]; + } + if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { + ob->loc[2] += cursor_parent[2]; + } - /* auto-keyframing */ - ED_autokeyframe_object(C, scene, ob, ks); + /* auto-keyframing */ + ED_autokeyframe_object(C, scene, ob, ks); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - } + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); } if (objects) { @@ -895,7 +895,7 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) /** * Calculates the center position of the active object in global space. * - * Note: this could be exported to be a generic function. + * NOTE: this could be exported to be a generic function. * see: #calculateCenterActive */ static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]) diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 4f8b0fa4685..8bcc05c1e55 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -530,7 +530,7 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, } /** * Action to take when rotating the view, - * handle auto-persp and logic for switching out of views. + * handle auto-perspective and logic for switching out of views. * * shared with NDOF. */ @@ -1699,7 +1699,7 @@ bool ED_view3d_depth_read_cached_normal(const ARegion *region, const int mval[2], float r_normal[3]) { - /* Note: we could support passing in a radius. + /* NOTE: we could support passing in a radius. * For now just read 9 pixels. */ /* pixels surrounding */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index a2d50c43bd2..86a610f8dd9 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -392,7 +392,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, b view3d_boxview_copy(CTX_wm_area(C), region); } - /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, + /* NOTE: this doesn't work right because the v3d->lens is now used in ortho mode r51636, * when switching camera in quad-view the other ortho views would zoom & reset. * * For now only redraw all regions when smooth-view finishes. @@ -1565,7 +1565,7 @@ static uint free_localcollection_bit(Main *bmain, ushort local_collections_uuid, ushort local_view_bits = 0; - /* Check all areas: which localviews are in use? */ + /* Check all areas: which local-views are in use? */ for (screen = bmain->screens.first; screen; screen = screen->id.next) { for (area = screen->areabase.first; area; area = area->next) { SpaceLink *sl = area->spacedata.first; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 88f91d477b5..efcf7d587e1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -78,7 +78,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2]); bool transdata_check_local_islands(TransInfo *t, short around) { - return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((ELEM(t->obedit_type, OB_MESH, OB_GPENCIL)))); + return ((around == V3D_AROUND_LOCAL_ORIGINS) && (ELEM(t->obedit_type, OB_MESH, OB_GPENCIL))); } /* ************************** SPACE DEPENDENT CODE **************************** */ @@ -536,7 +536,7 @@ static void viewRedrawPost(bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } - /* XXX temp, first hack to get auto-render in compositor work (ton) */ + /* XXX(ton): temp, first hack to get auto-render in compositor work. */ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C)); } @@ -1937,7 +1937,7 @@ int transformEnd(bContext *C, TransInfo *t) return exit_code; } -/* TODO, move to: transform_query.c */ +/* TODO: move to: `transform_query.c`. */ bool checkUseAxisMatrix(TransInfo *t) { /* currently only checks for editmode */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index bd0ee1a51c6..1a61a594f37 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -353,7 +353,7 @@ typedef struct TransCon { eTConstraint mode; void (*drawExtra)(struct TransInfo *t); - /* Note: if 'tc' is NULL, 'td' must also be NULL. + /* NOTE: if 'tc' is NULL, 'td' must also be NULL. * For constraints that needs to draw differently from the other * uses this instead of the generic draw function. */ @@ -802,7 +802,7 @@ struct Object *transform_object_deform_pose_armature_get(const TransInfo *t, str void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data); -/* TODO. transform_query.c */ +/* TODO: `transform_query.c`. */ bool checkUseAxisMatrix(TransInfo *t); #define TRANSFORM_SNAP_MAX_PX 100.0f diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 99368a40225..00fd008151d 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -849,10 +849,13 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) /* Copy Transforms constraint only does this in the Before mode. */ bTransLikeConstraint *data = (bTransLikeConstraint *)con->data; - if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE) && + if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE, TRANSLIKE_MIX_BEFORE_FULL) && ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) { return true; } + if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) { + return true; + } } else if (con->type == CONSTRAINT_TYPE_ACTION) { /* The Action constraint only does this in the Before mode. */ diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index 575e0da21a4..255af3feca2 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -277,7 +277,7 @@ void createTransCurveVerts(TransInfo *t) } td->ext = NULL; - /* TODO - make points scale */ + /* TODO: make points scale. */ if (t->mode == TFM_CURVE_SHRINKFATTEN /* `|| t->mode == TFM_RESIZE` */) { td->val = &(bezt->radius); td->ival = bezt->radius; @@ -423,7 +423,7 @@ void createTransCurveVerts(TransInfo *t) calc_distanceCurveVerts(head, tail, cyclic); } - /* TODO - in the case of tilt and radius we can also avoid allocating the + /* TODO: in the case of tilt and radius we can also avoid allocating the * initTransDataCurveHandles but for now just don't change handle types */ if ((nu->type == CU_BEZIER) && ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) { diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c index d57f7fffe0b..111f81ff87b 100644 --- a/source/blender/editors/transform/transform_convert_graph.c +++ b/source/blender/editors/transform/transform_convert_graph.c @@ -939,8 +939,8 @@ static void remake_graph_transdata(TransInfo *t, ListBase *anim_data) if (fcu->bezt) { BeztMap *bezm; - /* adjust transform-data pointers */ - /* note, none of these functions use 'use_handle', it could be removed */ + /* Adjust transform-data pointers. */ + /* NOTE: none of these functions use 'use_handle', it could be removed. */ bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert); sort_time_beztmaps(bezm, fcu->totvert); beztmap_to_data(t, fcu, bezm, fcu->totvert); @@ -1082,7 +1082,7 @@ void special_aftertrans_update__graph(bContext *C, TransInfo *t) /* Make sure all F-Curves are set correctly, but not if transform was * canceled, since then curves were already restored to initial state. - * Note: if the refresh is really needed after cancel then some way + * NOTE: if the refresh is really needed after cancel then some way * has to be added to not update handle types (see bug 22289). */ if (!canceled) { diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c index 45dc6df4fde..54df8270702 100644 --- a/source/blender/editors/transform/transform_convert_mask.c +++ b/source/blender/editors/transform/transform_convert_mask.c @@ -330,7 +330,7 @@ void createTransMaskingData(bContext *C, TransInfo *t) } } - /* note: in prop mode we need at least 1 selected */ + /* NOTE: in prop mode we need at least 1 selected. */ if (countsel == 0) { return; } diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index de2f96c0f97..383f9870714 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1337,7 +1337,7 @@ void transform_convert_mesh_crazyspace_detect(TransInfo *t, * correction with \a quats, relative to the coordinates after * the modifiers that support deform matrices \a defcos. */ -#if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */ +#if 0 /* TODO(campbell): fix crazy-space & extrude so it can be enabled for general use. */ if ((totleft > 0) || (totleft == -1)) #else if (totleft > 0) @@ -2067,6 +2067,27 @@ static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc) } } +static bool tc_mesh_is_deform_only_update(TransInfo *t, TransDataContainer *tc) +{ + if (tc->custom.type.data && + ((struct TransCustomDataMesh *)tc->custom.type.data)->cd_layer_correct) { + return false; + } + + Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(t->depsgraph, (ID *)tc->obedit->data); + Mesh *mesh_eval_cage = me_eval->edit_mesh->mesh_eval_cage; + Mesh *mesh_eval_final = me_eval->edit_mesh->mesh_eval_final; + if (mesh_eval_cage && !mesh_eval_cage->runtime.is_original) { + return false; + } + if (mesh_eval_final && mesh_eval_final != mesh_eval_cage && + !mesh_eval_final->runtime.is_original) { + return false; + } + + return me_eval->runtime.deformed_only; +} + void recalcData_mesh(TransInfo *t) { bool is_canceling = t->state == TRANS_CANCEL; @@ -2094,7 +2115,10 @@ void recalcData_mesh(TransInfo *t) tc_mesh_partial_types_calc(t, &partial_state); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); + const bool is_deform_only = tc_mesh_is_deform_only_update(t, tc); + + DEG_id_tag_update(tc->obedit->data, + is_deform_only ? ID_RECALC_GEOMETRY_DEFORM : ID_RECALC_GEOMETRY); tc_mesh_partial_update(t, tc, &partial_state); } diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index 3b1191a3401..2db3e259153 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -28,6 +28,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c index d91a2a8be4b..61397b6ef4b 100644 --- a/source/blender/editors/transform/transform_convert_mesh_uv.c +++ b/source/blender/editors/transform/transform_convert_mesh_uv.c @@ -30,6 +30,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh_mapping.h" diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index c217478bd04..ee6cb391fdc 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -153,7 +153,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) if (t->mode != TFM_DUMMY && ob->rigidbody_object) { float rot[3][3], scale[3]; - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); /* only use rigid body transform if simulation is running, * avoids problems with initial setup of rigid bodies */ @@ -978,7 +978,7 @@ void special_aftertrans_update__object(bContext *C, TransInfo *t) /* restore rigid body transform */ if (ob->rigidbody_object && canceled) { - float ctime = BKE_scene_frame_get(t->scene); + float ctime = BKE_scene_ctime_get(t->scene); if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) { BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c index cb4df28d94b..681d6aea774 100644 --- a/source/blender/editors/transform/transform_convert_particle.c +++ b/source/blender/editors/transform/transform_convert_particle.c @@ -91,7 +91,7 @@ void createTransParticleVerts(TransInfo *t) } } - /* note: in prop mode we need at least 1 selected */ + /* NOTE: in prop mode we need at least 1 selected. */ if (hasselected == 0) { return; } diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index 51914004e70..17512c79d03 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -262,8 +262,16 @@ static void free_transform_custom_data(TransCustomData *custom_data) /* Canceled, need to update the strips display. */ static void seq_transform_cancel(TransInfo *t, SeqCollection *transformed_strips) { + ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false)); + Sequence *seq; SEQ_ITERATOR_FOREACH (seq, transformed_strips) { + /* Handle pre-existing overlapping strips even when operator is canceled. + * This is necessary for SEQUENCER_OT_duplicate_move macro for example. */ + if (SEQ_transform_test_overlap(seqbase, seq)) { + SEQ_transform_seqbase_shuffle(seqbase, seq, t->scene); + } + SEQ_time_update_sequence_bounds(t->scene, seq); } } @@ -281,7 +289,7 @@ static bool seq_transform_check_overlap(SeqCollection *transformed_strips) static SeqCollection *extract_standalone_strips(SeqCollection *transformed_strips) { - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); Sequence *seq; SEQ_ITERATOR_FOREACH (seq, transformed_strips) { if ((seq->type & SEQ_TYPE_EFFECT) == 0 || seq->seq1 == NULL) { @@ -302,7 +310,7 @@ static SeqCollection *query_right_side_strips(ListBase *seqbase, SeqCollection * } } - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { if ((seq->flag & SELECT) == 0 && seq->startdisp >= minframe) { SEQ_collection_append_strip(seq, collection); @@ -407,7 +415,7 @@ static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transforme static SeqCollection *seq_transform_collection_from_transdata(TransDataContainer *tc) { - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); TransData *td = tc->data; for (int a = 0; a < tc->data_len; a++, td++) { Sequence *seq = ((TransDataSeq *)td->extra)->seq; @@ -428,6 +436,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c if (t->state == TRANS_CANCEL) { seq_transform_cancel(t, transformed_strips); + SEQ_collection_free(transformed_strips); free_transform_custom_data(custom_data); return; } diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h index 606453e356b..15e40ec466b 100644 --- a/source/blender/editors/transform/transform_data.h +++ b/source/blender/editors/transform/transform_data.h @@ -170,7 +170,7 @@ enum { TD_BEZTRIPLE = 1 << 8, /** when this is set, don't apply translation changes to this element */ TD_NO_LOC = 1 << 9, - /** For Graph Editor autosnap, indicates that point should not undergo autosnapping */ + /** For Graph Editor auto-snap, indicates that point should not undergo auto-snapping. */ TD_NOTIMESNAP = 1 << 10, /** For Graph Editor - curves that can only have int-values * need their keyframes tagged with this. */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 9e048a0ca1d..aaac8e21cb9 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -856,8 +856,8 @@ void calculateCenter2D(TransInfo *t) void calculateCenterLocal(TransInfo *t, const float center_global[3]) { - /* setting constraint center */ - /* note, init functions may over-ride t->center */ + /* Setting constraint center. */ + /* NOTE: init functions may over-ride `t->center`. */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->use_local_mat) { mul_v3_m4v3(tc->center_local, tc->imat, center_global); @@ -910,7 +910,7 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2]) BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor); } else { - BLI_assert(!"Shall not happen"); + BLI_assert_msg(0, "Shall not happen"); } r_center[0] = co[0] * t->aspect[0]; diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index fe853440c96..a8f7fc43b5e 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -129,7 +129,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2])) transform_convert_sequencer_channel_clamp(t, values_final); if (t->con.mode & CON_APPLY) { - t->con.applyVec(t, NULL, NULL, t->values, values_final); + t->con.applyVec(t, NULL, NULL, values_final, values_final); } } diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index 6134c8a98f5..066a2853dc7 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -107,7 +107,7 @@ static TransDataContainer *edge_slide_container_first_ok(TransInfo *t) return tc; } } - BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid"); + BLI_assert_msg(0, "Should never happen, at least one EdgeSlideData should be valid"); return NULL; } @@ -565,7 +565,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - /* note, any edge with loops can work, but we won't get predictable results, so bail out */ + /* NOTE: any edge with loops can work, but we won't get predictable results, so bail out. */ if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) { /* can edges with at least once face user */ MEM_freeN(sld); @@ -818,7 +818,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo /* if there are non-contiguous faces, we can still recover * the loops of the new edges faces */ - /* note!, the behavior in this case means edges may move in opposite directions, + /* NOTE:, the behavior in this case means edges may move in opposite directions, * this could be made to work more usefully. */ if (l_a_ok_prev) { diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index e16aa636872..def5f911c6f 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -158,7 +158,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] TransDataVertSlideVert *sv; int i; - /* note: we could save a matrix-multiply for each vertex + /* NOTE: we could save a matrix-multiply for each vertex * by finding the closest edge in local-space. * However this skews the outcome with non-uniform-scale. */ diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index d97bcba161f..155250261de 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -455,7 +455,7 @@ void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3] /* Updates all `BONE_TRANSFORM` flags. * Returns total number of bones with `BONE_TRANSFORM`. - * Note: `transform_convert_pose_transflags_update` has a similar logic. */ + * NOTE: `transform_convert_pose_transflags_update` has a similar logic. */ static int armature_bone_transflags_update_recursive(bArmature *arm, ListBase *lb, const bool do_it) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 9a33dc1218d..2619fdf3403 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -303,10 +303,15 @@ void drawSnapping(const struct bContext *C, TransInfo *t) uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, t->tsnap.snapPoint[0], region->v2d.cur.ymin); - immVertex2f(pos, t->tsnap.snapPoint[0], region->v2d.cur.ymax); - immEnd(); + UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col); + col[3] = 128; + immUniformColor4ubv(col); + float pixelx = BLI_rctf_size_x(®ion->v2d.cur) / BLI_rcti_size_x(®ion->v2d.mask); + immRectf(pos, + t->tsnap.snapPoint[0] - pixelx, + region->v2d.cur.ymax, + t->tsnap.snapPoint[0] + pixelx, + region->v2d.cur.ymin); immUnbindProgram(); GPU_blend(GPU_BLEND_NONE); } @@ -405,7 +410,7 @@ void applyProject(TransInfo *t) transform_data_ext_rotate(td, mat, true); - /* TODO support constraints for rotation too? see ElementRotation */ + /* TODO: support constraints for rotation too? see #ElementRotation. */ } } } diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 4212045a33d..2d98d756dba 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -255,7 +255,7 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object * static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob_eval, - Mesh *me_eval, + const Mesh *me_eval, bool use_hide) { SnapObjectData *sod; @@ -535,7 +535,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, * \{ */ /* Store all ray-hits - * Support for storing all depths, not just the first (raycast 'all') */ + * Support for storing all depths, not just the first (ray-cast 'all'). */ struct RayCastAll_Data { void *bvhdata; @@ -626,7 +626,7 @@ static bool raycast_tri_backface_culling_test( return dot_v3v3(no, dir) < 0.0f; } -/* Callback to raycast with backface culling (Mesh). */ +/* Callback to ray-cast with back-face culling (#Mesh). */ static void mesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, @@ -653,7 +653,7 @@ static void mesh_looptri_raycast_backface_culling_cb(void *userdata, } } -/* Callback to raycast with backface culling (EditMesh). */ +/* Callback to ray-cast with back-face culling (#EditMesh). */ static void editmesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, @@ -687,7 +687,7 @@ static bool raycastMesh(SnapObjectContext *sctx, const float ray_start[3], const float ray_dir[3], Object *ob_eval, - Mesh *me_eval, + const Mesh *me_eval, const float obmat[4][4], const uint ob_index, bool use_hide, @@ -1088,7 +1088,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, case OB_SURF: case OB_FONT: { if (!is_object_active) { - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); + const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); if (mesh_eval) { retval = raycastMesh(sctx, dt->ray_start, diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c index 91bebc9c59d..d0b730383d5 100644 --- a/source/blender/editors/transform/transform_snap_sequencer.c +++ b/source/blender/editors/transform/transform_snap_sequencer.c @@ -108,7 +108,7 @@ static SeqCollection *query_snap_targets(const TransInfo *t) { const ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false)); const short snap_flag = SEQ_tool_settings_snap_flag_get(t->scene); - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { if ((seq->flag & SELECT)) { continue; /* Selected are being transformed. */ @@ -236,6 +236,11 @@ void transform_snap_sequencer_data_free(TransSeqSnapData *data) bool transform_snap_sequencer_calc(TransInfo *t) { + /* Prevent snapping when constrained to Y axis. */ + if (t->con.mode & CON_APPLY && t->con.mode & CON_AXIS1) { + return false; + } + const TransSeqSnapData *snap_data = t->tsnap.seq_context; int best_dist = MAXFRAME, best_target_frame = 0, best_source_frame = 0; diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index df4e6f893ec..3e0029156c1 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -50,6 +50,7 @@ #include "BLO_blend_validate.h" +#include "ED_asset.h" #include "ED_gpencil.h" #include "ED_object.h" #include "ED_outliner.h" @@ -202,7 +203,7 @@ static void ed_undo_step_pre(bContext *C, /* App-Handlers (pre). */ { - /* Note: ignore grease pencil for now. */ + /* NOTE: ignore grease pencil for now. */ wm->op_undo_depth++; BKE_callback_exec_id( bmain, &scene->id, (undo_dir == STEP_UNDO) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE); @@ -268,6 +269,8 @@ static void ed_undo_step_post(bContext *C, WM_toolsystem_refresh_active(C); WM_toolsystem_refresh_screen_all(bmain); + ED_assetlist_storage_tag_main_data_dirty(); + if (CLOG_CHECK(&LOG, 1)) { BKE_undosys_print(wm->undo_stack); } @@ -321,7 +324,7 @@ static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList * /* FIXME: See comments in `ed_undo_step_direction`. */ if (ED_gpencil_session_active()) { - BLI_assert(!"Not implemented currently."); + BLI_assert_msg(0, "Not implemented currently."); } wmWindowManager *wm = CTX_wm_manager(C); @@ -369,7 +372,7 @@ static int ed_undo_step_by_index(bContext *C, const int undo_index, ReportList * /* FIXME: See comments in `ed_undo_step_direction`. */ if (ED_gpencil_session_active()) { - BLI_assert(!"Not implemented currently."); + BLI_assert_msg(0, "Not implemented currently."); } wmWindowManager *wm = CTX_wm_manager(C); @@ -528,7 +531,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op) { if (G.background) { /* Exception for background mode, see: T60934. - * Note: since the undo stack isn't initialized on startup, background mode behavior + * NOTE: since the undo stack isn't initialized on startup, background mode behavior * won't match regular usage, this is just for scripts to do explicit undo pushes. */ wmWindowManager *wm = CTX_wm_manager(C); if (wm->undo_stack == NULL) { @@ -692,12 +695,12 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) CTX_wm_region_set(C, region_win); } - if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) && - /* note, undo/redo can't run if there are jobs active, + if (WM_operator_repeat_check(C, op) && WM_operator_poll(C, op->type) && + /* NOTE: undo/redo can't run if there are jobs active, * check for screen jobs only so jobs like material/texture/world preview * (which copy their data), won't stop redo, see T29579], * - * note, - WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this */ + * NOTE: WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this. */ (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0)) { int retval; @@ -829,7 +832,7 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE return OPERATOR_CANCELLED; } -/* note: also check ed_undo_step() in top if you change notifiers */ +/* NOTE: also check #ed_undo_step() in top if you change notifiers. */ static int undo_history_exec(bContext *C, wmOperator *op) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item"); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 7bbdc58474f..73f328f85d7 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -46,6 +46,7 @@ #include "DEG_depsgraph.h" #include "ED_armature.h" +#include "ED_asset.h" #include "ED_image.h" #include "ED_mesh.h" #include "ED_object.h" @@ -169,6 +170,8 @@ void ED_editors_init(bContext *C) ED_space_image_paint_update(bmain, wm, scene); } + ED_assetlist_storage_tag_main_data_dirty(); + SWAP(int, reports->flag, reports_flag_prev); wm->op_undo_depth--; } diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c index 0f2e280251f..9e05efca3df 100644 --- a/source/blender/editors/util/ed_util_imbuf.c +++ b/source/blender/editors/util/ed_util_imbuf.c @@ -244,7 +244,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event } if (ibuf->zbuf) { - /* TODO, blend depth (not urgent). */ + /* TODO: blend depth (not urgent). */ info->z = ibuf->zbuf[y * ibuf->x + x]; info->zp = &info->z; if (ibuf->zbuf == (int *)ibuf->rect) { @@ -252,7 +252,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event } } if (ibuf->zbuf_float) { - /* TODO, blend depth (not urgent). */ + /* TODO: blend depth (not urgent). */ info->zf = ibuf->zbuf_float[y * ibuf->x + x]; info->zfp = &info->zf; if (ibuf->zbuf_float == ibuf->rect_float) { diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc index 462f7768f81..7d32d252718 100644 --- a/source/blender/editors/util/ed_util_ops.cc +++ b/source/blender/editors/util/ed_util_ops.cc @@ -36,6 +36,7 @@ #include "BLT_translation.h" +#include "ED_asset.h" #include "ED_render.h" #include "ED_undo.h" #include "ED_util.h" @@ -131,9 +132,11 @@ static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op)) if (preview) { BKE_previewimg_clear(preview); } + UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true); WM_event_add_notifier(C, NC_ASSET | NA_EDITED, nullptr); + ED_assetlist_storage_tag_main_data_dirty(); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c index 4e8cf1e92e6..5681edd2f5c 100644 --- a/source/blender/editors/util/select_utils.c +++ b/source/blender/editors/util/select_utils.c @@ -41,7 +41,7 @@ int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool case SEL_OP_XOR: return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1); } - BLI_assert(!"invalid sel_op"); + BLI_assert_msg(0, "invalid sel_op"); return -1; } /** @@ -67,7 +67,7 @@ int ED_select_op_action_deselected(const eSelectOp sel_op, case SEL_OP_XOR: return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1); } - BLI_assert(!"invalid sel_op"); + BLI_assert_msg(0, "invalid sel_op"); return -1; } diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c index 93948b5ae1b..56bcbc63de1 100644 --- a/source/blender/editors/uvedit/uvedit_islands.c +++ b/source/blender/editors/uvedit/uvedit_islands.c @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BLI_rect.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 2f88e50492f..0757e177235 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1496,7 +1496,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) } if (hide) { - /* note, a special case for edges could be used, + /* NOTE: a special case for edges could be used, * for now edges act like verts and get flushed */ if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index eb4ca2e13b2..f97403a0919 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -2154,7 +2154,7 @@ static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed) { - /* move to collapsed_ */ + /* Move to `collapsed_*`. */ PVert *v, *nextv = NULL, *verts = chart->verts; PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL; @@ -2224,7 +2224,7 @@ static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed) static void p_chart_post_split_flush(PChart *chart) { - /* move from collapsed_ */ + /* Move from `collapsed_*`. */ PVert *v, *nextv = NULL; PEdge *e, *nexte = NULL; @@ -2259,7 +2259,7 @@ static void p_chart_post_split_flush(PChart *chart) static void p_chart_simplify_compute(PChart *chart) { /* Computes a list of edge collapses / vertex splits. The collapsed - * simplices go in the chart->collapsed_* lists, The original and + * simplices go in the `chart->collapsed_*` lists, The original and * collapsed may then be view as stacks, where the next collapse/split * is at the top of the respective lists. */ diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 0a7cd579a0a..7709b76290f 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -1351,7 +1351,7 @@ static void uv_select_linked_multi(Scene *scene, BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320 + /* NOTE: we had 'use winding' so we don't consider overlapping islands as connected, see T44320 * this made *every* projection split the island into front/back islands. * Keep 'use_winding' to false, see: T50970. * diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 71656784947..535a0e00347 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1746,7 +1746,8 @@ static void stitch_draw_vbo(GPUVertBuf *vbo, GPUPrimType prim_type, const float GPU_batch_discard(batch); } -/* TODO make things pretier : store batches inside StitchPreviewer instead of the bare verts pos */ +/* TODO: make things pretier : store batches inside StitchPreviewer instead of the bare verts pos + */ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg) { @@ -1927,6 +1928,11 @@ static StitchState *stitch_init(bContext *C, state->obedit = obedit; state->em = em; + /* Workaround for sync-select & face-select mode which implies all selected faces are detached, + * for stitch this isn't useful behavior, see T86924. */ + const int selectmode_orig = scene->toolsettings->selectmode; + scene->toolsettings->selectmode = SCE_SELECT_VERTEX; + /* in uv synch selection, all uv's are visible */ if (ts->uv_flag & UV_SYNC_SELECTION) { state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, false, true, true); @@ -1934,6 +1940,9 @@ static StitchState *stitch_init(bContext *C, else { state->element_map = BM_uv_element_map_create(state->em->bm, scene, true, false, true, true); } + + scene->toolsettings->selectmode = selectmode_orig; + if (!state->element_map) { state_delete(state); return NULL; @@ -1988,7 +1997,7 @@ static StitchState *stitch_init(bContext *C, /* Now, on to generate our uv connectivity data */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!(ts->uv_flag & UV_SYNC_SELECTION) && - ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { continue; } @@ -2171,8 +2180,8 @@ static StitchState *stitch_init(bContext *C, "uv_stitch_selection_stack"); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!(ts->uv_flag & UV_SYNC_SELECTION) && ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || - !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + if (!(ts->uv_flag & UV_SYNC_SELECTION) && + (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { continue; } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index ae02097707c..3d5dabda23d 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -315,7 +315,7 @@ static ParamHandle *construct_param_handle(const Scene *scene, BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { - if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || + if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || (options->only_selected_faces && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) { continue; } @@ -404,7 +404,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene, BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { - if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || + if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || (options->only_selected_faces && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) { continue; } @@ -2319,7 +2319,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) const bool use_orthographic = RNA_boolean_get(op->ptr, "orthographic"); - /* Note: objects that aren't touched are set to NULL (to skip clipping). */ + /* NOTE: objects that aren't touched are set to NULL (to skip clipping). */ uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( view_layer, v3d, &objects_len); diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h index ccb2c61fef5..c8ecbc9eadc 100644 --- a/source/blender/freestyle/intern/application/AppView.h +++ b/source/blender/freestyle/intern/application/AppView.h @@ -214,7 +214,7 @@ class AppView { inline real GetFovyDegrees() const { - return _Fovy * 180.0 / M_PI; // TODO Use RAD2DEG here too? + return _Fovy * 180.0 / M_PI; // TODO: Use RAD2DEG here too? } BBox<Vec3r> scene3DBBox() const diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index a16479873e7..9c3270e788c 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -435,7 +435,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) transpose_m4(nmat); // We count the number of triangles after the clipping by the near and far view - // planes is applied (Note: mesh vertices are in the camera coordinate system). + // planes is applied (NOTE: mesh vertices are in the camera coordinate system). unsigned numFaces = 0; float v1[3], v2[3], v3[3]; float n1[3], n2[3], n3[3], facenormal[3]; diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 4f6ffc451c8..e290b8a87a3 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -671,7 +671,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) visible = false; - // Note: Mesh generation in the following loop assumes stroke strips + // NOTE: Mesh generation in the following loop assumes stroke strips // to be triangle strips. for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) { svRep[0] = *(v[0]); diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h index 9d8ffcfd7fb..949675e9d8d 100644 --- a/source/blender/freestyle/intern/geometry/normal_cycle.h +++ b/source/blender/freestyle/intern/geometry/normal_cycle.h @@ -67,7 +67,7 @@ class NormalCycle { void begin(); void end(); /** - * Note: the specified edge vector needs to be pre-clipped by the neighborhood. + * NOTE: the specified edge vector needs to be pre-clipped by the neighborhood. */ void accumulate_dihedral_angle(const Vec3r &edge, real angle, real neigh_area = 1.0); diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp index 4c339a54bb3..959c5ec7074 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp @@ -122,7 +122,7 @@ static PyObject *FrsNoise_turbulence_smooth(BPy_FrsNoise *self, PyObject *args, { static const char *kwlist[] = {"v", "oct", nullptr}; - double x; // note: this has to be a double (not float) + double x; // NOTE: this has to be a double (not float) unsigned nbOctaves = 8; if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|I", (char **)kwlist, &x, &nbOctaves)) { diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp index 3c0ee9fd9a3..f63ad0d618b 100644 --- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp @@ -48,7 +48,7 @@ PyDoc_STRVAR( " :arg svertex: An SVertex object.\n" " :type svertex: :class:`SVertex`"); -/* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */ +/* NOTE: No copy constructor in Python because the C++ copy constructor is 'protected'. */ static int NonTVertex_init(BPy_NonTVertex *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp index 9fe39b3e359..0e6d6766436 100644 --- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp @@ -49,7 +49,7 @@ PyDoc_STRVAR(TVertex_doc, "\n" " Default constructor."); -/* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */ +/* NOTE: No copy constructor in Python because the C++ copy constructor is 'protected'. */ static int TVertex_init(BPy_TVertex *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.h b/source/blender/freestyle/intern/scene_graph/NodeLight.h index 1d92a96100c..7eb8fcd0029 100644 --- a/source/blender/freestyle/intern/scene_graph/NodeLight.h +++ b/source/blender/freestyle/intern/scene_graph/NodeLight.h @@ -95,7 +95,7 @@ class NodeLight : public Node { * Initially, 0. */ static int numberOfLights; - /** The current lignt number */ + /** The current light number */ int _number; }; diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h index 209ec86edef..cc4c0749ca8 100644 --- a/source/blender/freestyle/intern/stroke/Stroke.h +++ b/source/blender/freestyle/intern/stroke/Stroke.h @@ -514,7 +514,7 @@ class Stroke : public Interface1D { return _id; } - /** The different blending modes available to similate the interaction media-medium. */ + /** The different blending modes available to simulate the interaction media-medium. */ typedef enum { DRY_MEDIUM, /**< To simulate a dry medium such as Pencil or Charcoal. */ HUMID_MEDIUM, /**< To simulate ink painting (color subtraction blending). */ diff --git a/source/blender/freestyle/intern/system/FreestyleConfig.h b/source/blender/freestyle/intern/system/FreestyleConfig.h index 032da864e6c..92c207a1b7f 100644 --- a/source/blender/freestyle/intern/system/FreestyleConfig.h +++ b/source/blender/freestyle/intern/system/FreestyleConfig.h @@ -30,7 +30,7 @@ namespace Freestyle { namespace Config { // Directory separators -// TODO Use Blender's stuff for such things! +// TODO: Use Blender's stuff for such things! #ifdef WIN32 static const string DIR_SEP("\\"); static const string PATH_SEP(";"); diff --git a/source/blender/freestyle/intern/system/RandGen.h b/source/blender/freestyle/intern/system/RandGen.h index f54a0035b62..9d9697a2d34 100644 --- a/source/blender/freestyle/intern/system/RandGen.h +++ b/source/blender/freestyle/intern/system/RandGen.h @@ -21,7 +21,7 @@ * \brief Pseudo-random number generator */ -// TODO Check whether we could replace this with BLI rand stuff... +// TODO: Check whether we could replace this with BLI rand stuff... #include "../system/Precision.h" diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h index 0ec9144595c..3709b0ae11a 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.h +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -1916,7 +1916,7 @@ class SShape { return _LibraryPath; } - /* Modififers */ + /* Modifiers */ /** Sets the Id of the shape. */ inline void setId(Id id) { diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index cd0059f3c21..afb23690a84 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -2285,7 +2285,7 @@ struct less_SVertex2D { Vec3r A = x->point2D(); Vec3r B = y->point2D(); for (unsigned int i = 0; i < 3; i++) { - if ((fabs(A[i] - B[i])) < epsilon) { + if (fabs(A[i] - B[i]) < epsilon) { continue; } if (A[i] < B[i]) { diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp index 774751a2589..7cb06673811 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp @@ -813,7 +813,7 @@ static int save(ostream &out, SVertex *sv) WRITE_IF_NON_NULL(sv->viewvertex()); // Normals (List) - // Note: the 'size()' method of a set doesn't seem to return the actual size of the given set, so + // NOTE: the 'size()' method of a set doesn't seem to return the actual size of the given set, so // we have to hack it... set<Vec3r>::const_iterator i; for (i = sv->normals().begin(), tmp = 0; i != sv->normals().end(); i++, tmp++) { diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp index 62d767fd2a1..478e48de66c 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -98,7 +98,7 @@ static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2) udotv = u * v; denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv); - /* Note: I assume this is what they mean by using atan2(). -Ray Jones */ + /* NOTE(Ray Jones): I assume this is what they mean by using #atan2. */ /* tan = denom/udotv = y/x (see man page for atan2) */ return (fabs(atan2(denom, udotv))); @@ -112,7 +112,7 @@ static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2) * Computes the Discrete Mean Curvature Normal approximation at \a v. * The mean curvature at \a v is half the magnitude of the vector \a Kh. * - * Note: the normal computed is not unit length, and may point either into or out of the surface, + * NOTE: the normal computed is not unit length, and may point either into or out of the surface, * depending on the curvature at \a v. It is the responsibility of the caller of the function to * use the mean curvature normal appropriately. * diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp index bedf4192d64..cef1a8f8f77 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp @@ -37,7 +37,7 @@ unsigned int WXFaceLayer::Get0VertexIndex() const int i = 0; int nEdges = _pWXFace->numberOfEdges(); for (i = 0; i < nEdges; ++i) { - if (_DotP[i] == 0.0f) { // TODO this comparison is weak, check if it actually works + if (_DotP[i] == 0.0f) { // TODO: this comparison is weak, check if it actually works return i; } } @@ -48,7 +48,7 @@ unsigned int WXFaceLayer::GetSmoothEdgeIndex() const int i = 0; int nEdges = _pWXFace->numberOfEdges(); for (i = 0; i < nEdges; ++i) { - if ((_DotP[i] == 0.0f) && (_DotP[(i + 1) % nEdges] == 0.0f)) { // TODO ditto + if ((_DotP[i] == 0.0f) && (_DotP[(i + 1) % nEdges] == 0.0f)) { // TODO: ditto return i; } } diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h index f95913c23f3..b335a364365 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h @@ -465,7 +465,7 @@ class WXFaceLayer { if (iDotP > 0.0f) { ++_nPosDotP; } - if (iDotP == 0.0f) { // TODO this comparison is weak, check if it actually works + if (iDotP == 0.0f) { // TODO: this comparison is weak, check if it actually works ++_nNullDotP; } } @@ -484,7 +484,7 @@ class WXFaceLayer { if ((*d) > 0.0f) { ++_nPosDotP; } - if ((*d) == 0.0f) { // TODO ditto + if ((*d) == 0.0f) { // TODO: ditto ++_nNullDotP; } } diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh index 4de0533a46d..421e5f0018d 100644 --- a/source/blender/functions/FN_cpp_type.hh +++ b/source/blender/functions/FN_cpp_type.hh @@ -545,6 +545,13 @@ class CPPType : NonCopyable, NonMovable { m_.print(value, ss); } + std::string to_string(const void *value) const + { + std::stringstream ss; + this->print(value, ss); + return ss.str(); + } + void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const { if (this->is_printable()) { diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index f39306ac9d0..ec965c9a29f 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -68,6 +68,7 @@ set(SRC intern/MOD_gpencilthick.c intern/MOD_gpenciltime.c intern/MOD_gpenciltint.c + intern/MOD_gpencilweight.c MOD_gpencil_lineart.h MOD_gpencil_modifiertypes.h diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h index f8a28f2e5cb..18310bd5dff 100644 --- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h +++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h @@ -44,6 +44,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Armature; extern GpencilModifierTypeInfo modifierType_Gpencil_Time; extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply; extern GpencilModifierTypeInfo modifierType_Gpencil_Texture; +extern GpencilModifierTypeInfo modifierType_Gpencil_Weight; extern GpencilModifierTypeInfo modifierType_Gpencil_Lineart; /* MOD_gpencil_util.c */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c index 94285b5032e..a156fca5b7b 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c @@ -203,20 +203,6 @@ void gpencil_modifier_curve_panel_draw(const bContext *UNUSED(C), Panel *panel) uiTemplateCurveMapping(layout, ptr, "curve", 0, false, false, false, false); } -void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel) -{ - PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); - - uiLayout *layout = panel->layout; - uiLayoutSetPropSep(layout, true); - - uiItemR(layout, ptr, "object", 0, NULL, ICON_CUBE); - uiLayout *sub = uiLayoutColumn(layout, true); - uiItemR(sub, ptr, "fading_start", 0, NULL, ICON_NONE); - uiItemR(sub, ptr, "fading_end", 0, IFACE_("End"), ICON_NONE); - uiItemR(layout, ptr, "fading_end_factor", 0, NULL, ICON_NONE); -} - /** * Draw modifier error message. */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h index 75907aaa781..782b36d47ed 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h @@ -37,8 +37,6 @@ void gpencil_modifier_masking_panel_draw(Panel *panel, bool use_material, bool u void gpencil_modifier_curve_header_draw(const bContext *C, Panel *panel); void gpencil_modifier_curve_panel_draw(const bContext *C, Panel *panel); -void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel); - void gpencil_modifier_panel_end(struct uiLayout *layout, PointerRNA *ptr); struct PointerRNA *gpencil_modifier_panel_get_property_pointers(struct Panel *panel, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index b28a44a0521..6409c86b6e3 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -63,6 +63,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]) INIT_GP_TYPE(Time); INIT_GP_TYPE(Multiply); INIT_GP_TYPE(Texture); + INIT_GP_TYPE(Weight); INIT_GP_TYPE(Lineart); #undef INIT_GP_TYPE } @@ -152,16 +153,16 @@ float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr) if ((dvert != NULL) && (def_nr != -1)) { MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr); weight = dw ? dw->weight : -1.0f; - if ((weight >= 0.0f) && (inverse == 1)) { + if ((weight >= 0.0f) && (inverse)) { return -1.0f; } - if ((weight < 0.0f) && (inverse == 0)) { + if ((weight < 0.0f) && (!inverse)) { return -1.0f; } /* if inverse, weight is always 1 */ - if ((weight < 0.0f) && (inverse == 1)) { + if ((weight < 0.0f) && (inverse)) { return 1.0f; } } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c index d9f0fc9bddd..4e07827c940 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c @@ -112,7 +112,7 @@ static void gpf_clear_all_strokes(bGPDframe *gpf) /* Reduce the number of points in the stroke * - * Note: This won't be called if all points are present/removed + * NOTE: This won't be called if all points are present/removed */ static void reduce_stroke_points(bGPdata *gpd, bGPDstroke *gps, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c index 9593a1364e7..fcc44aab583 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c @@ -205,11 +205,18 @@ static void bakeModifier(Main *UNUSED(bmain), } if (!gpd->runtime.lineart_cache) { + /* Only calculate for this modifier, thus no need to get maximum values from all line art + * modifiers in the stack. */ + lmd->edge_types_override = lmd->edge_types; + lmd->level_end_override = lmd->level_end; + MOD_lineart_compute_feature_lines(depsgraph, lmd, &gpd->runtime.lineart_cache); MOD_lineart_destroy_render_data(lmd); } generate_strokes_actual(md, depsgraph, ob, gpl, gpf); + + MOD_lineart_clear_cache(&gpd->runtime.lineart_cache); } static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams)) @@ -331,7 +338,7 @@ static void edge_types_panel_draw(const bContext *UNUSED(C), Panel *panel) PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr); const bool is_baked = RNA_boolean_get(ptr, "is_baked"); - const bool use_cache = RNA_boolean_get(ptr, "use_cached_result"); + const bool use_cache = RNA_boolean_get(ptr, "use_cache"); const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data); uiLayoutSetEnabled(layout, !is_baked); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c index cd29a006aae..1a38b91a18b 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c @@ -129,14 +129,6 @@ static void deformStroke(GpencilModifierData *md, } } } - /* Calculate Random matrix. */ - float mat_rnd[4][4]; - float rnd_loc[3], rnd_rot[3]; - float rnd_scale[3] = {1.0f, 1.0f, 1.0f}; - mul_v3_v3v3(rnd_loc, mmd->rnd_offset, rand[0]); - mul_v3_v3v3(rnd_rot, mmd->rnd_rot, rand[1]); - madd_v3_v3v3(rnd_scale, mmd->rnd_scale, rand[2]); - loc_eul_size_to_mat4(mat_rnd, rnd_loc, rnd_rot, rnd_scale); bGPdata *gpd = ob->data; @@ -150,6 +142,21 @@ static void deformStroke(GpencilModifierData *md, if (weight < 0.0f) { continue; } + + /* Calculate Random matrix. */ + float mat_rnd[4][4]; + float rnd_loc[3], rnd_rot[3], rnd_scale_weight[3]; + float rnd_scale[3] = {1.0f, 1.0f, 1.0f}; + + mul_v3_v3fl(rnd_loc, rand[0], weight); + mul_v3_v3fl(rnd_rot, rand[1], weight); + mul_v3_v3fl(rnd_scale_weight, rand[2], weight); + + mul_v3_v3v3(rnd_loc, mmd->rnd_offset, rnd_loc); + mul_v3_v3v3(rnd_rot, mmd->rnd_rot, rnd_rot); + madd_v3_v3v3(rnd_scale, mmd->rnd_scale, rnd_scale_weight); + + loc_eul_size_to_mat4(mat_rnd, rnd_loc, rnd_rot, rnd_scale); /* Apply randomness matrix. */ mul_m4_v3(mat_rnd, &pt->x); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c index 9f03e493ea8..fb75b1e99ac 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c @@ -47,8 +47,6 @@ #include "BKE_screen.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" -#include "DEG_depsgraph_query.h" #include "UI_interface.h" #include "UI_resources.h" @@ -86,39 +84,6 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } -static float give_opacity_fading_factor(OpacityGpencilModifierData *mmd, - Object *ob_this, - float *pos, - bool apply_obmat) -{ - float factor_depth = 1.0f; - - if (((mmd->flag & GP_OPACITY_FADING) == 0) || ((mmd->object) == NULL)) { - return factor_depth; - } - - float gvert[3]; - if (apply_obmat) { - mul_v3_m4v3(gvert, ob_this->obmat, pos); - } - float dist = len_v3v3(mmd->object->obmat[3], gvert); - float fading_max = MAX2(mmd->fading_start, mmd->fading_end); - float fading_min = MIN2(mmd->fading_start, mmd->fading_end); - - /* Better with ratiof() function from line art. */ - if (dist > fading_max) { - factor_depth = 0.0f; - } - else if (dist <= fading_max && dist > fading_min) { - factor_depth = (fading_max - dist) / (fading_max - fading_min); - } - else { - factor_depth = 1.0f; - } - - return factor_depth; -} - /* opacity strokes */ static void deformStroke(GpencilModifierData *md, Depsgraph *UNUSED(depsgraph), @@ -130,6 +95,9 @@ static void deformStroke(GpencilModifierData *md, OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md; const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname); const bool use_curve = (mmd->flag & GP_OPACITY_CUSTOM_CURVE) != 0 && mmd->curve_intensity; + const bool is_normalized = (mmd->flag & GP_OPACITY_NORMALIZE); + bool is_inverted = ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) == 0) && + ((mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0); if (!is_stroke_affected_by_modifier(ob, mmd->layername, @@ -161,11 +129,17 @@ static void deformStroke(GpencilModifierData *md, /* Stroke using strength. */ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) { /* verify vertex group */ - float weight = get_modifier_point_weight( - dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr); + float weight = get_modifier_point_weight(dvert, is_inverted, def_nr); if (weight < 0.0f) { continue; } + + /* Apply weight directly. */ + if ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) && (!is_normalized)) { + pt->strength *= ((mmd->flag & GP_OPACITY_INVERT_VGROUP) ? 1.0f - weight : weight); + continue; + } + /* Custom curve to modulate value. */ float factor_curve = mmd->factor; if (use_curve) { @@ -173,9 +147,6 @@ static void deformStroke(GpencilModifierData *md, factor_curve *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value); } - float factor_depth = give_opacity_fading_factor(mmd, ob, &pt->x, true); - factor_curve = interpf(factor_curve, mmd->fading_end_factor, factor_depth); - if (def_nr < 0) { if (mmd->flag & GP_OPACITY_NORMALIZE) { pt->strength = factor_curve; @@ -204,9 +175,19 @@ static void deformStroke(GpencilModifierData *md, /* Fill using opacity factor. */ if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) { - float factor_depth = give_opacity_fading_factor(mmd, ob, ob->obmat[3], true); - gps->fill_opacity_fac = interpf(mmd->factor, mmd->fading_end_factor, factor_depth); + float fill_factor = mmd->factor; + if ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) && (!is_normalized)) { + /* Use first point for weight. */ + MDeformVert *dvert = (gps->dvert != NULL) ? &gps->dvert[0] : NULL; + float weight = get_modifier_point_weight( + dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr); + if (weight >= 0.0f) { + fill_factor = ((mmd->flag & GP_OPACITY_INVERT_VGROUP) ? 1.0f - weight : weight); + } + } + + gps->fill_opacity_fac = fill_factor; CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f); } } @@ -241,18 +222,6 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md; walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); - walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP); -} - -static void updateDepsgraph(GpencilModifierData *md, - const ModifierUpdateDepsgraphContext *ctx, - const int UNUSED(mode)) -{ - OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md; - if (mmd->object != NULL) { - DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier"); - } - DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier"); } static void panel_draw(const bContext *UNUSED(C), Panel *panel) @@ -271,29 +240,25 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(layout, ptr, "hardness", 0, NULL, ICON_NONE); } else { + const bool is_normalized = RNA_boolean_get(ptr, "normalize_opacity"); + const bool is_weighted = RNA_boolean_get(ptr, "use_weight_factor"); + uiItemR(layout, ptr, "normalize_opacity", 0, NULL, ICON_NONE); - const char *text = (RNA_boolean_get(ptr, "normalize_opacity")) ? IFACE_("Strength") : - IFACE_("Opacity Factor"); - uiItemR(layout, ptr, "factor", 0, text, ICON_NONE); + const char *text = (is_normalized) ? IFACE_("Strength") : IFACE_("Opacity Factor"); + + uiLayout *row = uiLayoutRow(layout, true); + uiLayoutSetActive(row, !is_weighted || is_normalized); + uiItemR(row, ptr, "factor", 0, text, ICON_NONE); + if (!is_normalized) { + uiLayout *sub = uiLayoutRow(row, true); + uiLayoutSetActive(sub, true); + uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT); + } } gpencil_modifier_panel_end(layout, ptr); } -static void fading_header_draw(const bContext *UNUSED(C), Panel *panel) -{ - uiLayout *layout = panel->layout; - - PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); - - uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE); -} - -static void fading_panel_draw(const bContext *C, Panel *panel) -{ - gpencil_modifier_fading_draw(C, panel); -} - static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel) { PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); @@ -333,8 +298,6 @@ static void panelRegister(ARegionType *region_type) PanelType *panel_type = gpencil_modifier_panel_register( region_type, eGpencilModifierType_Opacity, panel_draw); - gpencil_modifier_subpanel_register( - region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type); PanelType *mask_panel_type = gpencil_modifier_subpanel_register( region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type); gpencil_modifier_subpanel_register( @@ -358,7 +321,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = { /* initData */ initData, /* freeData */ freeData, /* isDisabled */ NULL, - /* updateDepsgraph */ updateDepsgraph, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c index 126949cd659..cac700e15f4 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c @@ -43,8 +43,6 @@ #include "BKE_screen.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" -#include "DEG_depsgraph_query.h" #include "UI_interface.h" #include "UI_resources.h" @@ -118,42 +116,28 @@ static void deformStroke(GpencilModifierData *md, } float stroke_thickness_inv = 1.0f / max_ii(gps->thickness, 1); + const bool is_normalized = (mmd->flag & GP_THICK_NORMALIZE); + bool is_inverted = ((mmd->flag & GP_THICK_WEIGHT_FACTOR) == 0) && + ((mmd->flag & GP_THICK_INVERT_VGROUP) != 0); for (int i = 0; i < gps->totpoints; i++) { bGPDspoint *pt = &gps->points[i]; MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; /* Verify point is part of vertex group. */ - float weight = get_modifier_point_weight( - dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr); + float weight = get_modifier_point_weight(dvert, is_inverted, def_nr); if (weight < 0.0f) { continue; } - float curvef = 1.0f; - - float factor_depth = 1.0f; - - if (mmd->flag & GP_THICK_FADING) { - if (mmd->object) { - float gvert[3]; - mul_v3_m4v3(gvert, ob->obmat, &pt->x); - float dist = len_v3v3(mmd->object->obmat[3], gvert); - float fading_max = MAX2(mmd->fading_start, mmd->fading_end); - float fading_min = MIN2(mmd->fading_start, mmd->fading_end); - - /* Better with ratiof() function from line art. */ - if (dist > fading_max) { - factor_depth = 0.0f; - } - else if (dist <= fading_max && dist > fading_min) { - factor_depth = (fading_max - dist) / (fading_max - fading_min); - } - else { - factor_depth = 1.0f; - } - } + /* Apply weight directly. */ + if ((!is_normalized) && (mmd->flag & GP_THICK_WEIGHT_FACTOR)) { + pt->pressure *= ((mmd->flag & GP_THICK_INVERT_VGROUP) ? 1.0f - weight : weight); + CLAMP_MIN(pt->pressure, 0.0f); + continue; } + float curvef = 1.0f; + if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) { /* Normalize value to evaluate curve. */ float value = (float)i / (gps->totpoints - 1); @@ -161,7 +145,7 @@ static void deformStroke(GpencilModifierData *md, } float target; - if (mmd->flag & GP_THICK_NORMALIZE) { + if (is_normalized) { target = mmd->thickness * stroke_thickness_inv; target *= curvef; } @@ -170,11 +154,6 @@ static void deformStroke(GpencilModifierData *md, weight *= curvef; } - /* Apply distance fading. */ - if (mmd->flag & GP_THICK_FADING) { - target = interpf(target, mmd->fading_end_factor, factor_depth); - } - pt->pressure = interpf(target, pt->pressure, weight); CLAMP_MIN(pt->pressure, 0.0f); @@ -202,32 +181,6 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md; walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); - walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP); -} - -static void updateDepsgraph(GpencilModifierData *md, - const ModifierUpdateDepsgraphContext *ctx, - const int UNUSED(mode)) -{ - ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md; - if (mmd->object != NULL) { - DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier"); - } - DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier"); -} - -static void fading_header_draw(const bContext *UNUSED(C), Panel *panel) -{ - uiLayout *layout = panel->layout; - - PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); - - uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE); -} - -static void fading_panel_draw(const bContext *C, Panel *panel) -{ - gpencil_modifier_fading_draw(C, panel); } static void panel_draw(const bContext *UNUSED(C), Panel *panel) @@ -239,12 +192,17 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); uiItemR(layout, ptr, "normalize_thickness", 0, NULL, ICON_NONE); - if (RNA_boolean_get(ptr, "normalize_thickness")) { uiItemR(layout, ptr, "thickness", 0, NULL, ICON_NONE); } else { - uiItemR(layout, ptr, "thickness_factor", 0, NULL, ICON_NONE); + const bool is_weighted = !RNA_boolean_get(ptr, "use_weight_factor"); + uiLayout *row = uiLayoutRow(layout, true); + uiLayoutSetActive(row, is_weighted); + uiItemR(row, ptr, "thickness_factor", 0, NULL, ICON_NONE); + uiLayout *sub = uiLayoutRow(row, true); + uiLayoutSetActive(sub, true); + uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT); } gpencil_modifier_panel_end(layout, ptr); @@ -259,8 +217,6 @@ static void panelRegister(ARegionType *region_type) { PanelType *panel_type = gpencil_modifier_panel_register( region_type, eGpencilModifierType_Thick, panel_draw); - gpencil_modifier_subpanel_register( - region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type); PanelType *mask_panel_type = gpencil_modifier_subpanel_register( region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type); gpencil_modifier_subpanel_register(region_type, @@ -288,7 +244,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = { /* initData */ initData, /* freeData */ freeData, /* isDisabled */ NULL, - /* updateDepsgraph */ updateDepsgraph, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c index 4a6e3df59c7..680f5ab05ec 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c @@ -127,6 +127,8 @@ static void deformStroke(GpencilModifierData *md, const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname); const bool use_curve = (mmd->flag & GP_TINT_CUSTOM_CURVE) != 0 && mmd->curve_intensity; + bool is_inverted = ((mmd->flag & GP_TINT_WEIGHT_FACTOR) == 0) && + ((mmd->flag & GP_TINT_INVERT_VGROUP) != 0); if (!is_stroke_affected_by_modifier(ob, mmd->layername, @@ -169,6 +171,17 @@ static void deformStroke(GpencilModifierData *md, if (!fill_done) { /* Apply to fill. */ if (mmd->mode != GPPAINT_MODE_STROKE) { + float fill_factor = mmd->factor; + + /* Use weighted factor. */ + if (mmd->flag & GP_TINT_WEIGHT_FACTOR) { + /* Use first point for weight. */ + MDeformVert *dvert_fill = (gps->dvert != NULL) ? &gps->dvert[0] : NULL; + float weight = get_modifier_point_weight(dvert_fill, is_inverted, def_nr); + if (weight >= 0.0f) { + fill_factor = ((mmd->flag & GP_TINT_INVERT_VGROUP) ? 1.0f - weight : weight); + } + } /* If not using Vertex Color, use the material color. */ if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) && @@ -188,13 +201,13 @@ static void deformStroke(GpencilModifierData *md, BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res); interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, coba_res, mmd->factor); - gps->vert_color_fill[3] = clamp_f(mmd->factor, 0.0f, 1.0f); + gps->vert_color_fill[3] = clamp_f(fill_factor, 0.0f, 1.0f); } else { interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, mmd->rgb, - clamp_f(mmd->factor, 0.0f, 1.0f)); + clamp_f(fill_factor, 0.0f, 1.0f)); } /* If no stroke, cancel loop. */ if (mmd->mode != GPPAINT_MODE_BOTH) { @@ -207,11 +220,13 @@ static void deformStroke(GpencilModifierData *md, /* Verify vertex group. */ if (mmd->mode != GPPAINT_MODE_FILL) { - float weight = get_modifier_point_weight( - dvert, (mmd->flag & GP_TINT_INVERT_VGROUP) != 0, def_nr); + float weight = get_modifier_point_weight(dvert, is_inverted, def_nr); if (weight < 0.0f) { continue; } + + float factor = mmd->factor; + /* Custom curve to modulate value. */ if (use_curve) { float value = (float)i / (gps->totpoints - 1); @@ -224,6 +239,12 @@ static void deformStroke(GpencilModifierData *md, pt->vert_color[3] = 1.0f; } + /* Apply weight directly. */ + if (mmd->flag & GP_TINT_WEIGHT_FACTOR) { + factor = ((mmd->flag & GP_TINT_INVERT_VGROUP) ? 1.0f - weight : weight); + weight = 1.0f; + } + if (is_gradient) { /* Calc world position of point. */ float pt_loc[3]; @@ -237,11 +258,11 @@ static void deformStroke(GpencilModifierData *md, interp_v3_v3v3(pt->vert_color, pt->vert_color, coba_res, - clamp_f(mmd->factor, 0.0f, 1.0f) * weight * coba_res[3]); + clamp_f(factor, 0.0f, 1.0f) * weight * coba_res[3]); } else { interp_v3_v3v3( - pt->vert_color, pt->vert_color, mmd->rgb, clamp_f(mmd->factor * weight, 0.0, 1.0f)); + pt->vert_color, pt->vert_color, mmd->rgb, clamp_f(factor * weight, 0.0, 1.0f)); } } } @@ -338,7 +359,15 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); uiItemR(layout, ptr, "vertex_mode", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "factor", 0, NULL, ICON_NONE); + + const bool is_weighted = !RNA_boolean_get(ptr, "use_weight_factor"); + uiLayout *row = uiLayoutRow(layout, true); + uiLayoutSetActive(row, is_weighted); + uiItemR(row, ptr, "factor", 0, NULL, ICON_NONE); + uiLayout *sub = uiLayoutRow(row, true); + uiLayoutSetActive(sub, true); + uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT); + uiItemR(layout, ptr, "tint_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); if (tint_type == GP_TINT_UNIFORM) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c new file mode 100644 index 00000000000..c7fe20edef7 --- /dev/null +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c @@ -0,0 +1,335 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021, Blender Foundation + * This is a new part of Blender + */ + +/** \file + * \ingroup modifiers + */ + +#include <stdio.h> + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_defaults.h" +#include "DNA_gpencil_modifier_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" + +#include "BKE_colortools.h" +#include "BKE_context.h" +#include "BKE_deform.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" +#include "BKE_screen.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "RNA_access.h" + +#include "MOD_gpencil_modifiertypes.h" +#include "MOD_gpencil_ui_common.h" +#include "MOD_gpencil_util.h" + +static void initData(GpencilModifierData *md) +{ + WeightGpencilModifierData *gpmd = (WeightGpencilModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier)); + + MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(WeightGpencilModifierData), modifier); +} + +static void copyData(const GpencilModifierData *md, GpencilModifierData *target) +{ + BKE_gpencil_modifier_copydata_generic(md, target); +} + +/* Calc distance between point and target object. */ +static float calc_point_weight_by_distance(Object *ob, + WeightGpencilModifierData *mmd, + const float dist_max, + const float dist_min, + bGPDspoint *pt) +{ + float weight; + float gvert[3]; + mul_v3_m4v3(gvert, ob->obmat, &pt->x); + float dist = len_v3v3(mmd->object->obmat[3], gvert); + + if (dist > dist_max) { + weight = 0.0f; + } + else if (dist <= dist_max && dist > dist_min) { + weight = (dist_max - dist) / max_ff((dist_max - dist_min), 0.0001f); + } + else { + weight = 1.0f; + } + + return weight; +} + +/* change stroke thickness */ +static void deformStroke(GpencilModifierData *md, + Depsgraph *UNUSED(depsgraph), + Object *ob, + bGPDlayer *gpl, + bGPDframe *UNUSED(gpf), + bGPDstroke *gps) +{ + WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md; + const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname); + const eWeightGpencilModifierMode mode = mmd->mode; + + if (!is_stroke_affected_by_modifier(ob, + mmd->layername, + mmd->material, + mmd->pass_index, + mmd->layer_pass, + 1, + gpl, + gps, + mmd->flag & GP_WEIGHT_INVERT_LAYER, + mmd->flag & GP_WEIGHT_INVERT_PASS, + mmd->flag & GP_WEIGHT_INVERT_LAYERPASS, + mmd->flag & GP_WEIGHT_INVERT_MATERIAL)) { + return; + } + + const float dist_max = MAX2(mmd->dist_start, mmd->dist_end); + const float dist_min = MIN2(mmd->dist_start, mmd->dist_end); + const int target_def_nr = BKE_object_defgroup_name_index(ob, mmd->target_vgname); + + if (target_def_nr == -1) { + return; + } + + /* Use default Z up. */ + float vec_axis[3] = {0.0f, 0.0f, 1.0f}; + float axis[3] = {0.0f, 0.0f, 0.0f}; + axis[mmd->axis] = 1.0f; + float vec_ref[3]; + /* Apply modifier rotation (sub 90 degrees for Y axis due Z-Up vector). */ + float rot_angle = mmd->angle - ((mmd->axis == 1) ? M_PI_2 : 0.0f); + rotate_normalized_v3_v3v3fl(vec_ref, vec_axis, axis, rot_angle); + + /* Apply the rotation of the object. */ + if (mmd->space == GP_SPACE_LOCAL) { + mul_mat3_m4_v3(ob->obmat, vec_ref); + } + + /* Ensure there is a vertex group. */ + BKE_gpencil_dvert_ensure(gps); + + float weight_pt = 1.0f; + for (int i = 0; i < gps->totpoints; i++) { + MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; + /* Verify point is part of vertex group. */ + float weight = get_modifier_point_weight( + dvert, (mmd->flag & GP_WEIGHT_INVERT_VGROUP) != 0, def_nr); + if (weight < 0.0f) { + continue; + } + + switch (mode) { + case GP_WEIGHT_MODE_DISTANCE: { + if (mmd->object) { + bGPDspoint *pt = &gps->points[i]; + weight_pt = calc_point_weight_by_distance(ob, mmd, dist_max, dist_min, pt); + } + break; + } + case GP_WEIGHT_MODE_ANGLE: { + /* Special case for single points. */ + if (gps->totpoints == 1) { + weight_pt = 1.0f; + break; + } + + bGPDspoint *pt1 = (i > 0) ? &gps->points[i] : &gps->points[i + 1]; + bGPDspoint *pt2 = (i > 0) ? &gps->points[i - 1] : &gps->points[i]; + float fpt1[3], fpt2[3]; + mul_v3_m4v3(fpt1, ob->obmat, &pt1->x); + mul_v3_m4v3(fpt2, ob->obmat, &pt2->x); + + float vec[3]; + sub_v3_v3v3(vec, fpt1, fpt2); + float angle = angle_on_axis_v3v3_v3(vec_ref, vec, axis); + /* Use sin to get a value between 0 and 1. */ + weight_pt = 1.0f - sin(angle); + break; + } + default: + break; + } + + /* Invert weight if required. */ + if (mmd->flag & GP_WEIGHT_INVERT_OUTPUT) { + weight_pt = 1.0f - weight_pt; + } + /* Assign weight. */ + dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; + if (dvert != NULL) { + MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr); + if (dw) { + dw->weight = (mmd->flag & GP_WEIGHT_BLEND_DATA) ? dw->weight * weight_pt : weight_pt; + CLAMP(dw->weight, mmd->min_weight, 1.0f); + } + } + } +} + +static void bakeModifier(struct Main *UNUSED(bmain), + Depsgraph *depsgraph, + GpencilModifierData *md, + Object *ob) +{ + bGPdata *gpd = ob->data; + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + deformStroke(md, depsgraph, ob, gpl, gpf, gps); + } + } + } +} + +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP); +} + +static void updateDepsgraph(GpencilModifierData *md, + const ModifierUpdateDepsgraphContext *ctx, + const int UNUSED(mode)) +{ + WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md; + if (mmd->object != NULL) { + DEG_add_object_relation( + ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "GPencil Weight Modifier"); + } + DEG_add_object_relation( + ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "GPencil Weight Modifier"); +} + +static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams)) +{ + WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md; + + return !(mmd->target_vgname && mmd->target_vgname[0] != '\0'); +} + +static void distance_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + + uiLayout *layout = panel->layout; + uiLayoutSetPropSep(layout, true); + + uiItemR(layout, ptr, "object", 0, NULL, ICON_CUBE); + uiLayout *sub = uiLayoutColumn(layout, true); + uiItemR(sub, ptr, "distance_start", 0, NULL, ICON_NONE); + uiItemR(sub, ptr, "distance_end", 0, "End", ICON_NONE); +} + +static void panel_draw(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr); + + uiLayoutSetPropSep(layout, true); + uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE); + + const eWeightGpencilModifierMode mode = RNA_enum_get(ptr, "mode"); + + uiItemPointerR(layout, ptr, "target_vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE); + + uiItemR(layout, ptr, "minimum_weight", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_invert_output", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_blend", 0, NULL, ICON_NONE); + + switch (mode) { + case GP_WEIGHT_MODE_DISTANCE: + distance_panel_draw(C, panel); + break; + case GP_WEIGHT_MODE_ANGLE: + uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "axis", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE); + break; + default: + break; + } + + gpencil_modifier_panel_end(layout, ptr); +} + +static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + gpencil_modifier_masking_panel_draw(panel, true, true); +} + +static void panelRegister(ARegionType *region_type) +{ + PanelType *panel_type = gpencil_modifier_panel_register( + region_type, eGpencilModifierType_Weight, panel_draw); + + gpencil_modifier_subpanel_register( + region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type); +} + +GpencilModifierTypeInfo modifierType_Gpencil_Weight = { + /* name */ "Vertex Weight", + /* structName */ "WeightGpencilModifierData", + /* structSize */ sizeof(WeightGpencilModifierData), + /* type */ eGpencilModifierTypeType_Gpencil, + /* flags */ 0, + + /* copyData */ copyData, + + /* deformStroke */ deformStroke, + /* generateStrokes */ NULL, + /* bakeModifier */ bakeModifier, + /* remapTime */ NULL, + + /* initData */ initData, + /* freeData */ NULL, + /* isDisabled */ isDisabled, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ NULL, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ NULL, + /* panelRegister */ panelRegister, +}; diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h index 247b0b3f57b..1d4370ed3a9 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h +++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h @@ -575,9 +575,9 @@ BLI_INLINE int lineart_LineIntersectTest2d( } struct Depsgraph; -struct Scene; -struct LineartRenderBuffer; struct LineartGpencilModifierData; +struct LineartRenderBuffer; +struct Scene; void MOD_lineart_destroy_render_data(struct LineartGpencilModifierData *lmd); @@ -602,8 +602,8 @@ LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *r LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y); -struct bGPDlayer; struct bGPDframe; +struct bGPDlayer; void MOD_lineart_gpencil_generate(LineartCache *cache, struct Depsgraph *depsgraph, diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c index 52485648ee0..d86253e7fe0 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c @@ -635,7 +635,7 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb) } /** - * Note: segment type (crease/material/contour...) is ambiguous after this. + * NOTE: segment type (crease/material/contour...) is ambiguous after this. */ static void lineart_chain_connect(LineartRenderBuffer *UNUSED(rb), LineartEdgeChain *onto, diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index c05749061a9..82fd85f5c65 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -735,6 +735,7 @@ static void lineart_triangle_post(LineartTriangle *tri, LineartTriangle *orig) copy_v3_v3_db(tri->gn, orig->gn); tri->flags = LRT_CULL_GENERATED; tri->material_mask_bits = orig->material_mask_bits; + tri->mat_occlusion = orig->mat_occlusion; } static void lineart_triangle_set_cull_flag(LineartTriangle *tri, uchar flag) @@ -1695,7 +1696,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu } if (rb->remove_doubles) { - BMEditMesh *em = BKE_editmesh_create(bm, false); + BMEditMesh *em = BKE_editmesh_create(bm); BMOperator findop, weldop; /* See bmesh_opdefines.c and bmesh_operators.c for op names and argument formatting. */ @@ -3441,9 +3442,9 @@ static bool lineart_bounding_area_triangle_intersect(LineartRenderBuffer *fb, return true; } - if ((lineart_bounding_area_edge_intersect(fb, FBC1, FBC2, ba)) || - (lineart_bounding_area_edge_intersect(fb, FBC2, FBC3, ba)) || - (lineart_bounding_area_edge_intersect(fb, FBC3, FBC1, ba))) { + if (lineart_bounding_area_edge_intersect(fb, FBC1, FBC2, ba) || + lineart_bounding_area_edge_intersect(fb, FBC2, FBC3, ba) || + lineart_bounding_area_edge_intersect(fb, FBC3, FBC1, ba)) { return true; } @@ -4216,9 +4217,6 @@ static void lineart_gpencil_generate(LineartCache *cache, /* (!orig_col && !orig_ob) means the whole scene is selected. */ - float mat[4][4]; - unit_m4(mat); - int enabled_types = cache->rb_edge_types; bool invert_input = modifier_flags & LRT_GPENCIL_INVERT_SOURCE_VGROUP; bool match_output = modifier_flags & LRT_GPENCIL_MATCH_OUTPUT_VGROUP; @@ -4270,29 +4268,20 @@ static void lineart_gpencil_generate(LineartCache *cache, /* Preserved: If we ever do asynchronous generation, this picked flag should be set here. */ // ec->picked = 1; - int array_idx = 0; - int count = MOD_lineart_chain_count(ec); + const int count = MOD_lineart_chain_count(ec); bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, color_idx, count, thickness, false); - float *stroke_data = MEM_callocN(sizeof(float) * count * GP_PRIM_DATABUF_SIZE, - "line art add stroke"); - - LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) { - stroke_data[array_idx] = eci->gpos[0]; - stroke_data[array_idx + 1] = eci->gpos[1]; - stroke_data[array_idx + 2] = eci->gpos[2]; - mul_m4_v3(gp_obmat_inverse, &stroke_data[array_idx]); - stroke_data[array_idx + 3] = 1; /* thickness. */ - stroke_data[array_idx + 4] = opacity; /* hardness?. */ - array_idx += 5; + int i; + LISTBASE_FOREACH_INDEX (LineartEdgeChainItem *, eci, &ec->chain, i) { + bGPDspoint *point = &gps->points[i]; + mul_v3_m4v3(&point->x, gp_obmat_inverse, eci->gpos); + point->pressure = 1.0f; + point->strength = opacity; } - BKE_gpencil_stroke_add_points(gps, stroke_data, count, mat); BKE_gpencil_dvert_ensure(gps); gps->mat_nr = max_ii(material_nr, 0); - MEM_freeN(stroke_data); - if (source_vgname && vgname) { Object *eval_ob = DEG_get_evaluated_object(depsgraph, ec->object_ref); int gpdg = -1; @@ -4301,7 +4290,7 @@ static void lineart_gpencil_generate(LineartCache *cache, int dindex = 0; Mesh *me = (Mesh *)eval_ob->data; if (me->dvert) { - LISTBASE_FOREACH (bDeformGroup *, db, &eval_ob->defbase) { + LISTBASE_FOREACH (bDeformGroup *, db, &me->vertex_group_names) { if ((!source_vgname) || strstr(db->name, source_vgname) == db->name) { if (match_output) { gpdg = BKE_object_defgroup_name_index(gpencil_object, db->name); diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h index 9d109320f09..70ff4a373dd 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h @@ -33,10 +33,10 @@ #include <math.h> #include <string.h> -struct LineartStaticMemPool; -struct LineartStaticMemPoolNode; struct LineartEdge; struct LineartRenderBuffer; +struct LineartStaticMemPool; +struct LineartStaticMemPoolNode; void *lineart_list_append_pointer_pool(ListBase *h, struct LineartStaticMemPool *smp, void *data); void *lineart_list_append_pointer_pool_sized(ListBase *h, diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index abb7330d292..b7dc3210c41 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -82,8 +82,8 @@ set(SRC intern/gpu_select_sample_query.cc intern/gpu_shader.cc intern/gpu_shader_builtin.c - intern/gpu_shader_log.cc intern/gpu_shader_interface.cc + intern/gpu_shader_log.cc intern/gpu_state.cc intern/gpu_texture.cc intern/gpu_uniform_buffer.cc @@ -103,8 +103,8 @@ set(SRC opengl/gl_index_buffer.cc opengl/gl_query.cc opengl/gl_shader.cc - opengl/gl_shader_log.cc opengl/gl_shader_interface.cc + opengl/gl_shader_log.cc opengl/gl_state.cc opengl/gl_texture.cc opengl/gl_uniform_buffer.cc diff --git a/source/blender/gpu/GPU_primitive.h b/source/blender/gpu/GPU_primitive.h index b1d70326b45..f64a673d461 100644 --- a/source/blender/gpu/GPU_primitive.h +++ b/source/blender/gpu/GPU_primitive.h @@ -57,7 +57,7 @@ typedef enum { } GPUPrimClass; /** - * TODO Improve error checking by validating that the shader is suited for this primitive type. + * TODO: Improve error checking by validating that the shader is suited for this primitive type. * GPUPrimClass GPU_primtype_class(GPUPrimType); * bool GPU_primtype_belongs_to_class(GPUPrimType, GPUPrimClass); */ diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 13d0139e406..43483916236 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -707,7 +707,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers, float fno[3]; short no_short[3]; - /* Note: Clockwise indices ordering, that's why we invert order here. */ + /* NOTE: Clockwise indices ordering, that's why we invert order here. */ normal_quad_v3(fno, co[3], co[2], co[1], co[0]); normal_float_to_short_v3(no_short, fno); @@ -916,7 +916,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers, return; } - /* TODO, make mask layer optional for bmesh buffer */ + /* TODO: make mask layer optional for bmesh buffer. */ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); /* Fill vertex buffer */ diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index a2072e504fd..d12cecd129e 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -810,7 +810,7 @@ static char *code_generate_geometry(GPUNodeGraph *graph, } LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) { - /* TODO let shader choose what to do depending on what the attribute is. */ + /* TODO: let shader choose what to do depending on what the attribute is. */ BLI_dynstr_appendf(ds, "dataAttrOut.var%d = dataAttrIn[vert].var%d;\\\n", attr->id, attr->id); } BLI_dynstr_append(ds, "}\n\n"); @@ -938,9 +938,9 @@ GPUPass *GPU_generate_pass(GPUMaterial *material, return pass; } -static int count_active_texture_sampler(GPUShader *shader, char *source) +static int count_active_texture_sampler(GPUShader *shader, const char *source) { - char *code = source; + const char *code = source; /* Remember this is per stage. */ GSet *sampler_ids = BLI_gset_int_new(__func__); diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index b5a437b46f7..943a6151ced 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -28,7 +28,7 @@ * - free can be called from any thread */ -/* TODO Create cmake option. */ +/* TODO: Create cmake option. */ #define WITH_OPENGL_BACKEND 1 #include "BLI_assert.h" @@ -99,7 +99,7 @@ Context *Context::get() GPUContext *GPU_context_create(void *ghost_window) { if (GPUBackend::get() == nullptr) { - /* TODO move where it make sense. */ + /* TODO: move where it make sense. */ GPU_backend_init(GPU_BACKEND_OPENGL); } @@ -182,7 +182,7 @@ void GPU_backend_init(eGPUBackendType backend_type) void GPU_backend_exit(void) { - /* TODO assert no resource left. Currently UI textures are still not freed in their context + /* TODO: assert no resource left. Currently UI textures are still not freed in their context * correctly. */ delete g_backend; g_backend = nullptr; diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 1293cc0953d..4bb13d01c2d 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -609,7 +609,13 @@ GPUOffScreen *GPU_offscreen_create( } if ((depth && !ofs->depth) || !ofs->color) { - BLI_snprintf(err_out, 256, "GPUTexture: Texture allocation failed."); + const char error[] = "GPUTexture: Texture allocation failed."; + if (err_out) { + BLI_snprintf(err_out, 256, error); + } + else { + fprintf(stderr, error); + } GPU_offscreen_free(ofs); return nullptr; } diff --git a/source/blender/gpu/intern/gpu_material_library.c b/source/blender/gpu/intern/gpu_material_library.c index 3c216c1a991..73a80c62bdc 100644 --- a/source/blender/gpu/intern/gpu_material_library.c +++ b/source/blender/gpu/intern/gpu_material_library.c @@ -684,7 +684,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = { static GHash *FUNCTION_HASH = NULL; -char *gpu_str_skip_token(char *str, char *token, int max) +const char *gpu_str_skip_token(const char *str, char *token, int max) { int len = 0; @@ -752,7 +752,7 @@ static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library) eGPUType type; GPUFunctionQual qual; int i; - char *code = library->code; + const char *code = library->code; while ((code = strstr(code, "void "))) { function = MEM_callocN(sizeof(GPUFunction), "GPUFunction"); diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h index da7b1636fa3..782d89d6f2a 100644 --- a/source/blender/gpu/intern/gpu_material_library.h +++ b/source/blender/gpu/intern/gpu_material_library.h @@ -62,5 +62,5 @@ char *gpu_material_library_generate_code(struct GSet *used_libraries, const char /* Code Parsing */ -char *gpu_str_skip_token(char *str, char *token, int max); +const char *gpu_str_skip_token(const char *str, char *token, int max); const char *gpu_data_type_to_string(const eGPUType type); diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index b220c60e979..585cb296bac 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -88,7 +88,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType name = outnode->name; input = outnode->inputs.first; - if ((STR_ELEM(name, "set_value", "set_rgb", "set_rgba")) && (input->type == type)) { + if (STR_ELEM(name, "set_value", "set_rgb", "set_rgba") && (input->type == type)) { input = MEM_dupallocN(outnode->inputs.first); if (input->link) { input->link->users++; @@ -174,7 +174,7 @@ static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type) case SOCK_RGBA: return "set_rgba"; default: - BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype"); + BLI_assert_msg(0, "No gpu function for non-supported eNodeSocketDatatype"); return NULL; } } @@ -259,7 +259,7 @@ static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **li output->link->link_type = GPU_NODE_LINK_OUTPUT; output->link->output = output; - /* note: the caller owns the reference to the link, GPUOutput + /* NOTE: the caller owns the reference to the link, GPUOutput * merely points to it, and if the node is destroyed it will * set that pointer to NULL */ } diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index 5c33066c720..9ee8a8b8d32 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -187,7 +187,7 @@ void GPU_point_size(float size) /* Programmable point size * - shaders set their own point size when enabled * - use GPU_point_size when disabled */ -/* TODO remove and use program point size everywhere */ +/* TODO: remove and use program point size everywhere. */ void GPU_program_point_size(bool enable) { StateManager *stack = Context::get()->state_manager; diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh index b79350a6506..b96b71a7ac4 100644 --- a/source/blender/gpu/intern/gpu_state_private.hh +++ b/source/blender/gpu/intern/gpu_state_private.hh @@ -96,7 +96,7 @@ inline GPUState operator~(const GPUState &a) union GPUStateMutable { struct { /* Viewport State */ - /** TODO remove */ + /** TODO: remove. */ float depth_range[2]; /** Positive if using program point size. */ /* TODO(fclem): should be passed as uniform to all shaders. */ diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index de5a9f95b65..6564cbda694 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -154,7 +154,7 @@ void Texture::attach_to(FrameBuffer *fb, GPUAttachmentType type) return; } } - BLI_assert(!"GPU: Error: Texture: Not enough attachment"); + BLI_assert_msg(0, "GPU: Error: Texture: Not enough attachment"); } void Texture::detach_from(FrameBuffer *fb) @@ -166,7 +166,7 @@ void Texture::detach_from(FrameBuffer *fb) return; } } - BLI_assert(!"GPU: Error: Texture: Framebuffer is not attached"); + BLI_assert_msg(0, "GPU: Error: Texture: Framebuffer is not attached"); } void Texture::update(eGPUDataFormat format, const void *data) @@ -600,7 +600,7 @@ void GPU_texture_py_reference_set(GPUTexture *tex, void **py_ref) } #endif -/* TODO remove */ +/* TODO: remove. */ int GPU_texture_opengl_bindcode(const GPUTexture *tex) { return reinterpret_cast<const Texture *>(tex)->gl_bindcode_get(); diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index a8f2e482bdd..2b8a5a5cc12 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -155,7 +155,7 @@ class Texture { void mip_size_get(int mip, int r_size[3]) const { - /* TODO assert if lvl is below the limit of 1px in each dimension. */ + /* TODO: assert if lvl is below the limit of 1px in each dimension. */ int div = 1 << mip; r_size[0] = max_ii(1, w_ / div); @@ -559,7 +559,7 @@ static inline eGPUTextureFormat to_texture_format(const GPUVertFormat *format) case GPU_COMP_I16: return GPU_RGBA16I; case GPU_COMP_U16: - /* Note: Checking the fetch mode to select the right GPU texture format. This can be + /* NOTE: Checking the fetch mode to select the right GPU texture format. This can be * added to other formats as well. */ switch (format->attrs[0].fetch_mode) { case GPU_FETCH_INT: diff --git a/source/blender/gpu/intern/gpu_uniform_buffer.cc b/source/blender/gpu/intern/gpu_uniform_buffer.cc index 3edb090d81c..3a9269d1753 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer.cc +++ b/source/blender/gpu/intern/gpu_uniform_buffer.cc @@ -114,11 +114,11 @@ static void buffer_from_list_inputs_sort(ListBase *inputs) if (input->type == GPU_MAT3) { /* Alignment for mat3 is not handled currently, so not supported */ - BLI_assert(!"mat3 not supported in UBO"); + BLI_assert_msg(0, "mat3 not supported in UBO"); continue; } if (input->type > MAX_UBO_GPU_TYPE) { - BLI_assert(!"GPU type not supported in UBO"); + BLI_assert_msg(0, "GPU type not supported in UBO"); continue; } diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc index 2c21d2bf9af..7ff68242c17 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.cc +++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc @@ -28,8 +28,8 @@ #include "gpu_backend.hh" #include "gpu_vertex_format_private.h" -#include "gl_vertex_buffer.hh" /* TODO remove */ -#include "gpu_context_private.hh" /* TODO remove */ +#include "gl_vertex_buffer.hh" /* TODO: remove. */ +#include "gpu_context_private.hh" /* TODO: remove. */ #include "gpu_vertex_buffer_private.hh" @@ -287,7 +287,7 @@ void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *verts_, uint a_idx, GPUVertBufRaw /* NOTE: Be careful when using this. The data needs to match the expected format. */ void *GPU_vertbuf_get_data(const GPUVertBuf *verts) { - /* TODO Assert that the format has no padding. */ + /* TODO: Assert that the format has no padding. */ return unwrap(verts)->data; } @@ -296,7 +296,7 @@ void *GPU_vertbuf_get_data(const GPUVertBuf *verts) void *GPU_vertbuf_steal_data(GPUVertBuf *verts_) { VertBuf *verts = unwrap(verts_); - /* TODO Assert that the format has no padding. */ + /* TODO: Assert that the format has no padding. */ BLI_assert(verts->data); void *data = verts->data; verts->data = nullptr; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index ddf31b6ffa7..96bf1ec40b0 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -248,7 +248,7 @@ void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) } } - BLI_assert(!"Too many draw engines enabled at the same time"); + BLI_assert_msg(0, "Too many draw engines enabled at the same time"); return NULL; } diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 1ae68d6813c..42b85da1f93 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -90,7 +90,7 @@ void GLBackend::platform_init() device |= GPU_DEVICE_INTEL_UHD; } } - else if ((strstr(renderer, "Mesa DRI R")) || + else if (strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) || (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) || @@ -365,8 +365,8 @@ static void detect_workarounds() (strstr(version, "Build 20.19.15.4285"))) { GCaps.use_main_context_workaround = true; } - /* See T70187: merging vertices fail. This has been tested from 18.2.2 till 19.3.0~dev of the - * Mesa driver */ + /* See T70187: merging vertices fail. This has been tested from `18.2.2` till `19.3.0~dev` + * of the Mesa driver */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && (strstr(version, "Mesa 18.") || strstr(version, "Mesa 19.0") || strstr(version, "Mesa 19.1") || strstr(version, "Mesa 19.2"))) { diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc index 6c9c6e10774..23654cb96f3 100644 --- a/source/blender/gpu/opengl/gl_context.cc +++ b/source/blender/gpu/opengl/gl_context.cc @@ -39,7 +39,7 @@ #include "gl_state.hh" #include "gl_uniform_buffer.hh" -#include "gl_backend.hh" /* TODO remove */ +#include "gl_backend.hh" /* TODO: remove. */ #include "gl_context.hh" using namespace blender; diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index ac42a950945..3e259235515 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -81,9 +81,11 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), return; } - if (TRIM_NVIDIA_BUFFER_INFO && - GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) && - STRPREFIX(message, "Buffer detailed info")) { + /* NOTE: callback function can be triggered during before the platform is initialized. + * In this case invoking `GPU_type_matches` would fail and + * therefore the message is checked before the platform matching. */ + if (TRIM_NVIDIA_BUFFER_INFO && STRPREFIX(message, "Buffer detailed info") && + GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL)) { /** Suppress buffer infos flooding the output. */ return; } diff --git a/source/blender/gpu/opengl/gl_drawlist.hh b/source/blender/gpu/opengl/gl_drawlist.hh index db4b9c03c3c..6f80fdd5a8a 100644 --- a/source/blender/gpu/opengl/gl_drawlist.hh +++ b/source/blender/gpu/opengl/gl_drawlist.hh @@ -72,7 +72,7 @@ class GLDrawList : public DrawList { GLuint buffer_id_; /** Length of whole the buffer (in byte). */ GLsizeiptr buffer_size_; - /** Offset of data_ inside the whole buffer (in byte). */ + /** Offset of `data_` inside the whole buffer (in byte). */ GLintptr data_offset_; /** To free the buffer_id_. */ diff --git a/source/blender/gpu/opengl/gl_framebuffer.cc b/source/blender/gpu/opengl/gl_framebuffer.cc index e87b22985bd..8da114d9270 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.cc +++ b/source/blender/gpu/opengl/gl_framebuffer.cc @@ -268,7 +268,7 @@ void GLFrameBuffer::bind(bool enabled_srgb) } if (context_ != GLContext::get()) { - BLI_assert(!"Trying to use the same frame-buffer in multiple context"); + BLI_assert_msg(0, "Trying to use the same frame-buffer in multiple context"); return; } @@ -379,7 +379,7 @@ void GLFrameBuffer::clear_attachment(GPUAttachmentType type, glClearBufferfv(GL_DEPTH, 0, &depth); } else { - BLI_assert(!"Unhandled data format"); + BLI_assert_msg(0, "Unhandled data format"); } } else { @@ -395,7 +395,7 @@ void GLFrameBuffer::clear_attachment(GPUAttachmentType type, glClearBufferiv(GL_COLOR, slot, (GLint *)clear_value); break; default: - BLI_assert(!"Unhandled data format"); + BLI_assert_msg(0, "Unhandled data format"); break; } } diff --git a/source/blender/gpu/opengl/gl_query.cc b/source/blender/gpu/opengl/gl_query.cc index 8a42719c665..da9770b4cc1 100644 --- a/source/blender/gpu/opengl/gl_query.cc +++ b/source/blender/gpu/opengl/gl_query.cc @@ -41,7 +41,7 @@ void GLQueryPool::init(GPUQueryType type) query_issued_ = 0; } -#if 0 /* TODO to avoid realloc of permanent query pool. */ +#if 0 /* TODO: to avoid realloc of permanent query pool. */ void GLQueryPool::reset(GPUQueryType type) { initialized_ = false; @@ -50,7 +50,7 @@ void GLQueryPool::reset(GPUQueryType type) void GLQueryPool::begin_query() { - /* TODO add assert about expected usage. */ + /* TODO: add assert about expected usage. */ while (query_issued_ >= query_ids_.size()) { int64_t prev_size = query_ids_.size(); query_ids_.resize(prev_size + QUERY_CHUNCK_LEN); @@ -61,7 +61,7 @@ void GLQueryPool::begin_query() void GLQueryPool::end_query() { - /* TODO add assert about expected usage. */ + /* TODO: add assert about expected usage. */ glEndQuery(gl_type_); } @@ -70,7 +70,7 @@ void GLQueryPool::get_occlusion_result(MutableSpan<uint32_t> r_values) BLI_assert(r_values.size() == query_issued_); for (int i = 0; i < query_issued_; i++) { - /* Note: This is a sync point. */ + /* NOTE: This is a sync point. */ glGetQueryObjectuiv(query_ids_[i], GL_QUERY_RESULT, &r_values[i]); } } diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc index b837eae4871..1106e3dab50 100644 --- a/source/blender/gpu/opengl/gl_state.cc +++ b/source/blender/gpu/opengl/gl_state.cc @@ -131,7 +131,7 @@ void GLStateManager::set_state(const GPUState &state) set_shadow_bias(state.shadow_bias); } - /* TODO remove */ + /* TODO: remove. */ if (changed.polygon_smooth) { if (state.polygon_smooth) { glEnable(GL_POLYGON_SMOOTH); @@ -156,7 +156,7 @@ void GLStateManager::set_mutable_state(const GPUStateMutable &state) { GPUStateMutable changed = state ^ current_mutable_; - /* TODO remove, should be uniform. */ + /* TODO: remove, should be uniform. */ if (float_as_uint(changed.point_size) != 0) { if (state.point_size > 0.0f) { glEnable(GL_PROGRAM_POINT_SIZE); @@ -168,12 +168,12 @@ void GLStateManager::set_mutable_state(const GPUStateMutable &state) } if (changed.line_width != 0) { - /* TODO remove, should use wide line shader. */ + /* TODO: remove, should use wide line shader. */ glLineWidth(clamp_f(state.line_width, line_width_range_[0], line_width_range_[1])); } if (changed.depth_range[0] != 0 || changed.depth_range[1] != 0) { - /* TODO remove, should modify the projection matrix instead. */ + /* TODO: remove, should modify the projection matrix instead. */ glDepthRange(UNPACK2(state.depth_range)); } diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc index ddc45a6a904..db1fda63c28 100644 --- a/source/blender/gpu/opengl/gl_texture.cc +++ b/source/blender/gpu/opengl/gl_texture.cc @@ -32,7 +32,7 @@ #include "gl_backend.hh" #include "gl_debug.hh" #include "gl_state.hh" -#include "gpu_vertex_buffer_private.hh" /* TODO should be `gl_vertex_buffer.hh` */ +#include "gpu_vertex_buffer_private.hh" /* TODO: should be `gl_vertex_buffer.hh`. */ #include "gl_texture.hh" @@ -347,7 +347,7 @@ void GLTexture::copy_to(Texture *dst_) BLI_assert((dst->w_ == src->w_) && (dst->h_ == src->h_) && (dst->d_ == src->d_)); BLI_assert(dst->format_ == src->format_); BLI_assert(dst->type_ == src->type_); - /* TODO support array / 3D textures. */ + /* TODO: support array / 3D textures. */ BLI_assert(dst->d_ == 0); if (GLContext::copy_image_support) { diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl index 9ce2a1be015..aae7f641af8 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl @@ -18,6 +18,7 @@ in vec2 P2; in vec2 P3; in ivec4 colid_doarrow; in ivec2 domuted; +in float dim_factor; uniform vec4 colors[6]; @@ -39,6 +40,7 @@ uniform vec2 bezierPts[4]; uniform vec4 colors[3]; uniform bool doArrow; uniform bool doMuted; +uniform float dim_factor; # define colShadow colors[0] # define colStart colors[1] @@ -98,6 +100,8 @@ void main(void) } } + finalColor[3] *= dim_factor; + /* Expand into a line */ gl_Position.xy += exp_axis * expandSize * expand_dist; diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl index d33465fa846..40e46bc250c 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl @@ -1,4 +1,4 @@ -/* TODO : clean this ifdef mess */ +/* TODO: clean this `ifdef` mess. */ void world_normals_get(out vec3 N) { #ifndef VOLUMETRICS diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index 051bc193a42..0ee8b3057d2 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -47,7 +47,7 @@ /* ********************** THE IK SOLVER ******************* */ /* allocates PoseTree, and links that to root bone/channel */ -/* Note: detecting the IK chain is duplicate code... +/* NOTE: detecting the IK chain is duplicate code... * in drawarmature.c and in transform_conversions.c */ static void initialize_posetree(struct Object *UNUSED(ob), bPoseChannel *pchan_tip) { diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 2cfce7b1ba0..d527aca184c 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -69,8 +69,8 @@ extern "C" { * \attention defined in ??? */ struct ImBuf; -struct rcti; struct rctf; +struct rcti; /** * diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index ad72f373d12..70bb70ec4fa 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -395,9 +395,8 @@ bool imb_savebmp(ImBuf *ibuf, const char *filepath, int UNUSED(flags)) } } } - if (ofile) { - fflush(ofile); - fclose(ofile); - } + + fflush(ofile); + fclose(ofile); return 1; } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 71e513fb405..2cc44ebc67b 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1542,7 +1542,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, rgba_uchar_to_float(fp, cp); } else { - BLI_assert(!"Buffers of 3 or 4 channels are only supported here"); + BLI_assert_msg(0, "Buffers of 3 or 4 channels are only supported here"); } } @@ -3437,7 +3437,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, pixel[0] = linear_buffer[linear_index]; } else { - BLI_assert(!"Unsupported number of channels in partial buffer update"); + BLI_assert_msg(0, "Unsupported number of channels in partial buffer update"); } } else if (byte_buffer) { diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index e767cb14b1a..1729a9a64f8 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -44,7 +44,7 @@ extern "C" { bool imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/) { - return false; /* todo: finish this function */ + return false; /* TODO: finish this function. */ /* check image buffer */ if (ibuf == nullptr) { diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 71137a408d2..27195b294d6 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -357,7 +357,7 @@ int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size) case IMB_PROXY_100: return 3; default: - BLI_assert(!"Unhandled proxy size enum!"); + BLI_assert_msg(0, "Unhandled proxy size enum!"); return -1; } } @@ -376,7 +376,7 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc) case IMB_TC_RECORD_RUN_NO_GAPS: return 3; default: - BLI_assert(!"Unhandled timecode type enum!"); + BLI_assert_msg(0, "Unhandled timecode type enum!"); return -1; } } diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 65c25194477..0941338160d 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -156,7 +156,7 @@ static ImBuf *imb_oiio_load_image_float( /* ImBuf always needs 4 channels */ fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f); - /* Note: Photoshop 16 bit files never has alpha with it, + /* NOTE: Photoshop 16 bit files never has alpha with it, * so no need to handle associated/unassociated alpha. */ return ibuf; } diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 4a964c64917..79c2583f983 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -1195,22 +1195,9 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx) { uchar *rect, *_newrect = NULL, *newrect; float *rectf, *_newrectf = NULL, *newrectf; - float sample, add; - float val_a, nval_a, diff_a; - float val_b, nval_b, diff_b; - float val_g, nval_g, diff_g; - float val_r, nval_r, diff_r; - float val_af, nval_af, diff_af; - float val_bf, nval_bf, diff_bf; - float val_gf, nval_gf, diff_gf; - float val_rf, nval_rf, diff_rf; int x, y; bool do_rect = false, do_float = false; - val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; - val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; - val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; - val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; if (ibuf == NULL) { return NULL; } @@ -1236,119 +1223,158 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx) } } - add = (ibuf->x - 1.001) / (newx - 1.0); - rect = (uchar *)ibuf->rect; rectf = (float *)ibuf->rect_float; newrect = _newrect; newrectf = _newrectf; - for (y = ibuf->y; y > 0; y--) { - - sample = 0; - + /* Special case, copy all columns, needed since the scaling logic assumes there is at least + * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */ + if (UNLIKELY(ibuf->x == 1)) { if (do_rect) { - val_a = rect[0]; - nval_a = rect[4]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = rect[1]; - nval_b = rect[5]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = rect[2]; - nval_g = rect[6]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = rect[3]; - nval_r = rect[7]; - diff_r = nval_r - val_r; - val_r += 0.5f; - - rect += 8; + for (y = ibuf->y; y > 0; y--) { + for (x = newx; x > 0; x--) { + memcpy(newrect, rect, sizeof(char[4])); + newrect += 4; + } + rect += 4; + } } if (do_float) { - val_af = rectf[0]; - nval_af = rectf[4]; - diff_af = nval_af - val_af; + for (y = ibuf->y; y > 0; y--) { + for (x = newx; x > 0; x--) { + memcpy(newrectf, rectf, sizeof(float[4])); + newrectf += 4; + } + rectf += 4; + } + } + } + else { + const float add = (ibuf->x - 1.001) / (newx - 1.0); + float sample; - val_bf = rectf[1]; - nval_bf = rectf[5]; - diff_bf = nval_bf - val_bf; + float val_a, nval_a, diff_a; + float val_b, nval_b, diff_b; + float val_g, nval_g, diff_g; + float val_r, nval_r, diff_r; + float val_af, nval_af, diff_af; + float val_bf, nval_bf, diff_bf; + float val_gf, nval_gf, diff_gf; + float val_rf, nval_rf, diff_rf; - val_gf = rectf[2]; - nval_gf = rectf[6]; - diff_gf = nval_gf - val_gf; + val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; + val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; + val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; + val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; - val_rf = rectf[3]; - nval_rf = rectf[7]; - diff_rf = nval_rf - val_rf; + for (y = ibuf->y; y > 0; y--) { - rectf += 8; - } - for (x = newx; x > 0; x--) { - if (sample >= 1.0f) { - sample -= 1.0f; + sample = 0; - if (do_rect) { - val_a = nval_a; - nval_a = rect[0]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = nval_b; - nval_b = rect[1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = nval_g; - nval_g = rect[2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = nval_r; - nval_r = rect[3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - rect += 4; - } - if (do_float) { - val_af = nval_af; - nval_af = rectf[0]; - diff_af = nval_af - val_af; + if (do_rect) { + val_a = rect[0]; + nval_a = rect[4]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = rect[1]; + nval_b = rect[5]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = rect[2]; + nval_g = rect[6]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = rect[3]; + nval_r = rect[7]; + diff_r = nval_r - val_r; + val_r += 0.5f; + + rect += 8; + } + if (do_float) { + val_af = rectf[0]; + nval_af = rectf[4]; + diff_af = nval_af - val_af; - val_bf = nval_bf; - nval_bf = rectf[1]; - diff_bf = nval_bf - val_bf; + val_bf = rectf[1]; + nval_bf = rectf[5]; + diff_bf = nval_bf - val_bf; - val_gf = nval_gf; - nval_gf = rectf[2]; - diff_gf = nval_gf - val_gf; + val_gf = rectf[2]; + nval_gf = rectf[6]; + diff_gf = nval_gf - val_gf; - val_rf = nval_rf; - nval_rf = rectf[3]; - diff_rf = nval_rf - val_rf; - rectf += 4; - } - } - if (do_rect) { - newrect[0] = val_a + sample * diff_a; - newrect[1] = val_b + sample * diff_b; - newrect[2] = val_g + sample * diff_g; - newrect[3] = val_r + sample * diff_r; - newrect += 4; + val_rf = rectf[3]; + nval_rf = rectf[7]; + diff_rf = nval_rf - val_rf; + + rectf += 8; } - if (do_float) { - newrectf[0] = val_af + sample * diff_af; - newrectf[1] = val_bf + sample * diff_bf; - newrectf[2] = val_gf + sample * diff_gf; - newrectf[3] = val_rf + sample * diff_rf; - newrectf += 4; + for (x = newx; x > 0; x--) { + if (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + val_a = nval_a; + nval_a = rect[0]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = nval_b; + nval_b = rect[1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = nval_g; + nval_g = rect[2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = nval_r; + nval_r = rect[3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + rect += 4; + } + if (do_float) { + val_af = nval_af; + nval_af = rectf[0]; + diff_af = nval_af - val_af; + + val_bf = nval_bf; + nval_bf = rectf[1]; + diff_bf = nval_bf - val_bf; + + val_gf = nval_gf; + nval_gf = rectf[2]; + diff_gf = nval_gf - val_gf; + + val_rf = nval_rf; + nval_rf = rectf[3]; + diff_rf = nval_rf - val_rf; + rectf += 4; + } + } + if (do_rect) { + newrect[0] = val_a + sample * diff_a; + newrect[1] = val_b + sample * diff_b; + newrect[2] = val_g + sample * diff_g; + newrect[3] = val_r + sample * diff_r; + newrect += 4; + } + if (do_float) { + newrectf[0] = val_af + sample * diff_af; + newrectf[1] = val_bf + sample * diff_bf; + newrectf[2] = val_gf + sample * diff_gf; + newrectf[3] = val_rf + sample * diff_rf; + newrectf += 4; + } + sample += add; } - sample += add; } } @@ -1371,22 +1397,9 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy) { uchar *rect, *_newrect = NULL, *newrect; float *rectf, *_newrectf = NULL, *newrectf; - float sample, add; - float val_a, nval_a, diff_a; - float val_b, nval_b, diff_b; - float val_g, nval_g, diff_g; - float val_r, nval_r, diff_r; - float val_af, nval_af, diff_af; - float val_bf, nval_bf, diff_bf; - float val_gf, nval_gf, diff_gf; - float val_rf, nval_rf, diff_rf; int x, y, skipx; bool do_rect = false, do_float = false; - val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; - val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; - val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; - val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; if (ibuf == NULL) { return NULL; } @@ -1412,126 +1425,159 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy) } } - add = (ibuf->y - 1.001) / (newy - 1.0); - skipx = 4 * ibuf->x; - rect = (uchar *)ibuf->rect; rectf = (float *)ibuf->rect_float; newrect = _newrect; newrectf = _newrectf; - for (x = ibuf->x; x > 0; x--) { + skipx = 4 * ibuf->x; - sample = 0; + /* Special case, copy all rows, needed since the scaling logic assumes there is at least + * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */ + if (UNLIKELY(ibuf->y == 1)) { if (do_rect) { - rect = ((uchar *)ibuf->rect) + 4 * (x - 1); - newrect = _newrect + 4 * (x - 1); - - val_a = rect[0]; - nval_a = rect[skipx]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = rect[1]; - nval_b = rect[skipx + 1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = rect[2]; - nval_g = rect[skipx + 2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = rect[3]; - nval_r = rect[skipx + 3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - - rect += 2 * skipx; + for (y = newy; y > 0; y--) { + memcpy(newrect, rect, sizeof(char) * skipx); + newrect += skipx; + } } if (do_float) { - rectf = ibuf->rect_float + 4 * (x - 1); - newrectf = _newrectf + 4 * (x - 1); - - val_af = rectf[0]; - nval_af = rectf[skipx]; - diff_af = nval_af - val_af; + for (y = newy; y > 0; y--) { + memcpy(newrectf, rectf, sizeof(float) * skipx); + newrectf += skipx; + } + } + } + else { + const float add = (ibuf->y - 1.001) / (newy - 1.0); + float sample; + + float val_a, nval_a, diff_a; + float val_b, nval_b, diff_b; + float val_g, nval_g, diff_g; + float val_r, nval_r, diff_r; + float val_af, nval_af, diff_af; + float val_bf, nval_bf, diff_bf; + float val_gf, nval_gf, diff_gf; + float val_rf, nval_rf, diff_rf; + + val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; + val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; + val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; + val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; + + for (x = ibuf->x; x > 0; x--) { + sample = 0; + if (do_rect) { + rect = ((uchar *)ibuf->rect) + 4 * (x - 1); + newrect = _newrect + 4 * (x - 1); + + val_a = rect[0]; + nval_a = rect[skipx]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = rect[1]; + nval_b = rect[skipx + 1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = rect[2]; + nval_g = rect[skipx + 2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = rect[3]; + nval_r = rect[skipx + 3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + + rect += 2 * skipx; + } + if (do_float) { + rectf = ibuf->rect_float + 4 * (x - 1); + newrectf = _newrectf + 4 * (x - 1); - val_bf = rectf[1]; - nval_bf = rectf[skipx + 1]; - diff_bf = nval_bf - val_bf; + val_af = rectf[0]; + nval_af = rectf[skipx]; + diff_af = nval_af - val_af; - val_gf = rectf[2]; - nval_gf = rectf[skipx + 2]; - diff_gf = nval_gf - val_gf; + val_bf = rectf[1]; + nval_bf = rectf[skipx + 1]; + diff_bf = nval_bf - val_bf; - val_rf = rectf[3]; - nval_rf = rectf[skipx + 3]; - diff_rf = nval_rf - val_rf; + val_gf = rectf[2]; + nval_gf = rectf[skipx + 2]; + diff_gf = nval_gf - val_gf; - rectf += 2 * skipx; - } + val_rf = rectf[3]; + nval_rf = rectf[skipx + 3]; + diff_rf = nval_rf - val_rf; - for (y = newy; y > 0; y--) { - if (sample >= 1.0f) { - sample -= 1.0f; + rectf += 2 * skipx; + } + for (y = newy; y > 0; y--) { + if (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + val_a = nval_a; + nval_a = rect[0]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = nval_b; + nval_b = rect[1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = nval_g; + nval_g = rect[2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = nval_r; + nval_r = rect[3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + rect += skipx; + } + if (do_float) { + val_af = nval_af; + nval_af = rectf[0]; + diff_af = nval_af - val_af; + + val_bf = nval_bf; + nval_bf = rectf[1]; + diff_bf = nval_bf - val_bf; + + val_gf = nval_gf; + nval_gf = rectf[2]; + diff_gf = nval_gf - val_gf; + + val_rf = nval_rf; + nval_rf = rectf[3]; + diff_rf = nval_rf - val_rf; + rectf += skipx; + } + } if (do_rect) { - val_a = nval_a; - nval_a = rect[0]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = nval_b; - nval_b = rect[1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = nval_g; - nval_g = rect[2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = nval_r; - nval_r = rect[3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - rect += skipx; + newrect[0] = val_a + sample * diff_a; + newrect[1] = val_b + sample * diff_b; + newrect[2] = val_g + sample * diff_g; + newrect[3] = val_r + sample * diff_r; + newrect += skipx; } if (do_float) { - val_af = nval_af; - nval_af = rectf[0]; - diff_af = nval_af - val_af; - - val_bf = nval_bf; - nval_bf = rectf[1]; - diff_bf = nval_bf - val_bf; - - val_gf = nval_gf; - nval_gf = rectf[2]; - diff_gf = nval_gf - val_gf; - - val_rf = nval_rf; - nval_rf = rectf[3]; - diff_rf = nval_rf - val_rf; - rectf += skipx; + newrectf[0] = val_af + sample * diff_af; + newrectf[1] = val_bf + sample * diff_bf; + newrectf[2] = val_gf + sample * diff_gf; + newrectf[3] = val_rf + sample * diff_rf; + newrectf += skipx; } + sample += add; } - if (do_rect) { - newrect[0] = val_a + sample * diff_a; - newrect[1] = val_b + sample * diff_b; - newrect[2] = val_g + sample * diff_g; - newrect[3] = val_r + sample * diff_r; - newrect += skipx; - } - if (do_float) { - newrectf[0] = val_af + sample * diff_af; - newrectf[1] = val_bf + sample * diff_bf; - newrectf[2] = val_gf + sample * diff_gf; - newrectf[3] = val_rf + sample * diff_rf; - newrectf += skipx; - } - sample += add; } } @@ -1620,6 +1666,8 @@ static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy) */ bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) { + BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!"); + if (ibuf == NULL) { return false; } @@ -1666,6 +1714,8 @@ struct imbufRGBA { */ bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) { + BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!"); + unsigned int *rect, *_newrect, *newrect; struct imbufRGBA *rectf, *_newrectf, *newrectf; int x, y; @@ -1838,6 +1888,8 @@ static void *do_scale_thread(void *data_v) void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy) { + BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!"); + ScaleTreadInitData init_data = {NULL}; /* prepare initialization data */ diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index 2a7a189dd2b..8ed0b8b535c 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -117,7 +117,7 @@ static int tga_out4(unsigned int data, FILE *file) uchar *p; p = (uchar *)&data; - /* order = bgra */ + /* Order = BGRA. */ if (putc(p[2], file) == EOF) { return EOF; } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index db80d168e53..19f34a6aacd 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -172,7 +172,7 @@ static const unsigned char acceptable[96] = { static const char hex[17] = "0123456789abcdef"; -/* Note: This escape function works on file: URIs, but if you want to +/* NOTE: This escape function works on file: URIs, but if you want to * escape something else, please read RFC-2396 */ static void escape_uri_string(const char *string, char *escaped_string, diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index eb518828913..759f96af7c8 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -56,7 +56,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const return ima; } - /* Note: we should handle all previews for a same group at once, would avoid reopening + /* NOTE: we should handle all previews for a same group at once, would avoid reopening * `.blend` file for each and every ID. However, this adds some complexity, * so keep it for later. */ names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, false, &nnames); diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h index 5664a43233a..3d1391ac2a4 100644 --- a/source/blender/io/alembic/ABC_alembic.h +++ b/source/blender/io/alembic/ABC_alembic.h @@ -19,6 +19,8 @@ * \ingroup balembic */ +#include "DEG_depsgraph.h" + #ifdef __cplusplus extern "C" { #endif @@ -54,7 +56,6 @@ struct AlembicExportParams { bool curves_as_mesh; bool flatten_hierarchy; bool visible_objects_only; - bool renderable_only; bool face_sets; bool use_subdiv_schema; bool packuv; @@ -63,6 +64,7 @@ struct AlembicExportParams { bool export_particles; bool export_custom_properties; bool use_instancing; + enum eEvaluationMode evaluation_mode; /* See MOD_TRIANGULATE_NGON_xxx and MOD_TRIANGULATE_QUAD_xxx * in DNA_modifier_types.h */ diff --git a/source/blender/io/alembic/exporter/abc_custom_props.cc b/source/blender/io/alembic/exporter/abc_custom_props.cc index f5593e7ee30..4ea2fd03fff 100644 --- a/source/blender/io/alembic/exporter/abc_custom_props.cc +++ b/source/blender/io/alembic/exporter/abc_custom_props.cc @@ -141,7 +141,7 @@ void CustomPropertiesExporter::write_idparray(const IDProperty *idp_array) continue; } std::cerr << "Custom property " << idp_array->name << " has elements of varying type"; - BLI_assert(!"Mixed type IDP_ARRAY custom property found"); + BLI_assert_msg(0, "Mixed type IDP_ARRAY custom property found"); } #endif diff --git a/source/blender/io/alembic/exporter/abc_export_capi.cc b/source/blender/io/alembic/exporter/abc_export_capi.cc index 5b8998a0b1a..efe04d64cc3 100644 --- a/source/blender/io/alembic/exporter/abc_export_capi.cc +++ b/source/blender/io/alembic/exporter/abc_export_capi.cc @@ -213,8 +213,7 @@ bool ABC_export(Scene *scene, job->export_ok = false; BLI_strncpy(job->filename, filepath, sizeof(job->filename)); - job->depsgraph = DEG_graph_new( - job->bmain, scene, view_layer, DAG_EVAL_RENDER /* TODO(Sybren): params->evaluation_mode */); + job->depsgraph = DEG_graph_new(job->bmain, scene, view_layer, params->evaluation_mode); job->params = *params; bool export_ok = false; diff --git a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc index e2be241c144..174b2abb90f 100644 --- a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc +++ b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc @@ -229,7 +229,7 @@ ABCAbstractWriter *ABCHierarchyIterator::create_data_writer_for_object_type( case OB_GPENCIL: return nullptr; case OB_TYPE_MAX: - BLI_assert(!"OB_TYPE_MAX should not be used"); + BLI_assert_msg(0, "OB_TYPE_MAX should not be used"); return nullptr; } diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.cc b/source/blender/io/alembic/exporter/abc_writer_abstract.cc index 27b5c2fa2a4..910e04f3bf5 100644 --- a/source/blender/io/alembic/exporter/abc_writer_abstract.cc +++ b/source/blender/io/alembic/exporter/abc_writer_abstract.cc @@ -137,7 +137,7 @@ void ABCAbstractWriter::update_bounding_box(Object *object) void ABCAbstractWriter::write_visibility(const HierarchyContext &context) { - const bool is_visible = context.is_object_visible(DAG_EVAL_RENDER); + const bool is_visible = context.is_object_visible(args_.export_params->evaluation_mode); Alembic::Abc::OObject abc_object = get_alembic_object(); if (!abc_visibility_.valid()) { diff --git a/source/blender/io/alembic/exporter/abc_writer_instance.cc b/source/blender/io/alembic/exporter/abc_writer_instance.cc index 1737e8c091e..353705f2c1d 100644 --- a/source/blender/io/alembic/exporter/abc_writer_instance.cc +++ b/source/blender/io/alembic/exporter/abc_writer_instance.cc @@ -59,7 +59,7 @@ Alembic::Abc::OCompoundProperty ABCInstanceWriter::abc_prop_for_custom_props() OObject ABCInstanceWriter::get_alembic_object() const { /* There is no OObject for an instance. */ - BLI_assert(!"ABCInstanceWriter cannot return its Alembic OObject"); + BLI_assert_msg(0, "ABCInstanceWriter cannot return its Alembic OObject"); return OObject(); } diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index fd7db005dd2..7ffb61e1d1b 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -162,7 +162,7 @@ ModifierData *ABCGenericMeshWriter::get_liquid_sim_modifier(Scene *scene, Object bool ABCGenericMeshWriter::is_supported(const HierarchyContext *context) const { if (args_.export_params->visible_objects_only) { - return context->is_object_visible(DAG_EVAL_RENDER); + return context->is_object_visible(args_.export_params->evaluation_mode); } return true; } diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 79f34f671c7..c05df7f1ff5 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -565,7 +565,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, nullptr); if (read_mesh != mesh) { - /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_nomain_to_mesh() */ + /* XXX FIXME: after 2.80; mesh->flag isn't copied by #BKE_mesh_nomain_to_mesh(). */ /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ short autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); diff --git a/source/blender/io/collada/AnimationExporter.cpp b/source/blender/io/collada/AnimationExporter.cpp index 73952b06bc9..9ba59c0414d 100644 --- a/source/blender/io/collada/AnimationExporter.cpp +++ b/source/blender/io/collada/AnimationExporter.cpp @@ -135,7 +135,7 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler) container_is_open = open_animation_container(container_is_open, ob); /* Now take care of the Object Animations - * Note: For Armatures the skeletal animation has already been exported (see above) + * NOTE: For Armatures the skeletal animation has already been exported (see above) * However Armatures also can have Object animation. */ bool export_as_matrix = this->export_settings.get_animation_transformation_type() == @@ -168,7 +168,7 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler) /* * Export all animation FCurves of an Object. * - * Note: This uses the keyframes as sample points, + * NOTE: This uses the keyframes as sample points, * and exports "baked keyframes" while keeping the tangent information * of the FCurves intact. This works for simple cases, but breaks * especially when negative scales are involved in the animation. @@ -337,7 +337,7 @@ void AnimationExporter::export_curve_animation(Object *ob, BCAnimationCurve &cur /* * Some curves can not be exported as is and need some conversion * For more information see implementation of get_modified_export_curve() - * note: if mcurve is not NULL then it must be deleted at end of this method; + * NOTE: if mcurve is not NULL then it must be deleted at end of this method; */ int channel_index = curve.get_channel_index(); @@ -775,7 +775,7 @@ std::string AnimationExporter::get_collada_name(std::string channel_type) const { /* * Translation table to map FCurve animation types to Collada animation. - * Todo: Maybe we can keep the names from the fcurves here instead of + * TODO: Maybe we can keep the names from the fcurves here instead of * mapping. However this is what i found in the old code. So keep * this map for now. */ @@ -799,9 +799,9 @@ std::string AnimationExporter::get_collada_name(std::string channel_type) const {"spot_size", "falloff_angle"}, {"fall_off_exponent", "falloff_exponent"}, {"spot_blend", "falloff_exponent"}, - /* Special blender profile (todo: make this more elegant). */ + /* Special blender profile (TODO: make this more elegant). */ {"blender/blender_dist", "blender/blender_dist"}, - /* Special blender profile (todo: make this more elegant). */ + /* Special blender profile (TODO: make this more elegant). */ {"distance", "blender/blender_dist"}, /* Cameras */ diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index 49f28325257..626e4258239 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -164,7 +164,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) void AnimationImporter::fcurve_deg_to_rad(FCurve *cu) { for (unsigned int i = 0; i < cu->totvert; i++) { - /* TODO convert handles too */ + /* TODO: convert handles too. */ cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f); cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f); cu->bezt[i].vec[2][1] *= DEG2RADF(1.0f); @@ -174,7 +174,7 @@ void AnimationImporter::fcurve_deg_to_rad(FCurve *cu) void AnimationImporter::fcurve_scale(FCurve *cu, int scale) { for (unsigned int i = 0; i < cu->totvert; i++) { - /* TODO convert handles too */ + /* TODO: convert handles too. */ cu->bezt[i].vec[1][1] *= scale; cu->bezt[i].vec[0][1] *= scale; cu->bezt[i].vec[2][1] *= scale; @@ -305,7 +305,7 @@ bool AnimationImporter::write_animation(const COLLADAFW::Animation *anim) animation_to_fcurves(curve); break; default: - /* TODO there are also CARDINAL, HERMITE, BSPLINE and STEP types. */ + /* TODO: there are also CARDINAL, HERMITE, BSPLINE and STEP types. */ fprintf(stderr, "CARDINAL, HERMITE and BSPLINE anim interpolation types not supported yet.\n"); break; @@ -624,7 +624,7 @@ void AnimationImporter::Assign_transform_animations( } } break; case COLLADAFW::AnimationList::AXISANGLE: - /* TODO convert axis-angle to quat? or XYZ? */ + /* TODO: convert axis-angle to quat? or XYZ? */ default: unused_fcurve(curves); fprintf(stderr, @@ -972,7 +972,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, /* * This function returns the aspect ration from the Collada camera. * - * Note:COLLADA allows to specify either XFov, or YFov alone. + * NOTE:COLLADA allows to specify either XFov, or YFov alone. * In that case the aspect ratio can be determined from * the viewport aspect ratio (which is 1:1 ?) * XXX: check this: its probably wrong! @@ -1979,7 +1979,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, return false; } - /* TODO support other animclasses */ + /* TODO: support other animclasses. */ if (animclass != COLLADAFW::AnimationList::ANGLE) { report_class_type_unsupported(path, animclass, type); return false; diff --git a/source/blender/io/collada/BCAnimationCurve.h b/source/blender/io/collada/BCAnimationCurve.h index a1597cd47be..36b2a5e8509 100644 --- a/source/blender/io/collada/BCAnimationCurve.h +++ b/source/blender/io/collada/BCAnimationCurve.h @@ -116,7 +116,7 @@ class BCAnimationCurve { bool is_keyframe(int frame); void adjust_range(int frame); - std::string get_animation_name(Object *ob) const; /* xxx: this is collada specific */ + std::string get_animation_name(Object *ob) const; /* XXX: this is COLLADA specific. */ std::string get_channel_target() const; std::string get_channel_type() const; std::string get_channel_posebone() const; /* returns "" if channel is not a bone channel */ diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp index 6f0d422dbe2..e61ed47adee 100644 --- a/source/blender/io/collada/ControllerExporter.cpp +++ b/source/blender/io/collada/ControllerExporter.cpp @@ -29,6 +29,7 @@ #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_deform.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_lib_id.h" @@ -194,9 +195,9 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) add_bind_shape_mat(ob); - std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id); - std::string inv_bind_mat_source_id = add_inv_bind_mats_source( - ob_arm, &ob->defbase, controller_id); + const ListBase *defbase = BKE_object_defgroup_list(ob); + std::string joints_source_id = add_joints_source(ob_arm, defbase, controller_id); + std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, defbase, controller_id); std::list<int> vcounts; std::list<int> joints; @@ -207,9 +208,9 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) /* def group index -> joint index */ std::vector<int> joint_index_by_def_index; - bDeformGroup *def; + const bDeformGroup *def; - for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) { + for (def = (const bDeformGroup *)defbase->first, i = 0, j = 0; def; def = def->next, i++) { if (is_bone_defgroup(ob_arm, def)) { joint_index_by_def_index.push_back(j++); } @@ -269,7 +270,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) } std::string weights_source_id = add_weights_source(me, controller_id, weights); - add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); + add_joints_element(defbase, joints_source_id, inv_bind_mat_source_id); add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); BKE_id_free(nullptr, me); @@ -392,7 +393,7 @@ void ControllerExporter::add_weight_extras(Key *key) } } -void ControllerExporter::add_joints_element(ListBase *defbase, +void ControllerExporter::add_joints_element(const ListBase *defbase, const std::string &joints_source_id, const std::string &inv_bind_mat_source_id) { @@ -431,7 +432,7 @@ void ControllerExporter::add_bind_shape_mat(Object *ob) } std::string ControllerExporter::add_joints_source(Object *ob_arm, - ListBase *defbase, + const ListBase *defbase, const std::string &controller_id) { std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX; @@ -468,7 +469,7 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, } std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, - ListBase *defbase, + const ListBase *defbase, const std::string &controller_id) { std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX; @@ -568,13 +569,13 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, return source_id; } -Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def) +Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, const bDeformGroup *def) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name); return pchan ? pchan->bone : nullptr; } -bool ControllerExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def) +bool ControllerExporter::is_bone_defgroup(Object *ob_arm, const bDeformGroup *def) { return get_bone_from_defgroup(ob_arm, def) != nullptr; } diff --git a/source/blender/io/collada/ControllerExporter.h b/source/blender/io/collada/ControllerExporter.h index 6a377a4119e..0aec9e8d179 100644 --- a/source/blender/io/collada/ControllerExporter.h +++ b/source/blender/io/collada/ControllerExporter.h @@ -97,7 +97,7 @@ class ControllerExporter : public COLLADASW::LibraryControllers, void export_morph_controller(Object *ob, Key *key); - void add_joints_element(ListBase *defbase, + void add_joints_element(const ListBase *defbase, const std::string &joints_source_id, const std::string &inv_bind_mat_source_id); @@ -110,16 +110,16 @@ class ControllerExporter : public COLLADASW::LibraryControllers, void add_weight_extras(Key *key); std::string add_joints_source(Object *ob_arm, - ListBase *defbase, + const ListBase *defbase, const std::string &controller_id); std::string add_inv_bind_mats_source(Object *ob_arm, - ListBase *defbase, + const ListBase *defbase, const std::string &controller_id); - Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def); + Bone *get_bone_from_defgroup(Object *ob_arm, const bDeformGroup *def); - bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def); + bool is_bone_defgroup(Object *ob_arm, const bDeformGroup *def); std::string add_weights_source(Mesh *me, const std::string &controller_id, diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index beadfc98c74..35bdc0a4e06 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -145,7 +145,7 @@ bool DocumentImporter::import() return false; } - /** TODO set up scene graph and such here */ + /** TODO: set up scene graph and such here. */ mImportStage = Fetching_Controller_data; COLLADASaxFWL::Loader loader2; COLLADAFW::Root root2(&loader2, this); @@ -189,7 +189,7 @@ void DocumentImporter::finish() std::vector<Object *> *objects_to_scale = new std::vector<Object *>(); - /** TODO Break up and put into 2-pass parsing of DAE */ + /** TODO: Break up and put into 2-pass parsing of DAE. */ std::vector<const COLLADAFW::VisualScene *>::iterator sit; for (sit = vscenes.begin(); sit != vscenes.end(); sit++) { PointerRNA sceneptr, unit_settings; @@ -1122,7 +1122,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light) switch (light->getLightType()) { case COLLADAFW::Light::AMBIENT_LIGHT: { - lamp->type = LA_SUN; /* TODO needs more thoughts */ + lamp->type = LA_SUN; /* TODO: needs more thoughts. */ } break; case COLLADAFW::Light::SPOT_LIGHT: { lamp->type = LA_SPOT; diff --git a/source/blender/io/collada/ImageExporter.cpp b/source/blender/io/collada/ImageExporter.cpp index bb7b3bf0631..4dd7e617459 100644 --- a/source/blender/io/collada/ImageExporter.cpp +++ b/source/blender/io/collada/ImageExporter.cpp @@ -113,7 +113,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) /* This image is already located on the file system. * But we want to create copies here. * To move images into the same export directory. - * Note: If an image is already located in the export folder, + * NOTE: If an image is already located in the export folder, * then skip the copy (as it would result in a file copy error). */ if (BLI_path_cmp(source_path, export_path) != 0) { diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index a33256f9a59..5aa57159328 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -170,7 +170,7 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol) case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: { COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues(); if (values->empty() || values->getCount() <= (v_index * stride + 2)) { - return; /* xxx need to create an error instead */ + return; /* XXX: need to create an error instead. */ } mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]); @@ -181,7 +181,7 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol) case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: { COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); if (values->empty() || values->getCount() <= (v_index * stride + 2)) { - return; /* xxx need to create an error instead */ + return; /* XXX: need to create an error instead. */ } mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]); @@ -967,7 +967,7 @@ static void bc_remove_materials_from_object(Object *ob, Mesh *me) /** * Returns the list of Users of the given Mesh object. - * Note: This function uses the object user flag to control + * NOTE: This function uses the object user flag to control * which objects have already been processed. */ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) diff --git a/source/blender/io/collada/SkinInfo.cpp b/source/blender/io/collada/SkinInfo.cpp index c2f17174d75..f0e1c5e4c26 100644 --- a/source/blender/io/collada/SkinInfo.cpp +++ b/source/blender/io/collada/SkinInfo.cpp @@ -36,6 +36,7 @@ #include "DNA_scene_types.h" #include "BKE_action.h" +#include "BKE_deform.h" #include "BKE_object.h" #include "BKE_object_deform.h" @@ -289,7 +290,8 @@ void SkinInfo::link_armature(bContext *C, /* -1 means "weight towards the bind shape", we just don't assign it to any group */ if (joint != -1) { - bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *def = (bDeformGroup *)BLI_findlink(defbase, joint); ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE); } diff --git a/source/blender/io/collada/collada_internal.cpp b/source/blender/io/collada/collada_internal.cpp index 787af933e8f..355aa5c22f0 100644 --- a/source/blender/io/collada/collada_internal.cpp +++ b/source/blender/io/collada/collada_internal.cpp @@ -71,7 +71,7 @@ void UnitConverter::convertVector3(COLLADABU::Math::Vector3 &vec, float *v) v[2] = vec.z; } -/* TODO need also for angle conversion, time conversion... */ +/* TODO: need also for angle conversion, time conversion... */ void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in) { diff --git a/source/blender/io/collada/collada_internal.h b/source/blender/io/collada/collada_internal.h index 1d2ed11bfe6..e3894093507 100644 --- a/source/blender/io/collada/collada_internal.h +++ b/source/blender/io/collada/collada_internal.h @@ -62,7 +62,7 @@ class UnitConverter { float getLinearMeter(void); - /* TODO need also for angle conversion, time conversion... */ + /* TODO: need also for angle conversion, time conversion... */ static void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in); static void mat4_to_dae(float out[4][4], float in[4][4]); diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index d7855d69d99..9967a526971 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -159,7 +159,7 @@ std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool al for (id = (ID *)bmain->actions.first; id; id = (ID *)(id->next)) { bAction *act = (bAction *)id; /* XXX This currently creates too many actions. - * TODO Need to check if the action is compatible to the given object. */ + * TODO: Need to check if the action is compatible to the given object. */ actions.push_back(act); } } @@ -281,7 +281,7 @@ bool bc_has_object_type(LinkNode *export_set, short obtype) for (node = export_set; node; node = node->next) { Object *ob = (Object *)node->link; - /* XXX - why is this checking for ob->data? - we could be looking for empties */ + /* XXX: why is this checking for ob->data? - we could be looking for empties. */ if (ob->type == obtype && ob->data) { return true; } @@ -728,7 +728,7 @@ void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]) /** * Stores a Float value as a custom bone property * - * Note: This function is currently not needed. Keep for future usage + * NOTE: This function is currently not needed. Keep for future usage */ static void bc_set_IDProperty(EditBone *ebone, const char *key, float value) { @@ -1018,7 +1018,7 @@ void bc_apply_global_transform(Vector &to_vec, const BCMatrix &global_transform, * Check if custom information about bind matrix exists and modify the from_mat * accordingly. * - * Note: This is old style for Blender <= 2.78 only kept for compatibility + * NOTE: This is old style for Blender <= 2.78 only kept for compatibility */ void bc_create_restpose_mat(BCExportSettings &export_settings, Bone *bone, diff --git a/source/blender/io/gpencil/gpencil_io.h b/source/blender/io/gpencil/gpencil_io.h index 24b13479359..fab867b38b3 100644 --- a/source/blender/io/gpencil/gpencil_io.h +++ b/source/blender/io/gpencil/gpencil_io.h @@ -27,9 +27,9 @@ extern "C" { #endif struct ARegion; -struct bContext; struct Object; struct View3D; +struct bContext; typedef struct GpencilIOParams { bContext *C; diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc index 6c369382e0d..294f6bfccb7 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc @@ -100,11 +100,9 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara invert_m4_m4(viewmat, cam_ob->obmat); mul_m4_m4m4(persmat_, params.winmat, viewmat); - is_ortho_ = params.is_ortho; } else { unit_m4(persmat_); - is_ortho_ = false; } winx_ = params_.region->winx; @@ -129,7 +127,6 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara } else { is_camera_ = false; - is_ortho_ = false; /* Calc selected object boundbox. Need set initial value to some variables. */ camera_ratio_ = 1.0f; offset_.x = 0.0f; @@ -248,19 +245,14 @@ bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co) } /** Convert to render space. */ -float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho) +float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co) { float3 parent_co = diff_mat_ * co; - mul_m4_v3(persmat_, parent_co); - - if (!is_ortho) { - parent_co.x = parent_co.x / max_ff(FLT_MIN, parent_co.z); - parent_co.y = parent_co.y / max_ff(FLT_MIN, parent_co.z); - } float2 r_co; - r_co.x = (parent_co.x + 1.0f) / 2.0f * (float)render_x_; - r_co.y = (parent_co.y + 1.0f) / 2.0f * (float)render_y_; + mul_v2_project_m4_v3(&r_co.x, persmat_, &parent_co.x); + r_co.x = (r_co.x + 1.0f) / 2.0f * (float)render_x_; + r_co.y = (r_co.y + 1.0f) / 2.0f * (float)render_y_; /* Invert X axis. */ if (invert_axis_[0]) { @@ -279,7 +271,7 @@ float2 GpencilIO::gpencil_3D_point_to_2D(const float3 co) { const bool is_camera = (bool)(rv3d_->persp == RV3D_CAMOB); if (is_camera) { - return gpencil_3D_point_to_render_space(co, is_orthographic()); + return gpencil_3D_point_to_render_space(co); } float2 result; gpencil_3D_point_to_screen_space(co, result); @@ -346,11 +338,6 @@ bool GpencilIO::is_camera_mode() return is_camera_; } -bool GpencilIO::is_orthographic() -{ - return is_ortho_; -} - /* Calculate selected strokes boundbox. */ void GpencilIO::selected_objects_boundbox_calc() { diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.hh b/source/blender/io/gpencil/intern/gpencil_io_base.hh index c3c6f1156bb..02758883f19 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.hh +++ b/source/blender/io/gpencil/intern/gpencil_io_base.hh @@ -37,9 +37,9 @@ struct Object; struct RegionView3D; struct Scene; -struct bGPdata; struct bGPDlayer; struct bGPDstroke; +struct bGPdata; using blender::Vector; @@ -88,14 +88,13 @@ class GpencilIO { /* Geometry functions. */ bool gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co); - float2 gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho); + float2 gpencil_3D_point_to_render_space(const float3 co); float2 gpencil_3D_point_to_2D(const float3 co); float stroke_point_radius_get(struct bGPDlayer *gpl, struct bGPDstroke *gps); void create_object_list(); bool is_camera_mode(); - bool is_orthographic(); float stroke_average_opacity_get(); @@ -109,7 +108,6 @@ class GpencilIO { private: float avg_opacity_; bool is_camera_; - bool is_ortho_; rctf select_boundbox_; /* Camera matrix. */ diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh index 0e9271dd2c6..99e8b1ed4fd 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh +++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh @@ -24,10 +24,10 @@ #include "gpencil_io_import_base.hh" struct GpencilIOParams; -struct NSVGshape; struct NSVGpath; -struct bGPdata; +struct NSVGshape; struct bGPDframe; +struct bGPdata; #define SVG_IMPORTER_NAME "SVG Import for Grease Pencil" #define SVG_IMPORTER_VERSION "v1.0" diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc index 66dfc21441e..a9cba7f36d9 100644 --- a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc @@ -121,7 +121,7 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch case OB_GPENCIL: return nullptr; case OB_TYPE_MAX: - BLI_assert(!"OB_TYPE_MAX should not be used"); + BLI_assert_msg(0, "OB_TYPE_MAX should not be used"); return nullptr; } diff --git a/source/blender/io/usd/intern/usd_writer_abstract.cc b/source/blender/io/usd/intern/usd_writer_abstract.cc index 5e66136abf1..6965ecf6249 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.cc +++ b/source/blender/io/usd/intern/usd_writer_abstract.cc @@ -128,7 +128,7 @@ bool USDAbstractWriter::mark_as_instance(const HierarchyContext &context, const if (context.export_path == context.original_export_path) { printf("USD ref error: export path is reference path: %s\n", context.export_path.c_str()); - BLI_assert(!"USD reference error"); + BLI_assert_msg(0, "USD reference error"); return false; } diff --git a/source/blender/io/usd/intern/usd_writer_camera.cc b/source/blender/io/usd/intern/usd_writer_camera.cc index 677be9a7fc4..50d644241df 100644 --- a/source/blender/io/usd/intern/usd_writer_camera.cc +++ b/source/blender/io/usd/intern/usd_writer_camera.cc @@ -61,7 +61,7 @@ static void camera_sensor_size_for_render(const Camera *camera, *r_sensor_y = camera->sensor_y; break; case CAMERA_SENSOR_FIT_AUTO: - BLI_assert(!"Camera fit should be either horizontal or vertical"); + BLI_assert_msg(0, "Camera fit should be either horizontal or vertical"); break; } } diff --git a/source/blender/io/usd/intern/usd_writer_light.cc b/source/blender/io/usd/intern/usd_writer_light.cc index f77c51c22ec..7ffae1dd398 100644 --- a/source/blender/io/usd/intern/usd_writer_light.cc +++ b/source/blender/io/usd/intern/usd_writer_light.cc @@ -87,7 +87,7 @@ void USDLightWriter::do_write(HierarchyContext &context) usd_light = pxr::UsdLuxDistantLight::Define(stage, usd_path); break; default: - BLI_assert(!"is_supported() returned true for unsupported light type"); + BLI_assert_msg(0, "is_supported() returned true for unsupported light type"); } /* Scale factor to get to somewhat-similar illumination. Since the USDViewer had similar diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 15a4f8817fd..43969bf0768 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -62,7 +62,7 @@ typedef struct DrawDataList { typedef struct IDPropertyData { void *pointer; ListBase group; - /** Note, we actually fit a double into these two ints. */ + /** NOTE: we actually fit a double into these two 32bit integers. */ int val, val2; } IDPropertyData; @@ -76,7 +76,7 @@ typedef struct IDProperty { /* saved is used to indicate if this struct has been saved yet. * seemed like a good idea as a '_pad' var was needed anyway :) */ int saved; - /** Note, alignment for 64 bits. */ + /** NOTE: alignment for 64 bits. */ IDPropertyData data; /* Array length, also (this is important!) string length + 1. @@ -554,7 +554,7 @@ enum { * Also used internally in readfile.c to mark data-blocks needing do_versions. */ LIB_TAG_NEW = 1 << 8, /* RESET_BEFORE_USE free test flag. - * TODO make it a RESET_AFTER_USE too. */ + * TODO: make it a RESET_AFTER_USE too. */ LIB_TAG_DOIT = 1 << 10, /* RESET_AFTER_USE tag existing data before linking so we know what is new. */ LIB_TAG_PRE_EXISTING = 1 << 11, @@ -621,9 +621,9 @@ typedef enum IDRecalcFlag { * When a collection gets tagged with this flag, all objects depending on the geometry and * transforms on any of the objects in the collection are updated. */ ID_RECALC_GEOMETRY = (1 << 1), - - /* ** Animation or time changed and animation is to be re-evaluated. ** */ - ID_RECALC_ANIMATION = (1 << 2), + /* Same as #ID_RECALC_GEOMETRY, but instead of tagging the batch cache as `dirty_all`, just tags + what matches the deform cache. */ + ID_RECALC_GEOMETRY_DEFORM = (1 << 2), /* ** Particle system changed. ** */ /* Only do pathcache etc. */ @@ -683,6 +683,9 @@ typedef enum IDRecalcFlag { * have to be copied on every update. */ ID_RECALC_PARAMETERS = (1 << 21), + /* ** Animation or time changed and animation is to be re-evaluated. ** */ + ID_RECALC_ANIMATION = (1 << 22), + /* Input has changed and datablock is to be reload from disk. * Applies to movie clips to inform that copy-on-written version is to be refreshed for the new * input file or for color space changes. */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index b6ffefb55e0..aba6ccfd3ba 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -135,7 +135,7 @@ typedef struct bAnimVizSettings { /* bAnimVizSettings->recalc */ typedef enum eAnimViz_RecalcFlags { - /* motionpaths need recalculating */ + /* Motion-paths need recalculating. */ ANIMVIZ_RECALC_PATHS = (1 << 0), } eAnimViz_RecalcFlags; @@ -419,7 +419,7 @@ typedef enum ePchan_DrawFlag { PCHAN_DRAW_NO_CUSTOM_BONE_SIZE = (1 << 0), } ePchan_DrawFlag; -/* Note: It doesn't take custom_scale_xyz into account */ +/* NOTE: It doesn't take custom_scale_xyz into account. */ #define PCHAN_CUSTOM_BONE_LENGTH(pchan) \ (((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length) @@ -602,7 +602,7 @@ typedef struct bActionGroup { struct bActionGroup *next, *prev; /** - * Note: this must not be touched by standard listbase functions + * NOTE: this must not be touched by standard listbase functions * which would clear links to other channels. */ ListBase channels; diff --git a/source/blender/makesdna/DNA_asset_defaults.h b/source/blender/makesdna/DNA_asset_defaults.h index ff00ba79cf0..ce01563f619 100644 --- a/source/blender/makesdna/DNA_asset_defaults.h +++ b/source/blender/makesdna/DNA_asset_defaults.h @@ -32,6 +32,13 @@ 0 \ } +#define _DNA_DEFAULT_AssetLibraryReference \ + { \ + .type = ASSET_LIBRARY_LOCAL, \ + /* Not needed really (should be ignored for #ASSET_LIBRARY_LOCAL), but helps debugging. */ \ + .custom_library_index = -1, \ + } + /** \} */ /* clang-format on */ diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h index 697d25653f8..3907c158573 100644 --- a/source/blender/makesdna/DNA_asset_types.h +++ b/source/blender/makesdna/DNA_asset_types.h @@ -20,6 +20,7 @@ #pragma once +#include "DNA_defs.h" #include "DNA_listBase.h" #ifdef __cplusplus @@ -36,6 +37,16 @@ typedef struct AssetTag { char name[64]; /* MAX_NAME */ } AssetTag; +# +# +typedef struct AssetFilterSettings { + /** Tags to match against. These are newly allocated, and compared against the + * #AssetMetaData.tags. + * TODO not used and doesn't do anything yet. */ + ListBase tags; /* AssetTag */ + uint64_t id_types; /* rna_enum_id_type_filter_items */ +} AssetFilterSettings; + /** * \brief The meta-data of an asset. * By creating and giving this for a data-block (#ID.asset_data), the data-block becomes an asset. @@ -62,6 +73,52 @@ typedef struct AssetMetaData { char _pad[4]; } AssetMetaData; +typedef enum eAssetLibraryType { + /* For the future. Display assets bundled with Blender by default. */ + // ASSET_LIBRARY_BUNDLED = 0, + /** Display assets from the current session (current "Main"). */ + ASSET_LIBRARY_LOCAL = 1, + /* For the future. Display assets for the current project. */ + // ASSET_LIBRARY_PROJECT = 2, + + /** Display assets from custom asset libraries, as defined in the preferences + * (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library.idname + * then. + * In RNA, we add the index of the custom library to this to identify it by index. So keep + * this last! */ + ASSET_LIBRARY_CUSTOM = 100, +} eAssetLibraryType; + +/* TODO copy of FileSelectAssetLibraryUID */ +/** + * Information to identify a asset library. May be either one of the predefined types (current + * 'Main', builtin library, project library), or a custom type as defined in the Preferences. + * + * If the type is set to #ASSET_LIBRARY_CUSTOM, `custom_library_index` must be set to identify the + * custom library. Otherwise it is not used. + */ +typedef struct AssetLibraryReference { + short type; /* eAssetLibraryType */ + char _pad1[2]; + /** + * If showing a custom asset library (#ASSET_LIBRARY_CUSTOM), this is the index of the + * #bUserAssetLibrary within #UserDef.asset_libraries. + * Should be ignored otherwise (but better set to -1 then, for sanity and debugging). + */ + int custom_library_index; +} AssetLibraryReference; + +/** + * Not part of the core design, we should try to get rid of it. Only needed to wrap FileDirEntry + * into a type with PropertyGroup as base, so we can have an RNA collection of #AssetHandle's to + * pass to the UI. + */ +# +# +typedef struct AssetHandle { + struct FileDirEntry *file_data; +} AssetHandle; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 1e4fd2a70f2..34f50b23c77 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -316,8 +316,9 @@ typedef struct bSameVolumeConstraint { /* Copy Transform Constraint */ typedef struct bTransLikeConstraint { struct Object *tar; + int flag; char mix_mode; - char _pad[7]; + char _pad[3]; /** MAX_ID_NAME-2. */ char subtarget[64]; } bTransLikeConstraint; @@ -740,6 +741,8 @@ typedef enum eBConstraint_SpaceTypes { CONSTRAINT_SPACE_POSE = 2, /** For posechannels - local with parent. */ CONSTRAINT_SPACE_PARLOCAL = 3, + /** For posechannels - local converted to the owner bone orientation. */ + CONSTRAINT_SPACE_OWNLOCAL = 6, /** For files from between 2.43-2.46 (should have been parlocal). */ CONSTRAINT_SPACE_INVALID = 4, /* do not exchange for anything! */ } eBConstraint_SpaceTypes; @@ -810,6 +813,12 @@ typedef enum eCopyScale_Flags { SIZELIKE_UNIFORM = (1 << 5), } eCopyScale_Flags; +/* bTransLikeConstraint.flag */ +typedef enum eCopyTransforms_Flags { + /* Remove shear from the target matrix. */ + TRANSLIKE_REMOVE_TARGET_SHEAR = (1 << 0), +} eCopyTransforms_Flags; + /* bTransLikeConstraint.mix_mode */ typedef enum eCopyTransforms_MixMode { /* Replace rotation channel values. */ @@ -818,6 +827,14 @@ typedef enum eCopyTransforms_MixMode { TRANSLIKE_MIX_BEFORE = 1, /* Multiply the copied transformation on the right, with anti-shear scale handling. */ TRANSLIKE_MIX_AFTER = 2, + /* Multiply the copied transformation on the left, handling loc/rot/scale separately. */ + TRANSLIKE_MIX_BEFORE_SPLIT = 3, + /* Multiply the copied transformation on the right, handling loc/rot/scale separately. */ + TRANSLIKE_MIX_AFTER_SPLIT = 4, + /* Multiply the copied transformation on the left, using simple matrix multiplication. */ + TRANSLIKE_MIX_BEFORE_FULL = 5, + /* Multiply the copied transformation on the right, using simple matrix multiplication. */ + TRANSLIKE_MIX_AFTER_FULL = 6, } eCopyTransforms_MixMode; /* bTransformConstraint.to/from */ @@ -1179,13 +1196,6 @@ typedef enum eStretchTo_Flags { STRETCHTOCON_USE_BULGE_MAX = (1 << 1), } eStretchTo_Flags; -/* important: these defines need to match up with PHY_DynamicTypes headerfile */ -#define CONSTRAINT_RB_BALL 1 -#define CONSTRAINT_RB_HINGE 2 -#define CONSTRAINT_RB_CONETWIST 4 -#define CONSTRAINT_RB_VEHICLE 11 -#define CONSTRAINT_RB_GENERIC6DOF 12 - #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index f6242679808..520fc6c1b00 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -35,6 +35,7 @@ extern "C" { #define MAXTEXTBOX 256 /* used in readfile.c and editfont.c */ struct AnimData; +struct CurveEval; struct CurveProfile; struct EditFont; struct GHash; @@ -43,7 +44,6 @@ struct Key; struct Material; struct Object; struct VFont; -struct CurveEval; /* These two Lines with # tell makesdna this struct can be excluded. */ # @@ -598,7 +598,7 @@ typedef enum eBezTriple_KeyframeType { /* CharInfo.flag */ enum { - /* note: CU_CHINFO_WRAP, CU_CHINFO_SMALLCAPS_TEST and CU_CHINFO_TRUNCATE are set dynamically */ + /* NOTE: CU_CHINFO_WRAP, CU_CHINFO_SMALLCAPS_TEST and CU_CHINFO_TRUNCATE are set dynamically. */ CU_CHINFO_BOLD = 1 << 0, CU_CHINFO_ITALIC = 1 << 1, CU_CHINFO_UNDERLINE = 1 << 2, diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h index 01ee954d0d2..ef476f21458 100644 --- a/source/blender/makesdna/DNA_defs.h +++ b/source/blender/makesdna/DNA_defs.h @@ -31,7 +31,7 @@ # ifdef __GNUC__ # define DNA_DEPRECATED __attribute__((deprecated)) # else -/* TODO, msvc & others */ +/* TODO: MSVC & others. */ # define DNA_DEPRECATED # endif # endif diff --git a/source/blender/makesdna/DNA_fileglobal_types.h b/source/blender/makesdna/DNA_fileglobal_types.h index dc43524a325..a0285215ff9 100644 --- a/source/blender/makesdna/DNA_fileglobal_types.h +++ b/source/blender/makesdna/DNA_fileglobal_types.h @@ -32,7 +32,7 @@ extern "C" { * the moment of saving, and the file-specific settings. */ typedef struct FileGlobal { - /** Needs to be here, for human fileformat recognition (keep first!). */ + /** Needs to be here, for human file-format recognition (keep first!). */ char subvstr[4]; short subversion; diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h index 5e36c5673a4..cec6eb0d044 100644 --- a/source/blender/makesdna/DNA_fluid_types.h +++ b/source/blender/makesdna/DNA_fluid_types.h @@ -544,7 +544,7 @@ typedef struct FluidDomainSettings { int boundary_width; /* Usually this is just 1. */ float gravity_final[3]; /* Scene or domain gravity multiplied with gravity weight. */ - /* -- User-accesible fields (from here on). -- */ + /* -- User-accessible fields (from here on). -- */ /* Adaptive domain options. */ int adapt_margin; @@ -640,7 +640,7 @@ typedef struct FluidDomainSettings { /* Fluid guiding options. */ float guide_alpha; /* Guiding weight scalar (determines strength). */ - int guide_beta; /* Guiding blur radius (affects size of vortices). */ + int guide_beta; /* Guiding blur radius (affects size of vortices vortices). */ float guide_vel_factor; /* Multiply guiding velocity by this factor. */ int guide_res[3]; /* Res for velocity guide grids - independent from base res. */ short guide_source; @@ -790,7 +790,7 @@ typedef struct FluidFlowSettings { float vel_coord[3]; char _pad1[4]; - /* -- User-accesible fields (from here on). -- */ + /* -- User-accessible fields (from here on). -- */ /* Emission. */ float density; @@ -856,7 +856,7 @@ typedef struct FluidEffectorSettings { float *verts_old; int numverts; - /* -- User-accesible fields (from here on). -- */ + /* -- User-accessible fields (from here on). -- */ float surface_distance; /* Thickness of mesh surface, used in obstacle sdf. */ int flags; diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index a4ab38f6022..b9697beeea9 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -184,8 +184,6 @@ .layer_pass = 0, \ .hardeness = 1.0f, \ .curve_intensity = NULL, \ - .fading_end = 10.0f, \ - .fading_end_factor = 0.2f, \ } #define _DNA_DEFAULT_SimplifyGpencilModifierData \ @@ -253,8 +251,6 @@ .thickness_fac = 1.0f, \ .thickness = 30, \ .layer_pass = 0, \ - .fading_end = 10.0f, \ - .fading_end_factor = 0.2f, \ } #define _DNA_DEFAULT_TimeGpencilModifierData \ @@ -287,6 +283,20 @@ .colorband = NULL, \ } +#define _DNA_DEFAULT_WeightGpencilModifierData \ + { \ + .target_vgname = "", \ + .material = NULL, \ + .layername = "", \ + .vgname = "", \ + .pass_index = 0, \ + .flag = 0, \ + .axis = 1, \ + .layer_pass = 0, \ + .dist_start = 0.0f, \ + .dist_end = 20.0f, \ + } + #define _DNA_DEFAULT_LineartGpencilModifierData \ { \ .edge_types = LRT_EDGE_FLAG_ALL_TYPE, \ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 40e4c65c4b8..fac5bd3d4f4 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -55,6 +55,7 @@ typedef enum GpencilModifierType { eGpencilModifierType_Texture = 18, eGpencilModifierType_Lineart = 19, eGpencilModifierType_Length = 20, + eGpencilModifierType_Weight = 21, /* Keep last. */ NUM_GREASEPENCIL_MODIFIER_TYPES, } GpencilModifierType; @@ -188,12 +189,7 @@ typedef struct ThickGpencilModifierData { int thickness; /** Custom index for passes. */ int layer_pass; - /** Start/end distances of the fading effect. */ - float fading_start; - float fading_end; - float fading_end_factor; - /** Fading reference object */ - struct Object *object; + char _pad[4]; struct CurveMapping *curve_thickness; } ThickGpencilModifierData; @@ -205,7 +201,7 @@ typedef enum eThickGpencil_Flag { GP_THICK_NORMALIZE = (1 << 4), GP_THICK_INVERT_LAYERPASS = (1 << 5), GP_THICK_INVERT_MATERIAL = (1 << 6), - GP_THICK_FADING = (1 << 7), + GP_THICK_WEIGHT_FACTOR = (1 << 7), } eThickGpencil_Flag; typedef struct TimeGpencilModifierData { @@ -298,16 +294,9 @@ typedef struct OpacityGpencilModifierData { int flag; /** Main Opacity factor. */ float factor; - /** Fading controlling object */ - int _pad0; - struct Object *object; - /** Start/end distances of the fading effect. */ - float fading_start; - float fading_end; - float fading_end_factor; /** Modify stroke, fill or both. */ char modify_color; - char _pad1[3]; + char _pad[3]; /** Custom index for passes. */ int layer_pass; @@ -323,7 +312,7 @@ typedef enum eOpacityGpencil_Flag { GP_OPACITY_INVERT_MATERIAL = (1 << 5), GP_OPACITY_CUSTOM_CURVE = (1 << 6), GP_OPACITY_NORMALIZE = (1 << 7), - GP_OPACITY_FADING = (1 << 8), + GP_OPACITY_WEIGHT_FACTOR = (1 << 8), } eOpacityGpencil_Flag; typedef struct ArrayGpencilModifierData { @@ -814,6 +803,7 @@ typedef enum eTintGpencil_Flag { GP_TINT_INVERT_LAYERPASS = (1 << 4), GP_TINT_INVERT_MATERIAL = (1 << 5), GP_TINT_CUSTOM_CURVE = (1 << 6), + GP_TINT_WEIGHT_FACTOR = (1 << 7), } eTintGpencil_Flag; typedef struct TextureGpencilModifierData { @@ -867,6 +857,61 @@ typedef enum eTextureGpencil_Mode { STROKE_AND_FILL = 2, } eTextureGpencil_Mode; +typedef struct WeightGpencilModifierData { + GpencilModifierData modifier; + /** Target vertexgroup name, MAX_VGROUP_NAME. */ + char target_vgname[64]; + /** Material for filtering. */ + struct Material *material; + /** Layer name. */ + char layername[64]; + /** Optional vertexgroup filter name, MAX_VGROUP_NAME. */ + char vgname[64]; + /** Custom index for passes. */ + int pass_index; + /** Flags. */ + int flag; + /** Minimum valid weight (clamp value). */ + float min_weight; + /** Custom index for passes. */ + int layer_pass; + /** Calculation Mode. */ + short mode; + /** Axis. */ + short axis; + /** Angle */ + float angle; + /** Start/end distances. */ + float dist_start; + float dist_end; + /** Space (Local/World). */ + short space; + char _pad[6]; + + /** Reference object */ + struct Object *object; +} WeightGpencilModifierData; + +typedef enum eWeightGpencil_Flag { + GP_WEIGHT_INVERT_LAYER = (1 << 0), + GP_WEIGHT_INVERT_PASS = (1 << 1), + GP_WEIGHT_INVERT_VGROUP = (1 << 2), + GP_WEIGHT_INVERT_LAYERPASS = (1 << 3), + GP_WEIGHT_INVERT_MATERIAL = (1 << 4), + GP_WEIGHT_BLEND_DATA = (1 << 5), + GP_WEIGHT_INVERT_OUTPUT = (1 << 6), +} eWeightGpencil_Flag; + +typedef enum eWeightGpencilModifierMode { + GP_WEIGHT_MODE_DISTANCE = 0, + GP_WEIGHT_MODE_ANGLE = 1, +} eWeightGpencilModifierMode; + +typedef enum eGpencilModifierSpace { + GP_SPACE_LOCAL = 0, + GP_SPACE_WORLD = 1, +} eGpencilModifierSpace; + typedef enum eLineartGpencilModifierSource { LRT_SOURCE_COLLECTION = 0, LRT_SOURCE_OBJECT = 1, diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index d0ae50d09ef..380d8ad1249 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -33,8 +33,8 @@ extern "C" { struct AnimData; struct Curve; -struct MDeformVert; struct Curve; +struct MDeformVert; #define GP_DEFAULT_PIX_FACTOR 1.0f #define GP_DEFAULT_GRID_LINES 4 @@ -246,11 +246,11 @@ typedef struct bGPDstroke_Runtime { /** Runtime falloff factor (only for transform). */ float multi_frame_falloff; - /** Vertex offset in the vbo where this stroke starts. */ + /** Vertex offset in the VBO where this stroke starts. */ int stroke_start; /** Triangle offset in the ibo where this fill starts. */ int fill_start; - /** Curve Handles offset in the ibo where this handle starts. */ + /** Curve Handles offset in the IBO where this handle starts. */ int curve_start; /** Original stroke (used to dereference evaluated data) */ @@ -666,6 +666,9 @@ typedef struct bGPdata { /** List of bGPDpalette's - Deprecated (2.78 - 2.79 only). */ ListBase palettes DNA_DEPRECATED; + /** List of bDeformGroup names and flag only. */ + ListBase vertex_group_names; + /* 3D Viewport/Appearance Settings */ /** Factor to define pixel size conversion. */ float pixfactor; @@ -715,7 +718,8 @@ typedef struct bGPdata { /** Stroke selection last index. Used to generate a unique selection index. */ int select_last_index; - char _pad3[4]; + + int vertex_group_active_index; bGPgrid grid; diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h index 48eb8d90702..361893db893 100644 --- a/source/blender/makesdna/DNA_lattice_types.h +++ b/source/blender/makesdna/DNA_lattice_types.h @@ -72,6 +72,11 @@ typedef struct Lattice { struct MDeformVert *dvert; /** Multiply the influence, MAX_VGROUP_NAME. */ char vgroup[64]; + /** List of bDeformGroup names and flag only. */ + ListBase vertex_group_names; + int vertex_group_active_index; + + char _pad0[4]; struct EditLatt *editlatt; void *batch_cache; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 144e4594c98..c54c086affd 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -164,8 +164,10 @@ typedef struct Mesh { struct MVert *mvert; /** Array of edges. */ struct MEdge *medge; - /** Deformgroup vertices. */ + /** Deform-group vertices. */ struct MDeformVert *dvert; + /** List of bDeformGroup names and flag only. */ + ListBase vertex_group_names; /* array of colors for the tessellated faces, must be number of tessellated * faces * 4 in length */ @@ -189,7 +191,7 @@ typedef struct Mesh { /* END BMESH ONLY */ int attributes_active_index; - int _pad3; + int vertex_group_active_index; /* the last selected vertex/edge/face are used for the active face however * this means the active face must always be selected, this is to keep track diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 346e65f0fa1..bc6b35c8e43 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -151,7 +151,7 @@ enum { /** \} */ /* -------------------------------------------------------------------- */ -/** \name Loop Tesselation Runtime Data +/** \name Loop Tessellation Runtime Data * \{ */ /** diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index f6dac88051b..1b3dbd148df 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -647,7 +647,8 @@ .target = NULL, \ .verts = NULL, \ .falloff = 4.0f, \ - .numverts = 0, \ + .num_mesh_verts = 0, \ + .num_bind_verts = 0, \ .numpoly = 0, \ .flags = 0, \ .mat = _DNA_DEFAULT_UNIT_M4, \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index dfe49452636..401b49f2ee8 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1840,7 +1840,7 @@ typedef struct CorrectiveSmoothModifierData { * use for MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND */ float (*bind_coords)[3]; - /* note: -1 is used to bind */ + /* NOTE: -1 is used to bind. */ unsigned int bind_coords_num; float lambda, scale; @@ -2180,7 +2180,7 @@ typedef struct SDefBind { typedef struct SDefVert { SDefBind *binds; unsigned int numbinds; - char _pad[4]; + unsigned int vertex_idx; } SDefVert; typedef struct SurfaceDeformModifierData { @@ -2192,11 +2192,10 @@ typedef struct SurfaceDeformModifierData { /** Vertex bind data. */ SDefVert *verts; float falloff; - unsigned int numverts, numpoly; + unsigned int num_mesh_verts, num_bind_verts, numpoly; int flags; float mat[4][4]; float strength; - char _pad[4]; char defgrp_name[64]; } SurfaceDeformModifierData; @@ -2204,10 +2203,9 @@ typedef struct SurfaceDeformModifierData { enum { /* This indicates "do bind on next modifier evaluation" as well as "is bound". */ MOD_SDEF_BIND = (1 << 0), - MOD_SDEF_INVERT_VGROUP = (1 << 1) - - /* MOD_SDEF_USES_LOOPTRI = (1 << 1), */ /* UNUSED */ - /* MOD_SDEF_HAS_CONCAVE = (1 << 2), */ /* UNUSED */ + MOD_SDEF_INVERT_VGROUP = (1 << 1), + /* Only store bind data for nonzero vgroup weights at the time of bind. */ + MOD_SDEF_SPARSE_BIND = (1 << 2), }; /* Surface Deform vertex bind modes */ @@ -2256,6 +2254,10 @@ typedef struct NodesModifierData { ModifierData modifier; struct bNodeTree *node_group; struct NodesModifierSettings settings; + + /* Contains logged information from the last evaluation. This can be used to help the user to + * debug a node tree. */ + void *runtime_eval_log; } NodesModifierData; typedef struct MeshToVolumeModifierData { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 4e0fb64cf1f..d05fb6b4168 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -37,7 +37,8 @@ struct Collection; struct ID; struct Image; struct ListBase; -struct NodeTreeUIStorage; +struct Material; +struct Tex; struct bGPdata; struct bNodeInstanceHash; struct bNodeLink; @@ -45,8 +46,6 @@ struct bNodePreview; struct bNodeTreeExec; struct bNodeType; struct uiBlock; -struct Tex; -struct Material; #define NODE_MAXSTR 64 @@ -326,6 +325,7 @@ typedef struct bNode { #define NODE_HIDDEN 8 #define NODE_ACTIVE 16 #define NODE_ACTIVE_ID 32 +/* Used to indicate which group output node is used and which viewer node is active. */ #define NODE_DO_OUTPUT 64 #define __NODE_GROUP_EDIT 128 /* DEPRECATED */ /* free test flag, undefined */ @@ -341,7 +341,7 @@ typedef struct bNode { #define NODE_TRANSFORM (1 << 13) /* node is active texture */ -/* note: take care with this flag since its possible it gets +/* NOTE: take care with this flag since its possible it gets * `stuck` inside/outside the active group - which makes buttons * window texture not update, we try to avoid it by clearing the * flag when toggling group editing - Campbell */ @@ -360,7 +360,7 @@ typedef struct bNode { */ #define NODE_DO_OUTPUT_RECALC (1 << 17) /* A preview for the data in this node can be displayed in the spreadsheet editor. */ -#define NODE_ACTIVE_PREVIEW (1 << 18) +#define __NODE_ACTIVE_PREVIEW (1 << 18) /* deprecated */ /* node->update */ /* XXX NODE_UPDATE is a generic update flag. More fine-grained updates @@ -516,8 +516,6 @@ typedef struct bNodeTree { int (*test_break)(void *); void (*update_draw)(void *); void *tbh, *prh, *sdh, *udh; - - struct NodeTreeUIStorage *ui_storage; } bNodeTree; /* ntree->type, index */ @@ -1380,6 +1378,11 @@ typedef struct NodeSwitch { uint8_t input_type; } NodeSwitch; +typedef struct NodeGeometryCurvePrimitiveLine { + /* GeometryNodeCurvePrimitiveLineMode. */ + uint8_t mode; +} NodeGeometryCurvePrimitiveLine; + typedef struct NodeGeometryCurvePrimitiveBezierSegment { /* GeometryNodeCurvePrimitiveBezierSegmentMode. */ uint8_t mode; @@ -1390,6 +1393,11 @@ typedef struct NodeGeometryCurvePrimitiveCircle { uint8_t mode; } NodeGeometryCurvePrimitiveCircle; +typedef struct NodeGeometryCurvePrimitiveQuad { + /* GeometryNodeCurvePrimitiveQuadMode. */ + uint8_t mode; +} NodeGeometryCurvePrimitiveQuad; + typedef struct NodeGeometryCurveResample { /* GeometryNodeCurveSampleMode. */ uint8_t mode; @@ -1710,6 +1718,14 @@ typedef enum FloatCompareOperation { NODE_FLOAT_COMPARE_NOT_EQUAL = 5, } FloatCompareOperation; +/* Float to Int node operations. */ +typedef enum FloatToIntRoundingMode { + FN_NODE_FLOAT_TO_INT_ROUND = 0, + FN_NODE_FLOAT_TO_INT_FLOOR = 1, + FN_NODE_FLOAT_TO_INT_CEIL = 2, + FN_NODE_FLOAT_TO_INT_TRUNCATE = 3, +} FloatToIntRoundingMode; + /* Clamp node types. */ enum { NODE_CLAMP_MINMAX = 0, @@ -1927,6 +1943,19 @@ typedef enum GeometryNodeMeshLineCountMode { GEO_NODE_MESH_LINE_COUNT_RESOLUTION = 1, } GeometryNodeMeshLineCountMode; +typedef enum GeometryNodeCurvePrimitiveLineMode { + GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS = 0, + GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION = 1 +} GeometryNodeCurvePrimitiveLineMode; + +typedef enum GeometryNodeCurvePrimitiveQuadMode { + GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE = 0, + GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM = 1, + GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID = 2, + GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE = 3, + GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS = 4, +} GeometryNodeCurvePrimitiveQuadMode; + typedef enum GeometryNodeCurvePrimitiveBezierSegmentMode { GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT_POSITION = 0, GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT_OFFSET = 1, diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 8d861647bd2..dd31e85647d 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -172,12 +172,6 @@ typedef struct Object_Runtime { struct GeometrySet *geometry_set_eval; /** - * A GHash that contains geometry sets for intermediate stages of evaluation. The keys are just a - * hash and are not owned by the map. The geometry sets are owned. - */ - void *geometry_set_previews; - - /** * Mesh structure created during object evaluation. * It has deformation only modifiers applied on it. */ @@ -278,8 +272,7 @@ typedef struct Object { ListBase constraintChannels DNA_DEPRECATED; /* XXX deprecated... old animation system */ ListBase effect DNA_DEPRECATED; /* XXX deprecated... keep for readfile */ - /** List of bDeformGroup (vertex groups) names and flag only. */ - ListBase defbase; + ListBase defbase DNA_DEPRECATED; /* Only for versioning, moved to object data. */ /** List of ModifierData structures. */ ListBase modifiers; /** List of GpencilModifierData structures. */ @@ -335,12 +328,6 @@ typedef struct Object { */ float imat[4][4]; - /* Previously 'imat' was used at render time, but as other places use it too - * the interactive ui of 2.5 creates problems. So now only 'imat_ren' should - * be used when ever the inverse of ob->obmat * re->viewmat is needed! - jahka - */ - float imat_ren[4][4]; - /** Copy of Base's layer in the scene. */ unsigned int lay DNA_DEPRECATED; @@ -386,9 +373,9 @@ typedef struct Object { /** Custom index, for renderpasses. */ short index; - /** Current deformation group, note: index starts at 1. */ - unsigned short actdef; - /** Current face map, note: index starts at 1. */ + /** Current deformation group, NOTE: index starts at 1. */ + unsigned short actdef DNA_DEPRECATED; + /** Current face map, NOTE: index starts at 1. */ unsigned short actfmap; char _pad2[2]; /** Object color (in most cases the material color is used for drawing). */ @@ -711,7 +698,7 @@ enum { /* OB_ADS_SHOWCONS = 1 << 12, */ /* UNUSED */ /* object's material channels */ /* OB_ADS_SHOWMATS = 1 << 13, */ /* UNUSED */ - /* object's marticle channels */ + /* object's particle channels */ /* OB_ADS_SHOWPARTS = 1 << 14, */ /* UNUSED */ }; diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h index 7a39e0caef3..ebf3d4a248c 100644 --- a/source/blender/makesdna/DNA_outliner_types.h +++ b/source/blender/makesdna/DNA_outliner_types.h @@ -106,7 +106,7 @@ typedef enum eTreeStoreElemType { TSE_R_LAYER = 20, /* TSE_R_PASS = 21, */ /* UNUSED */ /* TSE_LINKED_MAT = 22, */ - /* NOTE, is used for light group */ + /* NOTE: is used for light group. */ /* TSE_LINKED_LAMP = 23, */ TSE_POSEGRP_BASE = 24, TSE_POSEGRP = 25, diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 0253de9f9d1..a51c532dfb3 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -74,8 +74,9 @@ typedef struct ParticleSpring { /* Child particles are created around or between parent particles */ typedef struct ChildParticle { - /** Num is face index on the final derived mesh. */ - int num, parent; + /** Face index on the final derived mesh. */ + int num; + int parent; /** Nearest particles to the child, used for the interpolation. */ int pa[4]; /** Interpolation weights for the above particles. */ diff --git a/source/blender/makesdna/DNA_pointcache_types.h b/source/blender/makesdna/DNA_pointcache_types.h index ad5f386bf2b..7de0bb29c46 100644 --- a/source/blender/makesdna/DNA_pointcache_types.h +++ b/source/blender/makesdna/DNA_pointcache_types.h @@ -131,32 +131,34 @@ typedef struct PointCache { void (*free_edit)(struct PTCacheEdit *edit); } PointCache; -/* pointcache->flag */ -#define PTCACHE_BAKED (1 << 0) -#define PTCACHE_OUTDATED (1 << 1) -#define PTCACHE_SIMULATION_VALID (1 << 2) -#define PTCACHE_BAKING (1 << 3) -//#define PTCACHE_BAKE_EDIT (1 << 4) -//#define PTCACHE_BAKE_EDIT_ACTIVE (1 << 5) -#define PTCACHE_DISK_CACHE (1 << 6) -///* removed since 2.64 - T30974, could be added back in a more useful way */ -//#define PTCACHE_QUICK_CACHE (1 << 7) -#define PTCACHE_FRAMES_SKIPPED (1 << 8) -#define PTCACHE_EXTERNAL (1 << 9) -#define PTCACHE_READ_INFO (1 << 10) -/** don't use the filename of the blendfile the data is linked from (write a local cache) */ -#define PTCACHE_IGNORE_LIBPATH (1 << 11) -/** - * High resolution cache is saved for smoke for backwards compatibility, - * so set this flag to know it's a "fake" cache. - */ -#define PTCACHE_FAKE_SMOKE (1 << 12) -#define PTCACHE_IGNORE_CLEAR (1 << 13) +enum { + /* pointcache->flag */ + PTCACHE_BAKED = 1 << 0, + PTCACHE_OUTDATED = 1 << 1, + PTCACHE_SIMULATION_VALID = 1 << 2, + PTCACHE_BAKING = 1 << 3, + // PTCACHE_BAKE_EDIT = 1 << 4, + // PTCACHE_BAKE_EDIT_ACTIVE = 1 << 5, + PTCACHE_DISK_CACHE = 1 << 6, + /* removed since 2.64 - T30974, could be added back in a more useful way */ + // PTCACHE_QUICK_CACHE = 1 << 7, + PTCACHE_FRAMES_SKIPPED = 1 << 8, + PTCACHE_EXTERNAL = 1 << 9, + PTCACHE_READ_INFO = 1 << 10, + /** Don't use the filename of the blend-file the data is linked from (write a local cache). */ + PTCACHE_IGNORE_LIBPATH = 1 << 11, + /** + * High resolution cache is saved for smoke for backwards compatibility, + * so set this flag to know it's a "fake" cache. + */ + PTCACHE_FAKE_SMOKE = 1 << 12, + PTCACHE_IGNORE_CLEAR = 1 << 13, -#define PTCACHE_FLAG_INFO_DIRTY (1 << 14) + PTCACHE_FLAG_INFO_DIRTY = 1 << 14, -/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */ -#define PTCACHE_REDO_NEEDED 258 + PTCACHE_REDO_NEEDED = PTCACHE_OUTDATED | PTCACHE_FRAMES_SKIPPED, + PTCACHE_FLAGS_COPY = PTCACHE_DISK_CACHE | PTCACHE_EXTERNAL | PTCACHE_IGNORE_LIBPATH, +}; #define PTCACHE_COMPRESS_NO 0 #define PTCACHE_COMPRESS_LZO 1 diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h index 740dc35517a..1d5e5eeed31 100644 --- a/source/blender/makesdna/DNA_rigidbody_types.h +++ b/source/blender/makesdna/DNA_rigidbody_types.h @@ -206,12 +206,12 @@ typedef enum eRigidBody_Shape { RB_SHAPE_SPHERE = 1, /** Rounded "pill" shape (i.e. calcium tablets). */ RB_SHAPE_CAPSULE = 2, - /** Cylinder (i.e. pringles can). */ + /** Cylinder (i.e. tin of beans). */ RB_SHAPE_CYLINDER = 3, /** Cone (i.e. party hat). */ RB_SHAPE_CONE = 4, - /** Convex hull (minimal shrinkwrap encompassing all verts). */ + /** Convex hull (minimal shrink-wrap encompassing all verts). */ RB_SHAPE_CONVEXH = 5, /** Triangulated mesh. */ RB_SHAPE_TRIMESH = 6, diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index d40de4184b6..cd752b220a3 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -25,7 +25,7 @@ #include "DNA_defs.h" -/* XXX, temp feature - campbell */ +/* XXX(campbell): temp feature. */ #define DURIAN_CAMERA_SWITCH /* check for cyclic set-scene, @@ -397,7 +397,7 @@ typedef enum eStereo3dInterlaceType { /* Generic image format settings, * this is used for NodeImageFile and IMAGE_OT_save_as operator too. * - * note: its a bit strange that even though this is an image format struct + * NOTE: its a bit strange that even though this is an image format struct * the imtype can still be used to select video formats. * RNA ensures these enum's are only selectable for render output. */ @@ -2069,6 +2069,7 @@ enum { /** #SequencerToolSettings.snap_flag */ #define SEQ_SNAP_IGNORE_MUTED (1 << 0) #define SEQ_SNAP_IGNORE_SOUND (1 << 1) +#define SEQ_SNAP_CURRENT_FRAME_TO_STRIPS (1 << 2) /** #ToolSettings.snap_node_mode */ #define SCE_SNAP_MODE_NODE_X (1 << 0) diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index ce25f8e40b7..5bd9cc7a999 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -43,23 +43,25 @@ struct SpaceLink; struct SpaceType; struct uiBlock; struct uiLayout; +struct uiList; struct wmDrawBuffer; struct wmTimer; struct wmTooltipState; -/* TODO Doing this is quite ugly :) +/* TODO: Doing this is quite ugly :) * Once the top-bar is merged bScreen should be refactored to use ScrAreaMap. */ #define AREAMAP_FROM_SCREEN(screen) ((ScrAreaMap *)&(screen)->vertbase) typedef struct bScreen { ID id; - /* TODO Should become ScrAreaMap now. - * ** NOTE: KEEP ORDER IN SYNC WITH ScrAreaMap! (see AREAMAP_FROM_SCREEN macro above) ** */ + /* TODO: Should become ScrAreaMap now. + * NOTE: KEEP ORDER IN SYNC WITH #ScrAreaMap! (see AREAMAP_FROM_SCREEN macro above). */ /** Screens have vertices/edges to define areas. */ ListBase vertbase; ListBase edgebase; ListBase areabase; + /* End variables that must be in sync with #ScrAreaMap. */ /** Screen level regions (menus), runtime only. */ ListBase regionbase; @@ -245,11 +247,16 @@ typedef struct PanelCategoryStack { char idname[64]; } PanelCategoryStack; +typedef void (*uiListFreeRuntimeDataFunc)(struct uiList *ui_list); + /* uiList dynamic data... */ /* These two Lines with # tell makesdna this struct can be excluded. */ # # typedef struct uiListDyn { + /** Callback to free UI data when freeing UI-Lists in BKE. */ + uiListFreeRuntimeDataFunc free_runtime_data_fn; + /** Number of rows needed to draw all elements. */ int height; /** Actual visual height of the list (in rows). */ @@ -257,6 +264,9 @@ typedef struct uiListDyn { /** Minimal visual height of the list (in rows). */ int visual_height_min; + /** Number of columns drawn for grid layouts. */ + int columns; + /** Number of items in collection. */ int items_len; /** Number of items actually visible after filtering. */ @@ -269,11 +279,19 @@ typedef struct uiListDyn { int resize; int resize_prev; + /** Allocated custom data. Freed together with the #uiList (and when re-assigning). */ + void *customdata; + /* Filtering data. */ /** Items_len length. */ int *items_filter_flags; /** Org_idx -> new_idx, items_len length. */ int *items_filter_neworder; + + struct wmOperatorType *custom_drag_optype; + struct PointerRNA *custom_drag_opptr; + struct wmOperatorType *custom_activate_optype; + struct PointerRNA *custom_activate_opptr; } uiListDyn; typedef struct uiList { /* some list UI data need to be saved in file */ @@ -300,6 +318,12 @@ typedef struct uiList { /* some list UI data need to be saved in file */ int filter_flag; int filter_sort_flag; + /** Operator executed when activating an item. */ + const char *custom_activate_opname; + /** Operator executed when dragging an item (item gets activated too, without running + * custom_activate_opname above). */ + const char *custom_drag_opname; + /* Custom sub-classes properties. */ IDProperty *properties; @@ -583,6 +607,7 @@ enum { UILST_LAYOUT_DEFAULT = 0, UILST_LAYOUT_COMPACT = 1, UILST_LAYOUT_GRID = 2, + UILST_LAYOUT_BIG_PREVIEW_GRID = 3, }; /** #uiList.flag */ diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 1bd4c9233e3..55dc51e0632 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -43,9 +43,9 @@ extern "C" { struct Ipo; struct MovieClip; struct Scene; +struct SequenceLookup; struct VFont; struct bSound; -struct SequenceLookup; /* strlens; 256= FILE_MAXFILE, 768= FILE_MAXDIR */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 556a9e48de5..b990de29ff3 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -448,7 +448,7 @@ typedef struct SpaceGraph { /** Mode for the Graph editor (eGraphEdit_Mode). */ short mode; /** - * Time-transform autosnapping settings for Graph editor + * Time-transform auto-snapping settings for Graph editor * (eAnimEdit_AutoSnap in DNA_action_types.h). */ short autosnap; @@ -700,14 +700,14 @@ typedef enum eSpaceSeq_OverlayType { * Information to identify a asset library. May be either one of the predefined types (current * 'Main', builtin library, project library), or a custom type as defined in the Preferences. * - * If the type is set to #FILE_ASSET_LIBRARY_CUSTOM, idname must have the name to identify the + * If the type is set to #ASSET_LIBRARY_CUSTOM, idname must have the name to identify the * custom library. Otherwise idname is not used. */ typedef struct FileSelectAssetLibraryUID { short type; /* eFileAssetLibrary_Type */ char _pad[2]; /** - * If showing a custom asset library (#FILE_ASSET_LIBRARY_CUSTOM), this is the index of the + * If showing a custom asset library (#ASSET_LIBRARY_CUSTOM), this is the index of the * #bUserAssetLibrary within #UserDef.asset_libraries. * Should be ignored otherwise (but better set to -1 then, for sanity and debugging). */ @@ -727,6 +727,12 @@ typedef struct FileSelectParams { char renamefile[256]; short rename_flag; + char _pad[4]; + /** An ID that was just renamed. Used to identify a renamed asset file over re-reads, similar to + * `renamefile` but for local IDs (takes precedence). Don't keep this stored across handlers! + * Would break on undo. */ + const ID *rename_id; + void *_pad3; /** List of filetypes to filter (FILE_MAXFILE). */ char filter_glob[256]; @@ -734,7 +740,6 @@ typedef struct FileSelectParams { /** Text items name must match to be shown. */ char filter_search[64]; /** Same as filter, but for ID types (aka library groups). */ - int _pad0; uint64_t filter_id; /** Active file used for keyboard navigation. */ @@ -880,22 +885,6 @@ typedef enum eFileBrowse_Mode { FILE_BROWSE_MODE_ASSETS = 1, } eFileBrowse_Mode; -typedef enum eFileAssetLibrary_Type { - /* For the future. Display assets bundled with Blender by default. */ - // FILE_ASSET_LIBRARY_BUNDLED = 0, - /** Display assets from the current session (current "Main"). */ - FILE_ASSET_LIBRARY_LOCAL = 1, - /* For the future. Display assets for the current project. */ - // FILE_ASSET_LIBRARY_PROJECT = 2, - - /** Display assets from custom asset libraries, as defined in the preferences - * (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library.idname - * then. - * In RNA, we add the index of the custom library to this to identify it by index. So keep - * this last! */ - FILE_ASSET_LIBRARY_CUSTOM = 100, -} eFileAssetLibrary_Type; - /* FileSelectParams.display */ enum eFileDisplayType { /** Internal (not exposed to users): Keep whatever display type was used during the last File @@ -987,7 +976,7 @@ typedef enum eFileSel_Params_Flag { } eFileSel_Params_Flag; /* sfile->params->rename_flag */ -/* Note: short flag. Defined as bitflags, but currently only used as exclusive status markers... */ +/* NOTE: short flag. Defined as bitflags, but currently only used as exclusive status markers... */ typedef enum eFileSel_Params_RenameFlag { /** Used when we only have the name of the entry we want to rename, * but not yet access to its matching file entry. */ @@ -1043,82 +1032,25 @@ typedef enum eDirEntry_SelectFlag { /* ***** Related to file browser, but never saved in DNA, only here to help with RNA. ***** */ -/** - * About Unique identifier. - * - * Stored in a CustomProps once imported. - * Each engine is free to use it as it likes - it will be the only thing passed to it by blender to - * identify asset/variant/version (concatenating the three into a single 48 bytes one). - * Assumed to be 128bits, handled as four integers due to lack of real bytes proptype in RNA :|. - */ -#define ASSET_UUID_LENGTH 16 - -/* Used to communicate with asset engines outside of 'import' context. */ -# -# -typedef struct AssetUUID { - int uuid_asset[4]; - int uuid_variant[4]; - int uuid_revision[4]; -} AssetUUID; - -# -# -typedef struct AssetUUIDList { - AssetUUID *uuids; - int nbr_uuids; - char _pad[4]; -} AssetUUIDList; - -/* Container for a revision, only relevant in asset context. */ -# -# -typedef struct FileDirEntryRevision { - struct FileDirEntryRevision *next, *prev; - - char *comment; - void *_pad; - - int uuid[4]; - - uint64_t size; - int64_t time; - /* Temp caching of UI-generated strings... */ - char size_str[16]; - char datetime_str[16 + 8]; -} FileDirEntryRevision; - -/* Container for a variant, only relevant in asset context. - * In case there are no variants, a single one shall exist, with NULL name/description. */ -# -# -typedef struct FileDirEntryVariant { - struct FileDirEntryVariant *next, *prev; - - int uuid[4]; - char *name; - char *description; - - ListBase revisions; - int nbr_revisions; - int act_revision; -} FileDirEntryVariant; - -/* Container for mere direntry, with additional asset-related data. */ # # typedef struct FileDirEntry { struct FileDirEntry *next, *prev; - int uuid[4]; + uint32_t uid; /* FileUID */ /* Name needs freeing if FILE_ENTRY_NAME_FREE is set. Otherwise this is a direct pointer to a * name buffer. */ char *name; char *description; - /* Either point to active variant/revision if available, or own entry - * (in mere filebrowser case). */ - FileDirEntryRevision *entry; + uint64_t size; + int64_t time; + + struct { + /* Temp caching of UI-generated strings. */ + char size_str[16]; + char datetime_str[16 + 8]; + } draw_data; /** #eFileSel_File_Types. */ int typeflag; @@ -1141,32 +1073,16 @@ typedef struct FileDirEntry { /* The icon_id for the preview image. */ int preview_icon_id; - /* Tags are for info only, most of filtering is done in asset engine. */ - char **tags; - int nbr_tags; - - short status; short flags; /* eFileAttributes defined in BLI_fileops.h */ int attributes; - - ListBase variants; - int nbr_variants; - int act_variant; } FileDirEntry; /** - * Array of direntries. - * - * This struct is used in various, different contexts. - * - * In Filebrowser UI, it stores the total number of available entries, the number of visible - * (filtered) entries, and a subset of those in 'entries' ListBase, from idx_start (included) - * to idx_end (excluded). + * Array of directory entries. * - * In AssetEngine context (i.e. outside of 'browsing' context), entries contain all needed data, - * there is no filtering, so nbr_entries_filtered, entry_idx_start and entry_idx_end - * should all be set to -1. + * Stores the total number of available entries, the number of visible (filtered) entries, and a + * subset of those in 'entries' ListBase, from idx_start (included) to idx_end (excluded). */ # # @@ -1180,14 +1096,6 @@ typedef struct FileDirEntryArr { char root[1024]; } FileDirEntryArr; -#if 0 /* UNUSED */ -/* FileDirEntry.status */ -enum { - ASSET_STATUS_LOCAL = 1 << 0, /* If active uuid is available locally/immediately. */ - ASSET_STATUS_LATEST = 1 << 1, /* If active uuid is latest available version. */ -}; -#endif - /* FileDirEntry.flags */ enum { FILE_ENTRY_INVALID_PREVIEW = 1 << 0, /* The preview for this entry could not be generated. */ @@ -2003,6 +1911,7 @@ typedef enum eSpreadsheetFilterOperation { typedef enum eSpaceSpreadsheet_ObjectEvalState { SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED = 0, SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL = 1, + SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE = 2, } eSpaceSpreadsheet_Context; typedef enum eSpaceSpreadsheet_ContextType { diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 60c255e8637..2308f04c4c7 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -219,10 +219,12 @@ typedef struct Tex { } Tex; -/* used for mapping and texture nodes. note: rot is now in radians */ - +/** Used for mapping and texture nodes. */ typedef struct TexMapping { - float loc[3], rot[3], size[3]; + float loc[3]; + /** Rotation in radians. */ + float rot[3]; + float size[3]; int flag; char projx, projy, projz, mapping; int type; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 7abd960c467..629aa191890 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -261,7 +261,7 @@ typedef struct ThemeSpace { /** Region background. */ unsigned char execution_buts[4]; - /* note, cannot use name 'panel' because of DNA mapping old files */ + /* NOTE: cannot use name 'panel' because of DNA mapping old files. */ uiPanelColors panelcolors; unsigned char shade1[4]; diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h index bc1a71102da..e782f7914b5 100644 --- a/source/blender/makesdna/DNA_vfont_types.h +++ b/source/blender/makesdna/DNA_vfont_types.h @@ -45,7 +45,7 @@ typedef struct VFont { struct PackedFile *packedfile; /* runtime only, holds memory for freetype to read from - * TODO, replace this with blf_font_new() style loading */ + * TODO: replace this with #blf_font_new() style loading. */ struct PackedFile *temp_pf; } VFont; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 80de5ae3b7c..08b29c82707 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -69,7 +69,7 @@ typedef struct RegionView3D { float clip_local[6][4]; struct BoundBox *clipbb; - /** Allocated backup of its self while in localview. */ + /** Allocated backup of its self while in local-view. */ struct RegionView3D *localvd; struct RenderEngine *render_engine; @@ -257,7 +257,7 @@ typedef struct View3D_Runtime { int flag; char _pad1[4]; - /* Only used for overlay stats while in localview. */ + /* Only used for overlay stats while in local-view. */ struct SceneStats *local_stats; } View3D_Runtime; @@ -295,7 +295,7 @@ typedef struct View3D { struct Object *camera, *ob_center; rctf render_border; - /** Allocated backup of its self while in localview. */ + /** Allocated backup of its self while in local-view. */ struct View3D *localvd; /** Optional string for armature bone to define center, MAXBONENAME. */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 59091fec4b8..94e89944f08 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -217,8 +217,8 @@ enum { #define WM_KEYCONFIG_STR_DEFAULT "Blender" -/* IME is win32 only! */ -#if !defined(WIN32) && !defined(DNA_DEPRECATED) +/* IME is win32 and apple only! */ +#if !(defined(WIN32) || defined(__APPLE__)) && !defined(DNA_DEPRECATED) # ifdef __GNUC__ # define ime_data ime_data __attribute__((deprecated)) # endif @@ -302,7 +302,7 @@ typedef struct wmWindow { struct wmGesture *tweak; /* Input Method Editor data - complex character input (especially for Asian character input) - * Currently WIN32, runtime-only data. */ + * Currently WIN32 and APPLE, runtime-only data. */ struct wmIMEData *ime_data; /** All events #wmEvent (ghost level events were handled). */ @@ -366,7 +366,7 @@ typedef struct wmKeyMapItem { short type; /** KM_ANY, KM_PRESS, KM_NOTHING etc. */ short val; - /** Oskey is apple or windowskey, value denotes order of pressed. */ + /** `oskey` also known as apple, windows-key or super, value denotes order of pressed. */ short shift, ctrl, alt, oskey; /** Raw-key modifier. */ short keymodifier; @@ -553,7 +553,7 @@ enum { /* in case operator got executed outside WM code... like via fileselect */ OPERATOR_HANDLED = (1 << 4), /* used for operators that act indirectly (eg. popup menu) - * note: this isn't great design (using operators to trigger UI) avoid where possible. */ + * NOTE: this isn't great design (using operators to trigger UI) avoid where possible. */ OPERATOR_INTERFACE = (1 << 5), }; #define OPERATOR_FLAGS_ALL \ diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h index c5c2351c718..9ed01a7dbcc 100644 --- a/source/blender/makesdna/DNA_workspace_types.h +++ b/source/blender/makesdna/DNA_workspace_types.h @@ -23,6 +23,7 @@ #pragma once #include "DNA_ID.h" +#include "DNA_asset_types.h" #ifdef __cplusplus extern "C" { @@ -135,6 +136,10 @@ typedef struct WorkSpace { /** Info text from modal operators (runtime). */ char *status_text; + + /** Workspace-wide active asset library, for asset UIs to use (e.g. asset view UI template). The + * Asset Browser has its own and doesn't use this. */ + AssetLibraryReference active_asset_library; } WorkSpace; /** @@ -165,7 +170,7 @@ typedef struct WorkSpaceDataRelation { /** The data used to identify the relation * (e.g. to find screen-layout (= value) from/for a hook). - * Note: Now runtime only. */ + * NOTE: Now runtime only. */ void *parent; /** The value for this parent-data/workspace relation. */ void *value; diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c index 2d55ea05867..a573e2f9e8c 100644 --- a/source/blender/makesdna/intern/dna_defaults.c +++ b/source/blender/makesdna/intern/dna_defaults.c @@ -152,6 +152,7 @@ /* DNA_asset_defaults.h */ SDNA_DEFAULT_DECL_STRUCT(AssetMetaData); +SDNA_DEFAULT_DECL_STRUCT(AssetLibraryReference); /* DNA_armature_defaults.h */ SDNA_DEFAULT_DECL_STRUCT(bArmature); @@ -315,6 +316,7 @@ SDNA_DEFAULT_DECL_STRUCT(TextureGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(ThickGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(TimeGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(TintGpencilModifierData); +SDNA_DEFAULT_DECL_STRUCT(WeightGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(LineartGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(LengthGpencilModifierData); @@ -347,6 +349,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = { /* DNA_asset_defaults.h */ SDNA_DEFAULT_DECL(AssetMetaData), + SDNA_DEFAULT_DECL(AssetLibraryReference), /* DNA_armature_defaults.h */ SDNA_DEFAULT_DECL(bArmature), @@ -541,6 +544,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = { SDNA_DEFAULT_DECL(ThickGpencilModifierData), SDNA_DEFAULT_DECL(TimeGpencilModifierData), SDNA_DEFAULT_DECL(TintGpencilModifierData), + SDNA_DEFAULT_DECL(WeightGpencilModifierData), SDNA_DEFAULT_DECL(LineartGpencilModifierData), SDNA_DEFAULT_DECL(LengthGpencilModifierData), }; diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 2a4bf53702f..d23b9441822 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -47,7 +47,7 @@ /** * \section dna_genfile Overview * - * - please note: no builtin security to detect input of double structs + * - please NOTE: no builtin security to detect input of double structs * - if you want a struct not to be in DNA file: add two hash marks above it `(#<enter>#<enter>)`. * * Structure DNA data is added to each blender file and to each executable, this to detect @@ -1060,7 +1060,7 @@ void DNA_struct_switch_endian(const SDNA *sdna, int struct_nr, char *data) } case SDNA_TYPE_INT: case SDNA_TYPE_FLOAT: { - /* Note, intentionally ignore long/ulong, because these could be 4 or 8 bytes. + /* NOTE: intentionally ignore long/ulong, because these could be 4 or 8 bytes. * Fortunately, we only use these types for runtime variables and only once for a * struct type that is no longer used. */ BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length); @@ -1398,7 +1398,7 @@ static void init_reconstruct_step_for_member(const SDNA *oldsdna, r_step->data.cast_pointer.array_len = shared_array_length; } else { - BLI_assert(!"invalid pointer size"); + BLI_assert_msg(0, "invalid pointer size"); r_step->type = RECONSTRUCT_STEP_INIT_ZERO; } break; diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index 735be0c10bf..d363e40e4f0 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -136,4 +136,5 @@ DNA_STRUCT_RENAME_ELEM(wmWindow, global_area_map, global_areas) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, mask_switches) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits) +DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numverts, num_bind_verts) DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits) diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 24cfc1d84f6..f2a75a60a44 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -43,6 +43,7 @@ #define DNA_DEPRECATED_ALLOW +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -272,6 +273,37 @@ void print_struct_sizes(void); * Make DNA string (write to file). * \{ */ +static bool match_identifier_with_len(const char *str, + const char *identifier, + const size_t identifier_len) +{ + if (strncmp(str, identifier, identifier_len) == 0) { + /* Check `str` isn't a prefix to a longer identifier. */ + if (isdigit(str[identifier_len]) || isalpha(str[identifier_len]) || + (str[identifier_len] == '_')) { + return false; + } + return true; + } + return false; +} + +static bool match_identifier(const char *str, const char *identifier) +{ + const size_t identifier_len = strlen(identifier); + return match_identifier_with_len(str, identifier, identifier_len); +} + +static bool match_identifier_and_advance(char **str_ptr, const char *identifier) +{ + const size_t identifier_len = strlen(identifier); + if (match_identifier_with_len(*str_ptr, identifier, identifier_len)) { + (*str_ptr) += identifier_len; + return true; + } + return false; +} + static const char *version_struct_static_from_alias(const char *str) { const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_static_from_alias, str); @@ -360,7 +392,7 @@ static int add_type(const char *str, int size) return -1; } if (strchr(str, '*')) { - /* note: this is valid C syntax but we can't parse, complain! + /* NOTE: this is valid C syntax but we can't parse, complain! * `struct SomeStruct* some_var;` <-- correct but we can't handle right now. */ return -1; } @@ -422,7 +454,7 @@ static int add_name(const char *str) int isfuncptr = (strchr(str + 1, '(')) != NULL; DEBUG_PRINTF(3, "\t\t\t\t*** Function pointer or multidim array pointer found\n"); - /* functionpointer: transform the type (sometimes) */ + /* function-pointer: transform the type (sometimes). */ int i = 0; while (str[i] != ')') { @@ -567,7 +599,7 @@ static short *add_struct(int namecode) static int preprocess_include(char *maindata, const int maindata_len) { - /* note: len + 1, last character is a dummy to prevent + /* NOTE: len + 1, last character is a dummy to prevent * comparisons using uninitialized memory */ char *temp = MEM_mallocN(maindata_len + 1, "preprocess_include"); temp[maindata_len] = ' '; @@ -619,7 +651,7 @@ static int preprocess_include(char *maindata, const int maindata_len) else if (cp[-1] == '*' && cp[0] == ' ') { /* pointers with a space */ } /* skip special keywords */ - else if (strncmp("DNA_DEPRECATED", cp, 14) == 0) { + else if (match_identifier(cp, "DNA_DEPRECATED")) { /* single values are skipped already, so decrement 1 less */ a -= 13; cp += 13; @@ -721,7 +753,7 @@ static int convert_include(const char *filename) md1++; /* we've got a struct name when... */ - if (strncmp(md1 - 7, "struct", 6) == 0) { + if (match_identifier(md1 - 7, "struct")) { const int strct = add_type(md1, 0); if (strct == -1) { @@ -756,14 +788,22 @@ static int convert_include(const char *filename) /* skip when it says 'struct' or 'unsigned' or 'const' */ if (*md1) { - if (strncmp(md1, "struct", 6) == 0) { - md1 += 7; - } - if (strncmp(md1, "unsigned", 8) == 0) { - md1 += 9; - } - if (strncmp(md1, "const", 5) == 0) { - md1 += 6; + const char *md1_prev = md1; + while (match_identifier_and_advance(&md1, "struct") || + match_identifier_and_advance(&md1, "unsigned") || + match_identifier_and_advance(&md1, "const")) { + if (UNLIKELY(!ELEM(*md1, '\0', ' '))) { + /* This will happen with: `unsigned(*value)[3]` which isn't supported. */ + fprintf(stderr, + "File '%s' contains non white space character " + "\"%c\" after identifier \"%s\"\n", + filename, + *md1, + md1_prev); + return 1; + } + /* Skip ' ' or '\0'. */ + md1++; } /* we've got a type! */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 876229411e0..97615016016 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -71,6 +71,8 @@ extern StructRNA RNA_ArrayGpencilModifier; extern StructRNA RNA_ArrayModifier; extern StructRNA RNA_Attribute; extern StructRNA RNA_AttributeGroup; +extern StructRNA RNA_AssetHandle; +extern StructRNA RNA_AssetLibraryReference; extern StructRNA RNA_AssetMetaData; extern StructRNA RNA_AssetTag; extern StructRNA RNA_BackgroundImage; @@ -450,6 +452,7 @@ extern StructRNA RNA_NodeOutputFileSlotFile; extern StructRNA RNA_NodeOutputFileSlotLayer; extern StructRNA RNA_NodeSocket; extern StructRNA RNA_NodeSocketInterface; +extern StructRNA RNA_NodeSocketStandard; extern StructRNA RNA_NodeTree; extern StructRNA RNA_NoiseGpencilModifier; extern StructRNA RNA_NoiseTexture; @@ -810,6 +813,7 @@ void RNA_struct_py_type_set(StructRNA *srna, void *py_type); void *RNA_struct_blender_type_get(StructRNA *srna); void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type); +struct IDProperty **RNA_struct_idprops_p(PointerRNA *ptr); struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create); bool RNA_struct_idprops_check(StructRNA *srna); bool RNA_struct_idprops_register_check(const StructRNA *type); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 71af69f77a1..d544083a749 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -204,6 +204,7 @@ extern const EnumPropertyItem rna_enum_node_vec_math_items[]; extern const EnumPropertyItem rna_enum_node_boolean_math_items[]; extern const EnumPropertyItem rna_enum_node_float_compare_items[]; extern const EnumPropertyItem rna_enum_node_filter_items[]; +extern const EnumPropertyItem rna_enum_node_float_to_int_items[]; extern const EnumPropertyItem rna_enum_node_map_range_items[]; extern const EnumPropertyItem rna_enum_node_clamp_items[]; @@ -244,6 +245,22 @@ extern const EnumPropertyItem *rna_enum_attribute_domain_itemf(struct ID *id, bo extern const EnumPropertyItem rna_enum_collection_color_items[]; +/** + * For ID filters (#FILTER_ID_AC, #FILTER_ID_AR, ...) an int isn't enough. This version allows 64 + * bit integers. So can't use the regular #EnumPropertyItem. Would be nice if RNA supported this + * itself. + * + * Meant to be used with #RNA_def_property_boolean_sdna() which supports 64 bit flags as well. + */ +struct IDFilterEnumPropertyItem { + const uint64_t flag; + const char *identifier; + const int icon; + const char *name; + const char *description; +}; +extern const struct IDFilterEnumPropertyItem rna_enum_id_type_filter_items[]; + /* API calls */ int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo); int rna_node_tree_idname_to_enum(const char *idname); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 96604b8a5fe..c2335b82fca 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -271,7 +271,7 @@ typedef enum PropertyFlag { /** * flag contains multiple enums. - * note: not to be confused with prop->enumbitflags + * NOTE: not to be confused with prop->enumbitflags * this exposes the flag as multiple options in python and the UI. * * \note These can't be animated so use with care. @@ -443,7 +443,7 @@ typedef struct CollectionListBase { typedef enum RawPropertyType { PROP_RAW_UNSET = -1, - PROP_RAW_INT, /* XXX - abused for types that are not set, eg. MFace.verts, needs fixing. */ + PROP_RAW_INT, /* XXX: abused for types that are not set, eg. MFace.verts, needs fixing. */ PROP_RAW_SHORT, PROP_RAW_CHAR, PROP_RAW_BOOLEAN, diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 5bf16baa1e8..719b0f73a9d 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2140,7 +2140,7 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property return; } - /* disabled for now to avoid msvc compiler error due to large file size */ + /* Disabled for now to avoid MSVC compiler error due to large file size. */ #if 0 if (prop->name && prop->description && prop->description[0] != '\0') { fprintf(f, "\t/* %s: %s */\n", prop->name, prop->description); @@ -2407,7 +2407,7 @@ static void rna_def_struct_function_prototype_cpp(FILE *f, static void rna_def_struct_function_header_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc) { if (dfunc->call) { - /* disabled for now to avoid msvc compiler error due to large file size */ + /* Disabled for now to avoid MSVC compiler error due to large file size. */ #if 0 FunctionRNA *func = dfunc->func; fprintf(f, "\n\t/* %s */\n", func->description); @@ -4449,7 +4449,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const fprintf(f, "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n\n"); #endif - fprintf(f, "/* Autogenerated Functions */\n\n"); + fprintf(f, "/* Auto-generated Functions. */\n\n"); for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { if (!filename || ds->filename == filename) { diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 43b65b087bf..6df03d19538 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -126,6 +126,97 @@ static const EnumPropertyItem rna_enum_override_library_property_operation_items {0, NULL, 0, NULL, NULL}, }; +/** + * \note Uses #IDFilterEnumPropertyItem, not EnumPropertyItem, to support 64 bit items. + */ +const struct IDFilterEnumPropertyItem rna_enum_id_type_filter_items[] = { + /* Datablocks */ + {FILTER_ID_AC, "filter_action", ICON_ANIM_DATA, "Actions", "Show Action data-blocks"}, + {FILTER_ID_AR, + "filter_armature", + ICON_ARMATURE_DATA, + "Armatures", + "Show Armature data-blocks"}, + {FILTER_ID_BR, "filter_brush", ICON_BRUSH_DATA, "Brushes", "Show Brushes data-blocks"}, + {FILTER_ID_CA, "filter_camera", ICON_CAMERA_DATA, "Cameras", "Show Camera data-blocks"}, + {FILTER_ID_CF, "filter_cachefile", ICON_FILE, "Cache Files", "Show Cache File data-blocks"}, + {FILTER_ID_CU, "filter_curve", ICON_CURVE_DATA, "Curves", "Show Curve data-blocks"}, + {FILTER_ID_GD, + "filter_grease_pencil", + ICON_GREASEPENCIL, + "Grease Pencil", + "Show Grease pencil data-blocks"}, + {FILTER_ID_GR, + "filter_group", + ICON_OUTLINER_COLLECTION, + "Collections", + "Show Collection data-blocks"}, + {FILTER_ID_HA, "filter_hair", ICON_HAIR_DATA, "Hairs", "Show/hide Hair data-blocks"}, + {FILTER_ID_IM, "filter_image", ICON_IMAGE_DATA, "Images", "Show Image data-blocks"}, + {FILTER_ID_LA, "filter_light", ICON_LIGHT_DATA, "Lights", "Show Light data-blocks"}, + {FILTER_ID_LP, + "filter_light_probe", + ICON_OUTLINER_DATA_LIGHTPROBE, + "Light Probes", + "Show Light Probe data-blocks"}, + {FILTER_ID_LS, + "filter_linestyle", + ICON_LINE_DATA, + "Freestyle Linestyles", + "Show Freestyle's Line Style data-blocks"}, + {FILTER_ID_LT, "filter_lattice", ICON_LATTICE_DATA, "Lattices", "Show Lattice data-blocks"}, + {FILTER_ID_MA, + "filter_material", + ICON_MATERIAL_DATA, + "Materials", + "Show Material data-blocks"}, + {FILTER_ID_MB, "filter_metaball", ICON_META_DATA, "Metaballs", "Show Metaball data-blocks"}, + {FILTER_ID_MC, + "filter_movie_clip", + ICON_TRACKER_DATA, + "Movie Clips", + "Show Movie Clip data-blocks"}, + {FILTER_ID_ME, "filter_mesh", ICON_MESH_DATA, "Meshes", "Show Mesh data-blocks"}, + {FILTER_ID_MSK, "filter_mask", ICON_MOD_MASK, "Masks", "Show Mask data-blocks"}, + {FILTER_ID_NT, "filter_node_tree", ICON_NODETREE, "Node Trees", "Show Node Tree data-blocks"}, + {FILTER_ID_OB, "filter_object", ICON_OBJECT_DATA, "Objects", "Show Object data-blocks"}, + {FILTER_ID_PA, + "filter_particle_settings", + ICON_PARTICLE_DATA, + "Particles Settings", + "Show Particle Settings data-blocks"}, + {FILTER_ID_PAL, "filter_palette", ICON_COLOR, "Palettes", "Show Palette data-blocks"}, + {FILTER_ID_PC, + "filter_paint_curve", + ICON_CURVE_BEZCURVE, + "Paint Curves", + "Show Paint Curve data-blocks"}, + {FILTER_ID_PT, + "filter_pointcloud", + ICON_POINTCLOUD_DATA, + "Point Clouds", + "Show/hide Point Cloud data-blocks"}, + {FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"}, + {FILTER_ID_SIM, + "filter_simulation", + ICON_PHYSICS, + "Simulations", + "Show Simulation data-blocks"}, /* TODO: Use correct icon. */ + {FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"}, + {FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"}, + {FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"}, + {FILTER_ID_TXT, "filter_text", ICON_TEXT, "Texts", "Show Text data-blocks"}, + {FILTER_ID_VF, "filter_font", ICON_FONT_DATA, "Fonts", "Show Font data-blocks"}, + {FILTER_ID_VO, "filter_volume", ICON_VOLUME_DATA, "Volumes", "Show/hide Volume data-blocks"}, + {FILTER_ID_WO, "filter_world", ICON_WORLD_DATA, "Worlds", "Show World data-blocks"}, + {FILTER_ID_WS, + "filter_work_space", + ICON_WORKSPACE, + "Workspaces", + "Show workspace data-blocks"}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME # include "DNA_anim_types.h" @@ -384,7 +475,7 @@ short RNA_type_to_ID_code(const StructRNA *type) StructRNA *ID_code_to_RNA_type(short idcode) { - /* Note, this switch doesn't use a 'default', + /* NOTE: this switch doesn't use a 'default', * so adding new ID's causes a warning. */ switch ((ID_Type)idcode) { case ID_AC: @@ -493,9 +584,10 @@ StructRNA *rna_ID_refine(PointerRNA *ptr) return ID_code_to_RNA_type(GS(id->name)); } -IDProperty *rna_ID_idprops(PointerRNA *ptr, bool create) +IDProperty **rna_ID_idprops(PointerRNA *ptr) { - return IDP_GetProperties(ptr->data, create); + ID *id = (ID *)ptr->data; + return &id->properties; } void rna_ID_fake_user_set(PointerRNA *ptr, bool value) @@ -510,9 +602,9 @@ void rna_ID_fake_user_set(PointerRNA *ptr, bool value) } } -IDProperty *rna_PropertyGroup_idprops(PointerRNA *ptr, bool UNUSED(create)) +IDProperty **rna_PropertyGroup_idprops(PointerRNA *ptr) { - return ptr->data; + return (IDProperty **)&ptr->data; } void rna_PropertyGroup_unregister(Main *UNUSED(bmain), StructRNA *type) @@ -538,7 +630,7 @@ StructRNA *rna_PropertyGroup_register(Main *UNUSED(bmain), return NULL; } - /* note: it looks like there is no length limit on the srna id since its + /* NOTE: it looks like there is no length limit on the srna id since its * just a char pointer, but take care here, also be careful that python * owns the string pointer which it could potentially free while blender * is running. */ @@ -772,7 +864,7 @@ static struct ID *rna_ID_make_local(struct ID *self, Main *bmain, bool clear_pro static AnimData *rna_ID_animation_data_create(ID *id, Main *bmain) { - AnimData *adt = BKE_animdata_add_id(id); + AnimData *adt = BKE_animdata_ensure_id(id); DEG_relations_tag_update(bmain); return adt; } @@ -1162,12 +1254,12 @@ static PointerRNA rna_IDPreview_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img); } -static IDProperty *rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr, bool UNUSED(create)) +static IDProperty **rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr) { if (ptr == NULL) { return NULL; } - return ptr->data; + return (IDProperty **)&ptr->data; } static void rna_Library_version_get(PointerRNA *ptr, int *value) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 840da76403a..0285ef44e17 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -369,15 +369,32 @@ static bool rna_idproperty_ui_set_default(PointerRNA *ptr, return true; } -IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create) +IDProperty **RNA_struct_idprops_p(PointerRNA *ptr) { StructRNA *type = ptr->type; + if (type == NULL) { + return NULL; + } + if (type->idproperties == NULL) { + return NULL; + } - if (type && type->idproperties) { - return type->idproperties(ptr, create); + return type->idproperties(ptr); +} + +IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create) +{ + IDProperty **property_ptr = RNA_struct_idprops_p(ptr); + if (property_ptr == NULL) { + return NULL; } - return NULL; + if (create && *property_ptr == NULL) { + IDPropertyTemplate val = {0}; + *property_ptr = IDP_New(IDP_GROUP, &val, __func__); + } + + return *property_ptr; } bool RNA_struct_idprops_check(StructRNA *srna) @@ -692,7 +709,7 @@ static const char *rna_ensure_property_description(const PropertyRNA *prop) } if (description == NULL) { - description = ((IDProperty *)prop)->name; /* XXX - not correct */ + description = ((IDProperty *)prop)->name; /* XXX: not correct. */ } } @@ -907,7 +924,7 @@ static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna) bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test) { - /* note, prop_test could be freed memory, only use for comparison */ + /* NOTE: prop_test could be freed memory, only use for comparison. */ /* validate the RNA is ok */ PropertyRNA *iterprop; @@ -1691,7 +1708,7 @@ static void property_enum_translate(PropertyRNA *prop, if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) { int i; - /* Note: Only do those tests once, and then use BLT_pgettext. */ + /* NOTE: Only do those tests once, and then use BLT_pgettext. */ bool do_iface = BLT_translate_iface(); bool do_tooltip = BLT_translate_tooltips(); EnumPropertyItem *nitem; @@ -2026,11 +2043,9 @@ bool RNA_property_enum_item_from_value( bool RNA_property_enum_item_from_value_gettexted( bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item) { - bool result; + const bool result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item); - result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item); - - if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) { + if (result && !(prop->flag & PROP_ENUM_NO_TRANSLATE)) { if (BLT_translate_iface()) { r_item->name = BLT_pgettext(prop->translation_context, r_item->name); } @@ -2325,7 +2340,7 @@ static void rna_property_update( } /* must keep in sync with 'rna_property_update' - * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE + * NOTE: its possible this returns a false positive in the case of #PROP_CONTEXT_UPDATE * but this isn't likely to be a performance problem. */ bool RNA_property_update_check(PropertyRNA *prop) { @@ -5812,7 +5827,7 @@ static char *rna_path_from_ID_to_idpgroup(PointerRNA *ptr) BLI_assert(ptr->owner_id != NULL); - /* TODO, Support Bones/PoseBones. no pointers stored to the bones from here, only the ID. + /* TODO: Support Bones/PoseBones. no pointers stored to the bones from here, only the ID. * See example in T25746. * Unless this is added only way to find this is to also search * all bones and pose bones of an armature or object. @@ -5849,12 +5864,12 @@ ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path) *r_path = "collection"; break; default: - BLI_assert(!"Missing handling of embedded id type."); + BLI_assert_msg(0, "Missing handling of embedded id type."); } } if (id_type->owner_get == NULL) { - BLI_assert(!"Missing handling of embedded id type."); + BLI_assert_msg(0, "Missing handling of embedded id type."); return id; } return id_type->owner_get(bmain, id); @@ -6244,8 +6259,8 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index) data_path = RNA_path_from_ID_to_property(ptr, prop); if (data_path == NULL) { - /* this may not be an ID at all, check for simple when pointer owns property. - * TODO, more complex nested case */ + /* This may not be an ID at all, check for simple when pointer owns property. + * TODO: more complex nested case. */ if (!RNA_struct_is_ID(ptr->type)) { const char *prop_identifier = RNA_property_identifier(prop); if (RNA_struct_find_property(ptr, prop_identifier) == prop) { @@ -6559,7 +6574,7 @@ char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, in PropertyRNA *prop = RNA_struct_find_property(ptr, name); if (prop) { - /* TODO, pass length */ + /* TODO: pass length. */ return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen, NULL); } printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name); diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c index c84ef1a6587..3912c873fd0 100644 --- a/source/blender/makesrna/intern/rna_access_compare_override.c +++ b/source/blender/makesrna/intern/rna_access_compare_override.c @@ -132,7 +132,7 @@ bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop) { if (prop->magic == RNA_MAGIC) { /* Special handling for insertions of constraints or modifiers... */ - /* TODO Note We may want to add a more generic system to RNA + /* TODO: Note We may want to add a more generic system to RNA * (like a special property in struct of items) * if we get more overridable collections, * for now we can live with those special-cases handling I think. */ @@ -234,7 +234,7 @@ bool RNA_property_copy( prop_src = rna_ensure_property_realdata(&prop_src, fromptr); /* IDprops: destination may not exist, if source does and is set, try to create it. */ - /* Note: this is sort of quick hack/bandage to fix the issue, + /* NOTE: this is sort of quick hack/bandage to fix the issue, * we need to rethink how IDProps are handled in 'diff' RNA code completely, imho... */ if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) { BLI_assert(prop_src->magic != RNA_MAGIC); @@ -422,7 +422,9 @@ static int rna_property_override_diff(Main *bmain, bool override_changed = false; eRNAOverrideMatch diff_flags = flags; - if (!RNA_property_overridable_get(&prop_a->ptr, prop_a->rawprop)) { + if (!RNA_property_overridable_get(&prop_a->ptr, prop_a->rawprop) || + (!ELEM(RNA_property_type(prop_a->rawprop), PROP_POINTER, PROP_COLLECTION) && + !RNA_property_editable_flag(&prop_a->ptr, prop_a->rawprop))) { diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE; } const int diff = override_diff(bmain, @@ -681,7 +683,7 @@ bool RNA_struct_override_matches(Main *bmain, * ensure this is valid, but in some situations (like hidden collections etc.) this won't * be the case, so we need to take care of this ourselves. * - * Note: Typically callers of this function (from BKE_lib_override area) will already have + * NOTE: Typically callers of this function (from BKE_lib_override area) will already have * ensured this. However, studio is still reporting sporadic, unreproducible crashes due to * invalid pose data, so think there are still some cases where some armatures are somehow * missing updates (possibly due to dependencies?). Since calling this function on same ID @@ -741,7 +743,7 @@ bool RNA_struct_override_matches(Main *bmain, char *rna_path = rna_path_buffer; size_t rna_path_len = 0; - /* XXX TODO this will have to be refined to handle collections insertions, and array items */ + /* XXX TODO: this will have to be refined to handle collections insertions, and array items. */ if (root_path) { BLI_assert(strlen(root_path) == root_path_len); @@ -865,7 +867,7 @@ bool RNA_struct_override_matches(Main *bmain, else { /* Too noisy for now, this triggers on runtime props like transform matrices etc. */ #if 0 - BLI_assert(!"We have differences between reference and " + BLI_assert_msg(0, "We have differences between reference and " "overriding data on non-editable property."); #endif matching = false; @@ -1138,7 +1140,7 @@ static void rna_property_override_apply_ex(Main *bmain, continue; } - /* Note: will have to think about putting that logic into its own function maybe? + /* NOTE: will have to think about putting that logic into its own function maybe? * Would be nice to have it in a single place... * Note that here, src is the local saved ID, and dst is a copy of the linked ID (since we use * local ID as storage to apply local changes on top of a clean copy of the linked data). */ @@ -1192,7 +1194,7 @@ void RNA_struct_override_apply(Main *bmain, #ifdef DEBUG_OVERRIDE_TIMEIT TIMEIT_START_AVERAGED(RNA_struct_override_apply); #endif - /* Note: Applying insert operations in a separate pass is mandatory. + /* NOTE: Applying insert operations in a separate pass is mandatory. * We could optimize this later, but for now, as inefficient as it is, * don't think this is a critical point. */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index b3b0d7d13f7..49d02524e43 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -260,28 +260,16 @@ static char *rna_Bone_path(PointerRNA *ptr) return BLI_sprintfN("bones[\"%s\"]", name_esc); } -static IDProperty *rna_Bone_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_Bone_idprops(PointerRNA *ptr) { Bone *bone = ptr->data; - - if (create && !bone->prop) { - IDPropertyTemplate val = {0}; - bone->prop = IDP_New(IDP_GROUP, &val, "RNA_Bone ID properties"); - } - - return bone->prop; + return &bone->prop; } -static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_EditBone_idprops(PointerRNA *ptr) { EditBone *ebone = ptr->data; - - if (create && !ebone->prop) { - IDPropertyTemplate val = {0}; - ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); - } - - return ebone->prop; + return &ebone->prop; } static void rna_bone_layer_set(int *layer, const bool *values) @@ -1395,7 +1383,7 @@ static void rna_def_armature_bones(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_ui_text(prop, "Active Bone", "Armature's active bone"); RNA_def_property_pointer_funcs(prop, NULL, "rna_Armature_act_bone_set", NULL, NULL); - /* todo, redraw */ + /* TODO: redraw. */ /* RNA_def_property_collection_active(prop, prop_act); */ } @@ -1421,7 +1409,7 @@ static void rna_def_armature_edit_bones(BlenderRNA *brna, PropertyRNA *cprop) /*RNA_def_property_update(prop, 0, "rna_Armature_act_editbone_update"); */ RNA_def_property_pointer_funcs(prop, NULL, "rna_Armature_act_edit_bone_set", NULL, NULL); - /* todo, redraw */ + /* TODO: redraw. */ /* RNA_def_property_collection_active(prop, prop_act); */ /* add target */ diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c index 1af53e95cc9..0020d90ba1a 100644 --- a/source/blender/makesrna/intern/rna_asset.c +++ b/source/blender/makesrna/intern/rna_asset.c @@ -25,6 +25,7 @@ #include "DNA_asset_types.h" #include "DNA_defs.h" +#include "DNA_space_types.h" #include "rna_internal.h" @@ -35,6 +36,8 @@ # include "BLI_listbase.h" +# include "ED_asset.h" + # include "RNA_access.h" static AssetTag *rna_AssetMetaData_tag_new(AssetMetaData *asset_data, @@ -75,16 +78,10 @@ static void rna_AssetMetaData_tag_remove(AssetMetaData *asset_data, RNA_POINTER_INVALIDATE(tag_ptr); } -static IDProperty *rna_AssetMetaData_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_AssetMetaData_idprops(PointerRNA *ptr) { AssetMetaData *asset_data = ptr->data; - - if (create && !asset_data->properties) { - IDPropertyTemplate val = {0}; - asset_data->properties = IDP_New(IDP_GROUP, &val, "RNA_AssetMetaData group"); - } - - return asset_data->properties; + return &asset_data->properties; } static void rna_AssetMetaData_description_get(PointerRNA *ptr, char *value) @@ -129,6 +126,105 @@ static void rna_AssetMetaData_active_tag_range( *max = *softmax = MAX2(asset_data->tot_tags - 1, 0); } +static PointerRNA rna_AssetHandle_file_data_get(PointerRNA *ptr) +{ + AssetHandle *asset_handle = ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_FileSelectEntry, asset_handle->file_data); +} + +static void rna_AssetHandle_get_full_library_path( + // AssetHandle *asset, + bContext *C, + FileDirEntry *asset_file, + AssetLibraryReference *library, + char r_result[/*FILE_MAX_LIBEXTRA*/]) +{ + AssetHandle asset = {.file_data = asset_file}; + ED_asset_handle_get_full_library_path(C, library, &asset, r_result); +} + +static PointerRNA rna_AssetHandle_local_id_get(PointerRNA *ptr) +{ + const AssetHandle *asset = ptr->data; + ID *id = ED_assetlist_asset_local_id_get(asset); + return rna_pointer_inherit_refine(ptr, &RNA_ID, id); +} + +static void rna_AssetHandle_file_data_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) +{ + AssetHandle *asset_handle = ptr->data; + asset_handle->file_data = value.data; +} + +int rna_asset_library_reference_get(const AssetLibraryReference *library) +{ + return ED_asset_library_reference_to_enum_value(library); +} + +void rna_asset_library_reference_set(AssetLibraryReference *library, int value) +{ + *library = ED_asset_library_reference_from_enum_value(value); +} + +const EnumPropertyItem *rna_asset_library_reference_itemf(bContext *UNUSED(C), + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + const EnumPropertyItem predefined_items[] = { + /* For the future. */ + // {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"}, + {ASSET_LIBRARY_LOCAL, + "LOCAL", + ICON_BLENDER, + "Current File", + "Show the assets currently available in this Blender session"}, + {0, NULL, 0, NULL, NULL}, + }; + + EnumPropertyItem *item = NULL; + int totitem = 0; + + /* Add separator if needed. */ + if (!BLI_listbase_is_empty(&U.asset_libraries)) { + const EnumPropertyItem sepr = {0, "", 0, "Custom", NULL}; + RNA_enum_item_add(&item, &totitem, &sepr); + } + + int i = 0; + for (bUserAssetLibrary *user_library = U.asset_libraries.first; user_library; + user_library = user_library->next, i++) { + /* Note that the path itself isn't checked for validity here. If an invalid library path is + * used, the Asset Browser can give a nice hint on what's wrong. */ + const bool is_valid = (user_library->name[0] && user_library->path[0]); + if (!is_valid) { + continue; + } + + /* Use library path as description, it's a nice hint for users. */ + EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i, + user_library->name, + ICON_NONE, + user_library->name, + user_library->path}; + RNA_enum_item_add(&item, &totitem, &tmp); + } + + if (totitem) { + const EnumPropertyItem sepr = {0, "", 0, "Built-in", NULL}; + RNA_enum_item_add(&item, &totitem, &sepr); + } + + /* Add predefined items. */ + RNA_enum_items_add(&item, &totitem, predefined_items); + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + return item; +} + #else static void rna_def_asset_tag(BlenderRNA *brna) @@ -215,12 +311,87 @@ static void rna_def_asset_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Active Tag", "Index of the tag set for editing"); } +static void rna_def_asset_handle_api(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func = RNA_def_function(srna, "get_full_library_path", "rna_AssetHandle_get_full_library_path"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + /* TODO temporarily static function, for until .py can receive the asset handle from context + * properly. `asset_file_handle` should go away too then. */ + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "asset_file_handle", "FileSelectEntry", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, + "asset_library", + "AssetLibraryReference", + "", + "The asset library containing the given asset, only valid if the asset " + "library is external (i.e. not the \"Current File\" one"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "result", NULL, FILE_MAX_LIBEXTRA, "result", ""); + RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); + RNA_def_function_output(func, parm); +} + +static void rna_def_asset_handle(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "AssetHandle", "PropertyGroup"); + RNA_def_struct_ui_text(srna, "Asset Handle", "Reference to some asset"); + + /* TODO why is this editable? There probably shouldn't be a setter. */ + prop = RNA_def_property(srna, "file_data", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "FileSelectEntry"); + RNA_def_property_pointer_funcs( + prop, "rna_AssetHandle_file_data_get", "rna_AssetHandle_file_data_set", NULL, NULL); + RNA_def_property_ui_text(prop, "File Entry", "File data used to refer to the asset"); + + prop = RNA_def_property(srna, "local_id", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ID"); + RNA_def_property_pointer_funcs(prop, "rna_AssetHandle_local_id_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, + "", + "The local data-block this asset represents; only valid if that is a " + "data-block in this file"); + RNA_def_property_flag(prop, PROP_HIDDEN); + + rna_def_asset_handle_api(srna); +} + +static void rna_def_asset_library_reference(BlenderRNA *brna) +{ + StructRNA *srna = RNA_def_struct(brna, "AssetLibraryReference", NULL); + RNA_def_struct_ui_text( + srna, "Asset Library Reference", "Identifier to refere to the asset library"); +} + +/** + * \note the UI text and updating has to be set by the caller. + */ +PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna, + const char *get, + const char *set) +{ + PropertyRNA *prop = RNA_def_property(srna, "active_asset_library", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, DummyRNA_NULL_items); + RNA_def_property_enum_funcs(prop, get, set, "rna_asset_library_reference_itemf"); + + return prop; +} + void RNA_def_asset(BlenderRNA *brna) { RNA_define_animate_sdna(false); rna_def_asset_tag(brna); rna_def_asset_data(brna); + rna_def_asset_library_reference(brna); + rna_def_asset_handle(brna); RNA_define_animate_sdna(true); } diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 7e1d513502c..2b09ea51a84 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1486,7 +1486,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) prop = RNA_def_property(srna, "uv_random", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "uv_random"); RNA_def_property_range(prop, 0.0, 1.0); - RNA_def_property_ui_text(prop, "UV Random", "Random factor for autogenerated UV rotation"); + RNA_def_property_ui_text(prop, "UV Random", "Random factor for auto-generated UV rotation"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); @@ -3260,7 +3260,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - /* only for projection paint & vertex paint, TODO, other paint modes */ + /* only for projection paint & vertex paint, TODO: other paint modes. */ prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_LOCK_ALPHA); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 9e57368f8f9..2bc00dd5af5 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -652,7 +652,6 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_UNIT_MASS); RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_text(prop, "Vertex Mass", "The mass of each vertex on the cloth material"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_cloth_update"); prop = RNA_def_property(srna, "vertex_group_mass", PROP_STRING, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c index 577a3273e21..752c9495e50 100644 --- a/source/blender/makesrna/intern/rna_collection.c +++ b/source/blender/makesrna/intern/rna_collection.c @@ -189,7 +189,7 @@ static bool rna_Collection_objects_override_apply(Main *bmain, return false; } - /* XXX TODO We most certainly rather want to have a 'swap object pointer in collection' + /* XXX TODO: We most certainly rather want to have a 'swap object pointer in collection' * util in BKE_collection. This is only temp quick dirty test! */ id_us_min(&cob_dst->ob->id); cob_dst->ob = ob_src; @@ -292,7 +292,7 @@ static bool rna_Collection_children_override_apply(Main *bmain, return false; } - /* XXX TODO We most certainly rather want to have a 'swap object pointer in collection' + /* XXX TODO: We most certainly rather want to have a 'swap object pointer in collection' * util in BKE_collection. This is only temp quick dirty test! */ id_us_min(&collchild_dst->collection->id); collchild_dst->collection = subcoll_src; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 39a44d7568a..9faf2ae7cb7 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -971,7 +971,7 @@ static void rna_def_color_ramp_element_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_struct_path_func(srna, "rna_ColorRampElement_path"); RNA_def_struct_ui_text(srna, "Color Ramp Elements", "Collection of Color Ramp Elements"); - /* TODO, make these functions generic in texture.c */ + /* TODO: make these functions generic in `texture.c`. */ func = RNA_def_function(srna, "new", "rna_ColorRampElement_new"); RNA_def_function_ui_description(func, "Add element to ColorRamp"); RNA_def_function_flag(func, FUNC_USE_REPORTS); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index d79f2c4d13f..3064703b02e 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -206,6 +206,7 @@ static const EnumPropertyItem target_space_pchan_items[] = { "Custom Space", "The transformation of the target is evaluated relative to a custom object/bone/vertex " "group"}, + {0, "", 0, NULL, NULL}, {CONSTRAINT_SPACE_POSE, "POSE", 0, @@ -224,6 +225,14 @@ static const EnumPropertyItem target_space_pchan_items[] = { "Local Space", "The transformation of the target is evaluated relative to its local " "coordinate system"}, + {CONSTRAINT_SPACE_OWNLOCAL, + "LOCAL_OWNER_ORIENT", + 0, + "Local Space (Owner Orientation)", + "The transformation of the target bone is evaluated relative to its local coordinate " + "system, followed by a correction for the difference in target and owner rest pose " + "orientations. When applied as local transform to the owner produces the same global " + "motion as the target if the parents are still in rest pose"}, {0, NULL, 0, NULL, NULL}, }; @@ -238,6 +247,7 @@ static const EnumPropertyItem owner_space_pchan_items[] = { 0, "Custom Space", "The constraint is applied in local space of a custom object/bone/vertex group"}, + {0, "", 0, NULL, NULL}, {CONSTRAINT_SPACE_POSE, "POSE", 0, @@ -1624,18 +1634,48 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna) 0, "Replace", "Replace the original transformation with copied"}, + {0, "", 0, NULL, NULL}, + {TRANSLIKE_MIX_BEFORE_FULL, + "BEFORE_FULL", + 0, + "Before Original (Full)", + "Apply copied transformation before original, using simple matrix multiplication as if " + "the constraint target is a parent in Full Inherit Scale mode. " + "Will create shear when combining rotation and non-uniform scale"}, {TRANSLIKE_MIX_BEFORE, "BEFORE", 0, - "Before Original", - "Apply copied transformation before original, as if the constraint target is a parent. " - "Scale is handled specially to avoid creating shear"}, + "Before Original (Aligned)", + "Apply copied transformation before original, as if the constraint target is a parent in " + "Aligned Inherit Scale mode. This effectively uses Full for location and Split Channels " + "for rotation and scale"}, + {TRANSLIKE_MIX_BEFORE_SPLIT, + "BEFORE_SPLIT", + 0, + "Before Original (Split Channels)", + "Apply copied transformation before original, handling location, rotation and scale " + "separately, similar to a sequence of three Copy constraints"}, + {0, "", 0, NULL, NULL}, + {TRANSLIKE_MIX_AFTER_FULL, + "AFTER_FULL", + 0, + "After Original (Full)", + "Apply copied transformation after original, using simple matrix multiplication as if " + "the constraint target is a child in Full Inherit Scale mode. " + "Will create shear when combining rotation and non-uniform scale"}, {TRANSLIKE_MIX_AFTER, "AFTER", 0, - "After Original", - "Apply copied transformation after original, as if the constraint target is a child. " - "Scale is handled specially to avoid creating shear"}, + "After Original (Aligned)", + "Apply copied transformation after original, as if the constraint target is a child in " + "Aligned Inherit Scale mode. This effectively uses Full for location and Split Channels " + "for rotation and scale"}, + {TRANSLIKE_MIX_AFTER_SPLIT, + "AFTER_SPLIT", + 0, + "After Original (Split Channels)", + "Apply copied transformation after original, handling location, rotation and scale " + "separately, similar to a sequence of three Copy constraints"}, {0, NULL, 0, NULL, NULL}, }; @@ -1653,6 +1693,12 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna) RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "remove_target_shear", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRANSLIKE_REMOVE_TARGET_SHEAR); + RNA_def_property_ui_text( + prop, "Remove Target Shear", "Remove shear from the target transformation before combining"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mix_mode"); RNA_def_property_enum_items(prop, mix_mode_items); @@ -2795,7 +2841,7 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) RNA_define_lib_overridable(true); prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO, mesh type */ + RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO: mesh type. */ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll"); RNA_def_property_ui_text(prop, "Target", "Target Mesh object"); RNA_def_property_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c index 4079406e64b..9da08de2168 100644 --- a/source/blender/makesrna/intern/rna_context.c +++ b/source/blender/makesrna/intern/rna_context.c @@ -58,6 +58,8 @@ const EnumPropertyItem rna_enum_context_mode_items[] = { #ifdef RNA_RUNTIME +# include "DNA_asset_types.h" + # ifdef WITH_PYTHON # include "BPY_extern.h" # endif @@ -134,6 +136,20 @@ static PointerRNA rna_Context_gizmo_group_get(PointerRNA *ptr) return newptr; } +static PointerRNA rna_Context_asset_file_handle_get(PointerRNA *ptr) +{ + bContext *C = (bContext *)ptr->data; + bool is_handle_valid; + AssetHandle asset_handle = CTX_wm_asset_handle(C, &is_handle_valid); + if (!is_handle_valid) { + return PointerRNA_NULL; + } + + PointerRNA newptr; + RNA_pointer_create(NULL, &RNA_FileSelectEntry, asset_handle.file_data, &newptr); + return newptr; +} + static PointerRNA rna_Context_main_get(PointerRNA *ptr) { bContext *C = (bContext *)ptr->data; @@ -281,6 +297,17 @@ void RNA_def_context(BlenderRNA *brna) RNA_def_property_struct_type(prop, "GizmoGroup"); RNA_def_property_pointer_funcs(prop, "rna_Context_gizmo_group_get", NULL, NULL, NULL); + /* TODO can't expose AssetHandle, since there is no permanent storage to it (so we can't + * return a pointer). Instead provide the FileDirEntry pointer it wraps. */ + prop = RNA_def_property(srna, "asset_file_handle", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "FileSelectEntry"); + RNA_def_property_pointer_funcs(prop, "rna_Context_asset_file_handle_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, + "", + "The file of an active asset. Avoid using this, it will be replaced by " + "a proper AssetHandle design"); + /* Data */ prop = RNA_def_property(srna, "blend_data", PROP_POINTER, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 299cd2504a8..9c6659a7130 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -591,7 +591,7 @@ static int rna_Curve_body_length(PointerRNA *ptr) return cu->len; } -/* TODO, how to handle editmode? */ +/* TODO: how to handle editmode? */ static void rna_Curve_body_set(PointerRNA *ptr, const char *value) { size_t len_bytes; @@ -1802,7 +1802,7 @@ static void rna_def_curve(BlenderRNA *brna) prop, "End Mapping Type", "Determine how the geometry end factor is mapped to a spline"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - /* XXX - would be nice to have a better way to do this, only add for testing. */ + /* XXX: would be nice to have a better way to do this, only add for testing. */ prop = RNA_def_property(srna, "twist_smooth", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "twist_smooth"); RNA_def_property_ui_range(prop, 0, 100.0, 1, 2); @@ -2017,7 +2017,7 @@ static void rna_def_curve_nurb(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Cyclic V", "Make this surface a closed loop in the V direction"); RNA_def_property_update(prop, 0, "rna_Nurb_update_cyclic_v"); - /* Note, endpoint and bezier flags should never be on at the same time! */ + /* NOTE: endpoint and bezier flags should never be on at the same time! */ prop = RNA_def_property(srna, "use_endpoint_u", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flagu", CU_NURB_ENDPOINT); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 0c6c3fd9b0a..fadce9e3c89 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -52,7 +52,7 @@ static CLG_LogRef LOG = {"rna.define"}; # define ASSERT_SOFT_HARD_LIMITS \ if (softmin < hardmin || softmax > hardmax) { \ CLOG_ERROR(&LOG, "error with soft/hard limits: %s.%s", CONTAINER_RNA_ID(cont), identifier); \ - BLI_assert(!"invalid soft/hard limits"); \ + BLI_assert_msg(0, "invalid soft/hard limits"); \ } \ (void)0 #else @@ -781,7 +781,7 @@ void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *rna_ext) { #ifdef RNA_RUNTIME rna_ext->free(rna_ext->data); /* decref's the PyObject that the srna owns */ - RNA_struct_blender_type_set(srna, NULL); /* this gets accessed again - XXX fixme */ + RNA_struct_blender_type_set(srna, NULL); /* FIXME: this gets accessed again. */ /* NULL the srna's value so RNA_struct_free won't complain of a leak */ RNA_struct_py_type_set(srna, NULL); @@ -4759,7 +4759,7 @@ static void rna_def_property_free(StructOrFunctionRNA *cont_, PropertyRNA *prop) } } -/* note: only intended for removing dynamic props */ +/* NOTE: only intended for removing dynamic props. */ int RNA_def_property_free_identifier(StructOrFunctionRNA *cont_, const char *identifier) { ContainerRNA *cont = cont_; diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index 0dfd7d74c25..a9d5ef089bb 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -342,8 +342,8 @@ static void rna_def_canvas_surface(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; - /* Effect type - * Only used by ui to view per effect settings */ + /* Effect type + * Only used by UI to view per effect settings. */ static const EnumPropertyItem prop_dynamicpaint_effecttype[] = { {1, "SPREAD", 0, "Spread", ""}, {2, "DRIP", 0, "Drip", ""}, @@ -351,7 +351,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; - /* Displacemap file format */ + /* Displace-map file format. */ static const EnumPropertyItem prop_dynamicpaint_image_fileformat[] = { {MOD_DPAINT_IMGFORMAT_PNG, "PNG", 0, "PNG", ""}, # ifdef WITH_OPENEXR @@ -360,7 +360,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; - /* Displacemap type */ + /* Displace-map type. */ static const EnumPropertyItem prop_dynamicpaint_displace_type[] = { {MOD_DPAINT_DISP_DISPLACE, "DISPLACE", 0, "Displacement", ""}, {MOD_DPAINT_DISP_DEPTH, "DEPTH", 0, "Depth", ""}, diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index f81a806b009..1f187382980 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -281,7 +281,7 @@ static void rna_DriverTarget_update_name(Main *bmain, Scene *scene, PointerRNA * /* ----------- */ -/* note: this function exists only to avoid id refcounting */ +/* NOTE: this function exists only to avoid id refcounting. */ static void rna_DriverTarget_id_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) @@ -1831,7 +1831,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_editable_func(prop, "rna_DriverTarget_id_editable"); - /* note: custom set function is ONLY to avoid rna setting a user for this. */ + /* NOTE: custom set function is ONLY to avoid rna setting a user for this. */ RNA_def_property_pointer_funcs( prop, NULL, "rna_DriverTarget_id_set", "rna_DriverTarget_id_typef", NULL); RNA_def_property_ui_text(prop, diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index decdc728bbe..5e015af8e20 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -2623,7 +2623,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "colors of a ramp or using a predefined color code"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - /* Coba field items - generated dynamically based on domain type */ + /* Color ramp field items are generated dynamically based on domain type. */ static const EnumPropertyItem coba_field_items[] = { {0, "NONE", 0, "", ""}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 21e905cfd2a..aad6f1231dd 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -1808,7 +1808,7 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) /* Frame Number */ prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "framenum"); - /* XXX note: this cannot occur on the same frame as another sketch */ + /* XXX NOTE: this cannot occur on the same frame as another sketch. */ RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears"); diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 3e6048e30c4..f1c05079d9c 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -93,6 +93,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { ICON_MOD_SUBSURF, "Subdivide", "Subdivide stroke adding more control points"}, + {eGpencilModifierType_Weight, + "GP_WEIGHT", + ICON_MOD_VERTEX_WEIGHT, + "Vertex Weight", + "Generate Vertex Weights"}, {0, "", 0, N_("Deform"), ""}, {eGpencilModifierType_Armature, "GP_ARMATURE", @@ -233,6 +238,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr) return &RNA_TintGpencilModifier; case eGpencilModifierType_Time: return &RNA_TimeGpencilModifier; + case eGpencilModifierType_Weight: + return &RNA_WeightGpencilModifier; case eGpencilModifierType_Color: return &RNA_ColorGpencilModifier; case eGpencilModifierType_Array: @@ -331,6 +338,8 @@ RNA_GP_MOD_VGROUP_NAME_SET(Offset, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Armature, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Texture, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Tint, vgname); +RNA_GP_MOD_VGROUP_NAME_SET(Weight, target_vgname); +RNA_GP_MOD_VGROUP_NAME_SET(Weight, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Lineart, vgname); # undef RNA_GP_MOD_VGROUP_NAME_SET @@ -363,8 +372,7 @@ static void greasepencil_modifier_object_set(Object *self, RNA_GP_MOD_OBJECT_SET(Armature, object, OB_ARMATURE); RNA_GP_MOD_OBJECT_SET(Lattice, object, OB_LATTICE); RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY); -RNA_GP_MOD_OBJECT_SET(Opacity, object, OB_EMPTY); -RNA_GP_MOD_OBJECT_SET(Thick, object, OB_EMPTY); +RNA_GP_MOD_OBJECT_SET(Weight, object, OB_EMPTY); # undef RNA_GP_MOD_OBJECT_SET @@ -538,6 +546,16 @@ static void rna_ThickGpencilModifier_material_set(PointerRNA *ptr, rna_GpencilModifier_material_set(ptr, value, ma_target, reports); } +static void rna_WeightGpencilModifier_material_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *reports) +{ + WeightGpencilModifierData *tmd = (WeightGpencilModifierData *)ptr->data; + Material **ma_target = &tmd->material; + + rna_GpencilModifier_material_set(ptr, value, ma_target, reports); +} + static void rna_OffsetGpencilModifier_material_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports) @@ -1143,35 +1161,9 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Thickness Factor", "Factor to multiply the thickness with"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_FADING); - RNA_def_property_ui_text(prop, "Fading", "Fading effect"); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - - /* Distance reference object */ - prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); - RNA_def_property_ui_text(prop, "Object", "Object used as distance reference"); - RNA_def_property_pointer_funcs(prop, NULL, "rna_ThickGpencilModifier_object_set", NULL, NULL); - RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); - - prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "fading_start"); - RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2); - RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect"); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - - prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "fading_end"); - RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2); - RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect"); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - - prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "fading_end_factor"); - RNA_def_property_range(prop, 0.0, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3); - RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor"); + prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_WEIGHT_FACTOR); + RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); @@ -1440,6 +1432,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Strength", "Factor for tinting"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_WEIGHT_FACTOR); + RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "radius"); RNA_def_property_range(prop, 1e-6f, FLT_MAX); @@ -1726,35 +1723,9 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Hardness", "Factor of stroke hardness"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_FADING); - RNA_def_property_ui_text(prop, "Fading", "Fading effect"); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - - /* Distance reference object */ - prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); - RNA_def_property_ui_text(prop, "Object", "Object used as distance reference"); - RNA_def_property_pointer_funcs(prop, NULL, "rna_OpacityGpencilModifier_object_set", NULL, NULL); - RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); - - prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "fading_start"); - RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2); - RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect"); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - - prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "fading_end"); - RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2); - RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect"); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - - prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "fading_end_factor"); - RNA_def_property_range(prop, 0.0, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3); - RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor"); + prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_WEIGHT_FACTOR); + RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); @@ -2733,6 +2704,170 @@ static void rna_def_modifier_gpenciltexture(BlenderRNA *brna) RNA_define_lib_overridable(false); } +static void rna_def_modifier_gpencilweight(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static const EnumPropertyItem mode_items[] = { + {GP_WEIGHT_MODE_DISTANCE, + "DISTANCE", + 0, + "Distance", + "Calculate weights depending on the distance to the target object"}, + {GP_WEIGHT_MODE_ANGLE, + "ANGLE", + 0, + "Angle", + "Calculate weights depending on the stroke orientation"}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem axis_items[] = { + {0, "X", 0, "X", ""}, + {1, "Y", 0, "Y", ""}, + {2, "Z", 0, "Z", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem space_items[] = { + {GP_SPACE_LOCAL, "LOCAL", 0, "Local Space", ""}, + {GP_SPACE_WORLD, "WORLD", 0, "World Space", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + srna = RNA_def_struct(brna, "WeightGpencilModifier", "GpencilModifier"); + RNA_def_struct_ui_text(srna, "Weight Modifier", "Calculate Vertex Weight dynamically"); + RNA_def_struct_sdna(srna, "WeightGpencilModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT); + + RNA_define_lib_overridable(true); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "target_vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "target_vgname"); + RNA_def_property_ui_text(prop, "Output", "Output Vertex group"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightGpencilModifier_target_vgname_set"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_blend", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_BLEND_DATA); + RNA_def_property_ui_text( + prop, "Blend", "Blend results with existing weights in output weight group"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_invert_output", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_OUTPUT); + RNA_def_property_ui_text(prop, "Invert", "Invert weight values"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "angle"); + RNA_def_property_ui_text(prop, "Angle", "Angle"); + RNA_def_property_range(prop, 0.0f, DEG2RAD(180.0f)); + RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "axis"); + RNA_def_property_enum_items(prop, axis_items); + RNA_def_property_ui_text(prop, "Axis", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "space"); + RNA_def_property_enum_items(prop, space_items); + RNA_def_property_ui_text(prop, "Space", "Coordinates space"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "layername"); + RNA_def_property_ui_text(prop, "Layer", "Layer name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, + NULL, + "rna_WeightGpencilModifier_material_set", + NULL, + "rna_GpencilModifier_material_poll"); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "vgname"); + RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightGpencilModifier_vgname_set"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + /* Distance reference object */ + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "Object", "Object used as distance reference"); + RNA_def_property_pointer_funcs(prop, NULL, "rna_WeightGpencilModifier_object_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + + prop = RNA_def_property(srna, "distance_start", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dist_start"); + RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2); + RNA_def_property_ui_text(prop, "Distance Start", "Start value for distance calculation"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "minimum_weight", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "min_weight"); + RNA_def_property_ui_text(prop, "Minimum", "Minimum value for vertex weight"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "distance_end", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dist_end"); + RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2); + RNA_def_property_ui_text(prop, "Distance End", "End value for distance calculation"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "pass_index"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Pass", "Pass index"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_LAYER); + RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_PASS); + RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_VGROUP); + RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "layer_pass"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Pass", "Layer pass index"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_LAYERPASS); + RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + RNA_define_lib_overridable(false); +} + static void rna_def_modifier_gpencillineart(BlenderRNA *brna) { StructRNA *srna; @@ -3187,6 +3322,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna) rna_def_modifier_gpencilarmature(brna); rna_def_modifier_gpencilmultiply(brna); rna_def_modifier_gpenciltexture(brna); + rna_def_modifier_gpencilweight(brna); rna_def_modifier_gpencillineart(brna); rna_def_modifier_gpencillength(brna); } diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 987517320f9..06ff1918040 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -117,7 +117,7 @@ static void rna_Image_save(Image *image, Main *bmain, bContext *C, ReportList *r BLI_strncpy(filename, image->filepath, sizeof(filename)); BLI_path_abs(filename, ID_BLEND_PATH(bmain, &image->id)); - /* note, we purposefully ignore packed files here, + /* NOTE: we purposefully ignore packed files here, * developers need to explicitly write them via 'packed_files' */ if (IMB_saveiff(ibuf, filename, ibuf->flags)) { @@ -374,7 +374,7 @@ void RNA_api_image(StructRNA *srna) func = RNA_def_function(srna, "buffers_free", "rna_Image_buffers_free"); RNA_def_function_ui_description(func, "Free the image buffers from memory"); - /* TODO, pack/unpack, maybe should be generic functions? */ + /* TODO: pack/unpack, maybe should be generic functions? */ } #endif diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index bfe9d4bb77c..9dc08430307 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -30,6 +30,7 @@ #define RNA_MAGIC ((int)~0) +struct AssetLibraryReference; struct FreestyleSettings; struct ID; struct IDOverrideLibrary; @@ -266,6 +267,16 @@ void rna_def_mtex_common(struct BlenderRNA *brna, void rna_def_texpaint_slots(struct BlenderRNA *brna, struct StructRNA *srna); void rna_def_view_layer_common(struct BlenderRNA *brna, struct StructRNA *srna, const bool scene); +PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna, + const char *get, + const char *set); +int rna_asset_library_reference_get(const struct AssetLibraryReference *library); +void rna_asset_library_reference_set(struct AssetLibraryReference *library, int value); +const EnumPropertyItem *rna_asset_library_reference_itemf(struct bContext *C, + struct PointerRNA *ptr, + struct PropertyRNA *prop, + bool *r_free); + void rna_def_actionbone_group_common(struct StructRNA *srna, int update_flag, const char *update_cb); @@ -276,10 +287,10 @@ void rna_ID_name_get(struct PointerRNA *ptr, char *value); int rna_ID_name_length(struct PointerRNA *ptr); void rna_ID_name_set(struct PointerRNA *ptr, const char *value); struct StructRNA *rna_ID_refine(struct PointerRNA *ptr); -struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, bool create); +struct IDProperty **rna_ID_idprops(struct PointerRNA *ptr); void rna_ID_fake_user_set(struct PointerRNA *ptr, bool value); void **rna_ID_instance(PointerRNA *ptr); -struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, bool create); +struct IDProperty **rna_PropertyGroup_idprops(struct PointerRNA *ptr); void rna_PropertyGroup_unregister(struct Main *bmain, struct StructRNA *type); struct StructRNA *rna_PropertyGroup_register(struct Main *bmain, struct ReportList *reports, diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 0bb452dfb07..479306e8c06 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -54,7 +54,7 @@ typedef void (*ContextPropUpdateFunc)(struct bContext *C, typedef void (*ContextUpdateFunc)(struct bContext *C, struct PointerRNA *ptr); typedef int (*EditableFunc)(struct PointerRNA *ptr, const char **r_info); typedef int (*ItemEditableFunc)(struct PointerRNA *ptr, int index); -typedef struct IDProperty *(*IDPropertiesFunc)(struct PointerRNA *ptr, bool create); +typedef struct IDProperty **(*IDPropertiesFunc)(struct PointerRNA *ptr); typedef struct StructRNA *(*StructRefineFunc)(struct PointerRNA *ptr); typedef char *(*StructPathFunc)(struct PointerRNA *ptr); @@ -280,7 +280,7 @@ struct FunctionRNA { CallFunc call; /* parameter for the return value - * note: this is only the C return value, rna functions can have multiple return values */ + * NOTE: this is only the C return value, rna functions can have multiple return values. */ PropertyRNA *c_ret; }; @@ -559,7 +559,7 @@ struct StructRNA { */ StructInstanceFunc instance; - /* callback to get id properties */ + /** Return the location of the struct's pointer to the root group IDProperty. */ IDPropertiesFunc idproperties; /* functions of this struct */ diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index a48727526c9..9d8ed161738 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -168,7 +168,7 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value) # undef SHAPEKEY_SLIDER_TOL /* ***** Normals accessors for shapekeys. ***** */ -/* Note: with this we may recompute several times the same data, should we want to access verts, +/* NOTE: with this we may recompute several times the same data, should we want to access verts, * then polys, then loops normals... However, * such case looks rather unlikely - and not worth adding some kind of caching in KeyBlocks. */ diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index b4253ab9236..0414afe1514 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -119,16 +119,10 @@ static char *rna_ViewLayer_path(PointerRNA *ptr) return BLI_sprintfN("view_layers[\"%s\"]", name_esc); } -static IDProperty *rna_ViewLayer_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_ViewLayer_idprops(PointerRNA *ptr) { ViewLayer *view_layer = (ViewLayer *)ptr->data; - - if (create && !view_layer->id_properties) { - IDPropertyTemplate val = {0}; - view_layer->id_properties = IDP_New(IDP_GROUP, &val, "ViewLayer ID properties"); - } - - return view_layer->id_properties; + return &view_layer->id_properties; } static bool rna_LayerCollection_visible_get(LayerCollection *layer_collection, bContext *C) diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 24bc5504a58..8c7d9698a67 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -115,7 +115,7 @@ static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr) rna_Mask_update_data(bmain, scene, ptr); } -/* note: this function exists only to avoid id refcounting */ +/* NOTE: this function exists only to avoid id refcounting. */ static void rna_MaskParent_id_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) @@ -505,7 +505,7 @@ static void rna_MaskSpline_points_add(ID *id, MaskSpline *spline, int count) if (!layer) { /* Shall not happen actually */ - BLI_assert(!"No layer found for the spline"); + BLI_assert_msg(0, "No layer found for the spline"); return; } @@ -631,7 +631,7 @@ static void rna_def_maskParent(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ID"); RNA_def_property_flag(prop, PROP_EDITABLE); // RNA_def_property_editable_func(prop, "rna_maskSpline_id_editable"); - /* note: custom set function is ONLY to avoid rna setting a user for this. */ + /* NOTE: custom set function is ONLY to avoid rna setting a user for this. */ RNA_def_property_pointer_funcs( prop, NULL, "rna_MaskParent_id_set", "rna_MaskParent_id_typef", NULL); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 81cf1447604..9caff88a3a5 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -14,7 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* note: the original vertex color stuff is now just used for +/* NOTE: the original vertex color stuff is now just used for * getting info on the layers themselves, accessing the data is * done through the (not yet written) mpoly interfaces. */ @@ -1084,7 +1084,7 @@ static void rna_Mesh_face_map_remove(struct Mesh *me, static int rna_MeshPoly_vertices_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) { MPoly *mp = (MPoly *)ptr->data; - /* note, raw access uses dummy item, this _could_ crash, + /* NOTE: raw access uses dummy item, this _could_ crash, * watch out for this, mface uses it but it can't work here. */ return (length[0] = mp->totloop); } @@ -3006,7 +3006,7 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Loop Triangles", "Tessellation of mesh polygons into triangles"); rna_def_mesh_looptris(brna, prop); - /* TODO, should this be allowed to be its self? */ + /* TODO: should this be allowed to be its self? */ prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "texcomesh"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); @@ -3098,7 +3098,7 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "All vertex colors"); rna_def_vert_colors(brna, prop); - /* TODO, edge customdata layers (bmesh py api can access already) */ + /* TODO: edge customdata layers (bmesh py api can access already). */ prop = RNA_def_property(srna, "vertex_layers_float", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); RNA_def_property_collection_funcs(prop, diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 8128bdb83a0..9835d664a55 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -249,7 +249,7 @@ void RNA_api_mesh(StructRNA *srna) func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces"); RNA_def_function_ui_description(func, "Split faces based on the edge angle"); RNA_def_boolean( - func, "free_loop_normals", 1, "Free Loop Notmals", "Free loop normals custom data layer"); + func, "free_loop_normals", 1, "Free Loop Normals", "Free loop normals custom data layer"); func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents"); RNA_def_function_flag(func, FUNC_USE_REPORTS); @@ -288,7 +288,7 @@ void RNA_api_mesh(StructRNA *srna) "Define custom split normals of this mesh " "(use zero-vectors to keep auto ones)"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - /* TODO, see how array size of 0 works, this shouldn't be used */ + /* TODO: see how array size of 0 works, this shouldn't be used. */ parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f); RNA_def_property_multi_array(parm, 2, normals_array_dim); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); @@ -301,7 +301,7 @@ void RNA_api_mesh(StructRNA *srna) "Define custom split normals of this mesh, from vertices' normals " "(use zero-vectors to keep auto ones)"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - /* TODO, see how array size of 0 works, this shouldn't be used */ + /* TODO: see how array size of 0 works, this shouldn't be used. */ parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f); RNA_def_property_multi_array(parm, 2, normals_array_dim); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 9a895a0c75a..5fddb0f18a5 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -602,6 +602,7 @@ const EnumPropertyItem rna_enum_axis_flag_xyz_items[] = { # include "BKE_cachefile.h" # include "BKE_context.h" +# include "BKE_deform.h" # include "BKE_mesh_runtime.h" # include "BKE_modifier.h" # include "BKE_object.h" @@ -690,6 +691,7 @@ static void rna_Modifier_is_active_set(PointerRNA *ptr, bool value) } md->flag |= eModifierFlag_Active; + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id); } } @@ -1249,12 +1251,13 @@ static const EnumPropertyItem *rna_DataTransferModifier_layers_select_src_itemf( # endif if (ob_src) { - bDeformGroup *dg; + const bDeformGroup *dg; int i; RNA_enum_item_add_separator(&item, &totitem); - for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) { + const ListBase *defbase = BKE_object_defgroup_list(ob_src); + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { tmp_item.value = i; tmp_item.identifier = tmp_item.name = dg->name; RNA_enum_item_add(&item, &totitem, &tmp_item); @@ -1348,12 +1351,13 @@ static const EnumPropertyItem *rna_DataTransferModifier_layers_select_dst_itemf( Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */ if (ob_dst) { - bDeformGroup *dg; + const bDeformGroup *dg; int i; RNA_enum_item_add_separator(&item, &totitem); - for (i = 0, dg = ob_dst->defbase.first; dg; i++, dg = dg->next) { + const ListBase *defbase = BKE_object_defgroup_list(ob_dst); + for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) { tmp_item.value = i; tmp_item.identifier = tmp_item.name = dg->name; RNA_enum_item_add(&item, &totitem, &tmp_item); @@ -1617,15 +1621,11 @@ static void rna_NodesModifier_node_group_update(Main *bmain, Scene *scene, Point MOD_nodes_update_interface(object, nmd); } -static IDProperty *rna_NodesModifier_properties(PointerRNA *ptr, bool create) +static IDProperty **rna_NodesModifier_properties(PointerRNA *ptr) { NodesModifierData *nmd = ptr->data; NodesModifierSettings *settings = &nmd->settings; - if (create && settings->properties == NULL) { - IDPropertyTemplate val = {0}; - settings->properties = IDP_New(IDP_GROUP, &val, "Nodes Modifier Settings"); - } - return settings->properties; + return &settings->properties; } #else @@ -2256,7 +2256,7 @@ static void rna_def_modifier_decimate(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; - /* Note, keep in sync with operator 'MESH_OT_decimate' */ + /* NOTE: keep in sync with operator 'MESH_OT_decimate'. */ StructRNA *srna; PropertyRNA *prop; @@ -6884,6 +6884,15 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_sparse_bind", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SDEF_SPARSE_BIND); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text( + prop, + "Sparse Bind", + "Only record binding data for vertices matching the vertex group at the time of bind"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, -100, 100); RNA_def_property_ui_range(prop, -100, 100, 10, 2); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 2642ba82bc0..17c7b331c88 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -297,7 +297,7 @@ static int rna_NlaStrip_action_editable(PointerRNA *ptr, const char **UNUSED(r_i { NlaStrip *strip = (NlaStrip *)ptr->data; - /* strip actions shouldn't be editable if NLA tweakmode is on */ + /* Strip actions shouldn't be editable if NLA tweak-mode is on. */ if (ptr->owner_id) { AnimData *adt = BKE_animdata_from_id(ptr->owner_id); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 6f4f63eaa5e..2ff43296d76 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -350,6 +350,31 @@ const EnumPropertyItem rna_enum_node_float_compare_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_node_float_to_int_items[] = { + {FN_NODE_FLOAT_TO_INT_ROUND, + "ROUND", + 0, + "Round", + "Round the float up or down to the nearest integer"}, + {FN_NODE_FLOAT_TO_INT_FLOOR, + "FLOOR", + 0, + "Floor", + "Round the float down to the next smallest integer"}, + {FN_NODE_FLOAT_TO_INT_CEIL, + "CEILING", + 0, + "Ceiling", + "Round the float up to the next largest integer"}, + {FN_NODE_FLOAT_TO_INT_TRUNCATE, + "TRUNCATE", + 0, + "Truncate", + "Round the float to the closest integer in the direction of zero (floor if positive; ceiling " + "if negative)"}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_node_map_range_items[] = { {NODE_MAP_RANGE_LINEAR, "LINEAR", @@ -787,7 +812,7 @@ const EnumPropertyItem *rna_node_socket_type_itemf(void *data, tmp.value = i; tmp.identifier = stype->idname; tmp.icon = RNA_struct_ui_icon(srna); - tmp.name = RNA_struct_ui_name(srna); + tmp.name = nodeSocketTypeLabel(stype); tmp.description = RNA_struct_ui_description(srna); RNA_enum_item_add(&item, &totitem, &tmp); @@ -1013,8 +1038,7 @@ static void rna_NodeTree_get_from_context( RNA_parameter_list_free(&list); } -static bool rna_NodeTree_valid_socket_type(eNodeSocketDatatype socket_type, - bNodeTreeType *ntreetype) +static bool rna_NodeTree_valid_socket_type(bNodeTreeType *ntreetype, bNodeSocketType *socket_type) { extern FunctionRNA rna_NodeTree_valid_socket_type_func; @@ -1028,7 +1052,7 @@ static bool rna_NodeTree_valid_socket_type(eNodeSocketDatatype socket_type, func = &rna_NodeTree_valid_socket_type_func; RNA_parameter_list_create(&list, &ptr, func); - RNA_parameter_set_lookup(&list, "type", &socket_type); + RNA_parameter_set_lookup(&list, "idname", &socket_type->idname); ntreetype->rna_ext.call(NULL, &ptr, func, &list); RNA_parameter_get_lookup(&list, "valid", &ret); @@ -2370,16 +2394,10 @@ static StructRNA *rna_FunctionNode_register(Main *bmain, return nt->rna_ext.srna; } -static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_Node_idprops(PointerRNA *ptr) { bNode *node = ptr->data; - - if (create && !node->prop) { - IDPropertyTemplate val = {0}; - node->prop = IDP_New(IDP_GROUP, &val, "RNA_Node ID properties"); - } - - return node->prop; + return &node->prop; } static void rna_Node_parent_set(PointerRNA *ptr, @@ -2838,16 +2856,10 @@ static char *rna_NodeSocket_path(PointerRNA *ptr) } } -static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_NodeSocket_idprops(PointerRNA *ptr) { bNodeSocket *sock = ptr->data; - - if (create && !sock->prop) { - IDPropertyTemplate val = {0}; - sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocket ID properties"); - } - - return sock->prop; + return &sock->prop; } static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr) @@ -2869,7 +2881,7 @@ static void rna_NodeSocket_type_set(PointerRNA *ptr, int value) bNodeSocket *sock = (bNodeSocket *)ptr->data; bNode *node; nodeFindNode(ntree, sock, &node, NULL); - nodeModifySocketType(ntree, node, sock, value, 0); + nodeModifySocketTypeStatic(ntree, node, sock, value, 0); } static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -3154,16 +3166,10 @@ static char *rna_NodeSocketInterface_path(PointerRNA *ptr) return NULL; } -static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_NodeSocketInterface_idprops(PointerRNA *ptr) { bNodeSocket *sock = ptr->data; - - if (create && !sock->prop) { - IDPropertyTemplate val = {0}; - sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocketInterface ID properties"); - } - - return sock->prop; + return &sock->prop; } static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -3209,7 +3215,7 @@ static void rna_NodeSocketInterfaceStandard_draw(ID *id, struct uiLayout *layout) { PointerRNA ptr; - RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr); + RNA_pointer_create(id, &RNA_NodeSocketInterface, sock, &ptr); sock->typeinfo->interface_draw(C, layout, &ptr); } @@ -3219,7 +3225,7 @@ static void rna_NodeSocketInterfaceStandard_draw_color(ID *id, float r_color[4]) { PointerRNA ptr; - RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr); + RNA_pointer_create(id, &RNA_NodeSocketInterface, sock, &ptr); sock->typeinfo->interface_draw_color(C, &ptr, r_color); } @@ -4442,7 +4448,7 @@ static int point_density_particle_color_source_from_shader( case SHD_POINTDENSITY_COLOR_PARTVEL: return TEX_PD_COLOR_PARTVEL; default: - BLI_assert(!"Unknown color source"); + BLI_assert_msg(0, "Unknown color source"); return TEX_PD_COLOR_CONSTANT; } } @@ -4458,7 +4464,7 @@ static int point_density_vertex_color_source_from_shader( case SHD_POINTDENSITY_COLOR_VERTNOR: return TEX_PD_COLOR_VERTNOR; default: - BLI_assert(!"Unknown color source"); + BLI_assert_msg(0, "Unknown color source"); return TEX_PD_COLOR_CONSTANT; } } @@ -4854,6 +4860,18 @@ static void def_float_compare(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_float_to_int(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "rounding_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_node_float_to_int_items); + RNA_def_property_ui_text( + prop, "Rounding Mode", "Method used to convert the float to an integer"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_vector_math(StructRNA *srna) { PropertyRNA *prop; @@ -5814,7 +5832,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna) func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc"); RNA_def_function_ui_description(func, "Calculate point density"); RNA_def_pointer(func, "depsgraph", "Depsgraph", "", ""); - /* TODO, See how array size of 0 works, this shouldn't be used. */ + /* TODO: See how array size of 0 works, this shouldn't be used. */ parm = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, 0); RNA_def_function_output(func, parm); @@ -6265,7 +6283,7 @@ static void def_sh_script(StructRNA *srna) /* API functions */ -# if 0 /* XXX TODO use general node api for this */ +# if 0 /* XXX TODO: use general node api for this. */ func = RNA_def_function(srna, "find_socket", "rna_ShaderNodeScript_find_socket"); RNA_def_function_ui_description(func, "Find a socket by name"); parm = RNA_def_string(func, "name", NULL, 0, "Socket name", ""); @@ -9511,6 +9529,32 @@ static void def_geo_curve_primitive_circle(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_curve_primitive_line(StructRNA *srna) +{ + static const EnumPropertyItem mode_items[] = { + {GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS, + "POINTS", + ICON_NONE, + "Points", + "Define the start and end points of the line"}, + {GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION, + "DIRECTION", + ICON_NONE, + "Direction", + "Define a line with a start point, direction and length"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeGeometryCurvePrimitiveLine", "storage"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "Method used to determine radius and placement"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_point_rotate(StructRNA *srna) { static const EnumPropertyItem type_items[] = { @@ -9945,6 +9989,45 @@ static void def_geo_switch(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_curve_primitive_quadrilateral(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem mode_items[] = { + {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE, + "RECTANGLE", + 0, + "Rectangle", + "Create a rectangle"}, + {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM, + "PARALLELOGRAM", + 0, + "Parallelogram", + "Create a parallelogram"}, + {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID, + "TRAPEZOID", + 0, + "Trapezoid", + "Create a trapezoid"}, + {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE, "KITE", 0, "Kite", "Create a Kite / Dart"}, + {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS, + "POINTS", + 0, + "Points", + "Create a quadrilateral from four points"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryCurvePrimitiveQuad", "storage"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_enum_default(prop, GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_curve_resample(StructRNA *srna) { PropertyRNA *prop; @@ -10186,7 +10269,7 @@ static void rna_def_node_socket(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine"); - RNA_def_struct_ui_icon(srna, ICON_PLUGIN); + RNA_def_struct_ui_icon(srna, ICON_NONE); RNA_def_struct_path_func(srna, "rna_NodeSocket_path"); RNA_def_struct_register_funcs( srna, "rna_NodeSocket_register", "rna_NodeSocket_unregister", NULL); @@ -10291,6 +10374,11 @@ static void rna_def_node_socket(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER); RNA_def_property_ui_text(prop, "ID Name", ""); + prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "typeinfo->label"); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_ui_text(prop, "Type Label", "Label to display for the socket type in the UI"); + /* draw socket */ func = RNA_def_function(srna, "draw", NULL); RNA_def_function_ui_description(func, "Draw socket"); @@ -10379,6 +10467,11 @@ static void rna_def_node_socket_interface(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER); RNA_def_property_ui_text(prop, "ID Name", ""); + prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "typeinfo->label"); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_ui_text(prop, "Type Label", "Label to display for the socket type in the UI"); + func = RNA_def_function(srna, "draw", NULL); RNA_def_function_ui_description(func, "Draw template settings"); RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); @@ -11543,12 +11636,6 @@ static void rna_def_node(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Texture", "Display node in viewport textured shading mode"); RNA_def_property_update(prop, 0, "rna_Node_update"); - prop = RNA_def_property(srna, "active_preview", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_ACTIVE_PREVIEW); - RNA_def_property_ui_text(prop, "Active Preview", "Node is previewed in other editor"); - RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); - RNA_def_property_update(prop, NC_NODE, NULL); - /* generic property update function */ func = RNA_def_function(srna, "socket_value_update", "rna_Node_socket_value_update"); RNA_def_function_ui_description(func, "Update after property changes"); @@ -12045,11 +12132,12 @@ static void rna_def_nodetree(BlenderRNA *brna) func, "result_3", "ID", "From ID", "Original ID data-block selected from the context"); RNA_def_function_output(func, parm); - /* Check for support of a socket type. */ + /* Check for support of a socket type with a type identifier. */ func = RNA_def_function(srna, "valid_socket_type", NULL); RNA_def_function_ui_description(func, "Check if the socket type is valid for the node tree"); RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL); - parm = RNA_def_enum(func, "type", node_socket_type_items, 0, "", ""); + parm = RNA_def_string( + func, "idname", "NodeSocket", MAX_NAME, "Socket Type", "Identifier of the socket type"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); RNA_def_function_return(func, RNA_def_boolean(func, "valid", false, "", "")); } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index a208e520d02..ed681291e29 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -790,9 +790,27 @@ static void rna_Object_dup_collection_set(PointerRNA *ptr, } } +static void rna_Object_vertex_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Object *ob = (Object *)ptr->data; + if (!BKE_object_supports_vertex_groups(ob)) { + iter->valid = 0; + return; + } + + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + iter->valid = defbase != NULL; + + rna_iterator_listbase_begin(iter, defbase, NULL); +} + static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value) { Object *ob = (Object *)ptr->owner_id; + if (!BKE_object_supports_vertex_groups(ob)) { + return; + } + bDeformGroup *dg = (bDeformGroup *)ptr->data; BLI_strncpy_utf8(dg->name, value, sizeof(dg->name)); BKE_object_defgroup_unique_name(dg, ob); @@ -801,15 +819,25 @@ static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value) static int rna_VertexGroup_index_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; + if (!BKE_object_supports_vertex_groups(ob)) { + return -1; + } - return BLI_findindex(&ob->defbase, ptr->data); + const ListBase *defbase = BKE_object_defgroup_list(ob); + return BLI_findindex(defbase, ptr->data); } static PointerRNA rna_Object_active_vertex_group_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; + if (!BKE_object_supports_vertex_groups(ob)) { + return PointerRNA_NULL; + } + + const ListBase *defbase = BKE_object_defgroup_list(ob); + return rna_pointer_inherit_refine( - ptr, &RNA_VertexGroup, BLI_findlink(&ob->defbase, ob->actdef - 1)); + ptr, &RNA_VertexGroup, BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1)); } static void rna_Object_active_vertex_group_set(PointerRNA *ptr, @@ -817,7 +845,13 @@ static void rna_Object_active_vertex_group_set(PointerRNA *ptr, struct ReportList *reports) { Object *ob = (Object *)ptr->owner_id; - int index = BLI_findindex(&ob->defbase, value.data); + if (!BKE_object_supports_vertex_groups(ob)) { + return; + } + + const ListBase *defbase = BKE_object_defgroup_list(ob); + + int index = BLI_findindex(defbase, value.data); if (index == -1) { BKE_reportf(reports, RPT_ERROR, @@ -827,19 +861,27 @@ static void rna_Object_active_vertex_group_set(PointerRNA *ptr, return; } - ob->actdef = index + 1; + BKE_object_defgroup_active_index_set(ob, index + 1); } static int rna_Object_active_vertex_group_index_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - return ob->actdef - 1; + if (!BKE_object_supports_vertex_groups(ob)) { + return -1; + } + + return BKE_object_defgroup_active_index_get(ob) - 1; } static void rna_Object_active_vertex_group_index_set(PointerRNA *ptr, int value) { Object *ob = (Object *)ptr->owner_id; - ob->actdef = value + 1; + if (!BKE_object_supports_vertex_groups(ob)) { + return; + } + + BKE_object_defgroup_active_index_set(ob, value + 1); } static void rna_Object_active_vertex_group_index_range( @@ -848,15 +890,24 @@ static void rna_Object_active_vertex_group_index_range( Object *ob = (Object *)ptr->owner_id; *min = 0; - *max = max_ii(0, BLI_listbase_count(&ob->defbase) - 1); + if (!BKE_object_supports_vertex_groups(ob)) { + *max = 0; + return; + } + const ListBase *defbase = BKE_object_defgroup_list(ob); + *max = max_ii(0, BLI_listbase_count(defbase) - 1); } void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index) { Object *ob = (Object *)ptr->owner_id; - bDeformGroup *dg; + if (!BKE_object_supports_vertex_groups(ob)) { + value[0] = '\0'; + return; + } - dg = BLI_findlink(&ob->defbase, index - 1); + const ListBase *defbase = BKE_object_defgroup_list(ob); + const bDeformGroup *dg = BLI_findlink(defbase, index - 1); if (dg) { BLI_strncpy(value, dg->name, sizeof(dg->name)); @@ -869,21 +920,34 @@ void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index) int rna_object_vgroup_name_index_length(PointerRNA *ptr, int index) { Object *ob = (Object *)ptr->owner_id; - bDeformGroup *dg; + if (!BKE_object_supports_vertex_groups(ob)) { + return 0; + } - dg = BLI_findlink(&ob->defbase, index - 1); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *dg = BLI_findlink(defbase, index - 1); return (dg) ? strlen(dg->name) : 0; } void rna_object_vgroup_name_index_set(PointerRNA *ptr, const char *value, short *index) { Object *ob = (Object *)ptr->owner_id; + if (!BKE_object_supports_vertex_groups(ob)) { + *index = -1; + return; + } + *index = BKE_object_defgroup_name_index(ob, value) + 1; } void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen) { Object *ob = (Object *)ptr->owner_id; + if (!BKE_object_supports_vertex_groups(ob)) { + result[0] = '\0'; + return; + } + bDeformGroup *dg = BKE_object_defgroup_find_name(ob, value); if (dg) { /* No need for BLI_strncpy_utf8, since this matches an existing group. */ @@ -1706,6 +1770,8 @@ static void rna_Object_active_modifier_set(PointerRNA *ptr, PointerRNA value, Re Object *ob = (Object *)ptr->owner_id; ModifierData *md = value.data; + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); + if (RNA_pointer_is_null(&value)) { BKE_object_modifier_set_active(ob, NULL); return; @@ -1931,16 +1997,25 @@ static void rna_Object_boundbox_get(PointerRNA *ptr, float *values) } } +static bool check_object_vgroup_support_and_warn(const Object *ob, + const char *op_name, + ReportList *reports) +{ + if (!BKE_object_supports_vertex_groups(ob)) { + const char *ob_type_name = "Unknown"; + RNA_enum_name_from_value(rna_enum_object_type_items, ob->type, &ob_type_name); + BKE_reportf(reports, RPT_ERROR, "%s is not supported for '%s' objects", op_name, ob_type_name); + return false; + } + return true; +} + static bDeformGroup *rna_Object_vgroup_new(Object *ob, Main *bmain, ReportList *reports, const char *name) { - if (!OB_TYPE_SUPPORT_VGROUP(ob->type)) { - const char *ob_type_name = "Unknown"; - RNA_enum_name_from_value(rna_enum_object_type_items, ob->type, &ob_type_name); - BKE_reportf( - reports, RPT_ERROR, "VertexGroups.new(): is not supported for '%s' objects", ob_type_name); + if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.new()", reports)) { return NULL; } @@ -1957,8 +2032,14 @@ static void rna_Object_vgroup_remove(Object *ob, ReportList *reports, PointerRNA *defgroup_ptr) { + if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.remove()", reports)) { + return; + } + bDeformGroup *defgroup = defgroup_ptr->data; - if (BLI_findindex(&ob->defbase, defgroup) == -1) { + ListBase *defbase = BKE_object_defgroup_list_mutable(ob); + + if (BLI_findindex(defbase, defgroup) == -1) { BKE_reportf(reports, RPT_ERROR, "DeformGroup '%s' not in object '%s'", @@ -1974,8 +2055,12 @@ static void rna_Object_vgroup_remove(Object *ob, WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); } -static void rna_Object_vgroup_clear(Object *ob, Main *bmain) +static void rna_Object_vgroup_clear(Object *ob, Main *bmain, ReportList *reports) { + if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.clear()", reports)) { + return; + } + BKE_object_defgroup_remove_all(ob); DEG_relations_tag_update(bmain); @@ -2268,7 +2353,7 @@ static void rna_def_vertex_group(BlenderRNA *brna) func = RNA_def_function(srna, "add", "rna_VertexGroup_vertex_add"); RNA_def_function_ui_description(func, "Add vertices to the group"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldn't be used */ + /* TODO: see how array size of 0 works, this shouldn't be used. */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); parm = RNA_def_float(func, "weight", 0, 0.0f, 1.0f, "", "Vertex weight", 0.0f, 1.0f); @@ -2279,7 +2364,7 @@ static void rna_def_vertex_group(BlenderRNA *brna) func = RNA_def_function(srna, "remove", "rna_VertexGroup_vertex_remove"); RNA_def_function_ui_description(func, "Remove vertices from the group"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldn't be used */ + /* TODO: see how array size of 0 works, this shouldn't be used. */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); @@ -2326,14 +2411,14 @@ static void rna_def_face_map(BlenderRNA *brna) func = RNA_def_function(srna, "add", "rna_FaceMap_face_add"); RNA_def_function_ui_description(func, "Add faces to the face-map"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldn't be used */ + /* TODO: see how array size of 0 works, this shouldn't be used. */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); func = RNA_def_function(srna, "remove", "rna_FaceMap_face_remove"); RNA_def_function_ui_description(func, "Remove faces from the face-map"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldn't be used */ + /* TODO: see how array size of 0 works, this shouldn't be used. */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); } @@ -2488,7 +2573,7 @@ static void rna_def_object_modifiers(BlenderRNA *brna, PropertyRNA *cprop) /*RNA_def_property_update(prop, 0, "rna_Armature_act_editbone_update"); */ RNA_def_property_pointer_funcs(prop, NULL, "rna_Armature_act_edit_bone_set", NULL, NULL); - /* todo, redraw */ + /* TODO: redraw. */ /* RNA_def_property_collection_active(prop, prop_act); */ # endif @@ -2685,7 +2770,6 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_sdna(prop, NULL, "actdef"); RNA_def_property_int_funcs(prop, "rna_Object_active_vertex_group_index_get", "rna_Object_active_vertex_group_index_set", @@ -2710,7 +2794,7 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); func = RNA_def_function(srna, "clear", "rna_Object_vgroup_clear"); - RNA_def_function_flag(func, FUNC_USE_MAIN); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Delete all vertex groups from object"); } @@ -3272,7 +3356,15 @@ static void rna_def_object(BlenderRNA *brna) /* vertex groups */ prop = RNA_def_property(srna, "vertex_groups", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "defbase", NULL); + RNA_def_property_collection_funcs(prop, + "rna_Object_vertex_groups_begin", + "rna_iterator_listbase_next", + "rna_iterator_listbase_end", + "rna_iterator_listbase_get", + NULL, + NULL, + NULL, + NULL); RNA_def_property_struct_type(prop, "VertexGroup"); RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Vertex Groups", "Vertex groups of the object"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 4608b0c1bac..10ba2b9acb1 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -303,6 +303,9 @@ static void rna_Object_mat_convert_space(Object *ob, { copy_m4_m4((float(*)[4])mat_ret, (float(*)[4])mat); + BLI_assert(!ELEM(from, CONSTRAINT_SPACE_OWNLOCAL)); + BLI_assert(!ELEM(to, CONSTRAINT_SPACE_OWNLOCAL)); + /* Error in case of invalid from/to values when pchan is NULL */ if (pchan == NULL) { if (ELEM(from, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL)) { diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 30baf01e952..98d59bf3a1a 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -133,8 +133,9 @@ static bool rna_Cache_get_valid_owner_ID(PointerRNA *ptr, Object **ob, Scene **s *scene = (Scene *)ptr->owner_id; break; default: - BLI_assert(!"Trying to get PTCacheID from an invalid ID type " - "(Only scenes and objects are supported)."); + BLI_assert_msg(0, + "Trying to get PTCacheID from an invalid ID type " + "(Only scenes and objects are supported)."); break; } @@ -1095,7 +1096,7 @@ static void rna_def_pointcache_active(BlenderRNA *brna) * Those caches items have exact same content as 'active' one, except for that collection, * to prevent ugly recursive layout pattern. * - * Note: This shall probably be redone from scratch in a proper way at some point, + * NOTE: This shall probably be redone from scratch in a proper way at some point, * but for now that will do, and shall not break anything in the API. */ prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 9ab685fa462..de4cfb2b61a 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -554,7 +554,7 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys } part = particlesystem->part; - /* Note: only hair, keyed and baked particles may have cached items... */ + /* NOTE: only hair, keyed and baked particles may have cached items... */ totpart = particlesystem->totcached != 0 ? particlesystem->totcached : particlesystem->totpart; totchild = particlesystem->totchildcache != 0 ? particlesystem->totchildcache : particlesystem->totchild; @@ -1430,9 +1430,10 @@ static void psys_vg_name_get__internal(PointerRNA *ptr, char *value, int index) { Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = (ParticleSystem *)ptr->data; + const ListBase *defbase = BKE_object_defgroup_list(ob); if (psys->vgroup[index] > 0) { - bDeformGroup *defGroup = BLI_findlink(&ob->defbase, psys->vgroup[index] - 1); + bDeformGroup *defGroup = BLI_findlink(defbase, psys->vgroup[index] - 1); if (defGroup) { strcpy(value, defGroup->name); @@ -1448,7 +1449,8 @@ static int psys_vg_name_len__internal(PointerRNA *ptr, int index) ParticleSystem *psys = (ParticleSystem *)ptr->data; if (psys->vgroup[index] > 0) { - bDeformGroup *defGroup = BLI_findlink(&ob->defbase, psys->vgroup[index] - 1); + const ListBase *defbase = BKE_object_defgroup_list(ob); + bDeformGroup *defGroup = BLI_findlink(defbase, psys->vgroup[index] - 1); if (defGroup) { return strlen(defGroup->name); @@ -3752,7 +3754,7 @@ static void rna_def_particle_system(BlenderRNA *brna) /* vertex groups */ - /* note, internally store as ints, access as strings */ + /* NOTE: internally store as ints, access as strings. */ # if 0 /* int access. works ok but isn't useful for the UI */ prop = RNA_def_property(srna, "vertex_group_density", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "vgroup[0]"); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index bb4939a010b..ee509fa92d4 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -224,16 +224,10 @@ static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value) sizeof(agrp->name)); } -static IDProperty *rna_PoseBone_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_PoseBone_idprops(PointerRNA *ptr) { bPoseChannel *pchan = ptr->data; - - if (create && !pchan->prop) { - IDPropertyTemplate val = {0}; - pchan->prop = IDP_New(IDP_GROUP, &val, "RNA_PoseBone group"); - } - - return pchan->prop; + return &pchan->prop; } static void rna_Pose_ik_solver_set(struct PointerRNA *ptr, int value) diff --git a/source/blender/makesrna/intern/rna_pose_api.c b/source/blender/makesrna/intern/rna_pose_api.c index 0d35365c2d8..1e1667f0ae8 100644 --- a/source/blender/makesrna/intern/rna_pose_api.c +++ b/source/blender/makesrna/intern/rna_pose_api.c @@ -117,7 +117,7 @@ static void rna_Pose_apply_pose_from_action(ID *pose_owner, Object *pose_owner_ob = (Object *)pose_owner; AnimationEvalContext anim_eval_context = {CTX_data_depsgraph_pointer(C), evaluation_time}; - BKE_pose_apply_action(pose_owner_ob, action, &anim_eval_context); + BKE_pose_apply_action_selected_bones(pose_owner_ob, action, &anim_eval_context); /* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */ DEG_id_tag_update(pose_owner, ID_RECALC_GEOMETRY); diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 899c3397361..6008ef40b60 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -933,7 +933,7 @@ static const EnumPropertyItem *rna_EnumProperty_default_itemf(bContext *C, return eprop->item_fn(C, ptr, prop, r_free); } -/* XXX - not sure this is needed? */ +/* XXX: not sure this is needed? */ static int rna_EnumProperty_default_get(PointerRNA *ptr) { PropertyRNA *prop = (PropertyRNA *)ptr->data; @@ -1529,7 +1529,7 @@ int rna_property_override_diff_default(Main *bmain, BLI_assert(len_a == len_b); - /* Note: at this point, we are sure that when len_a is zero, + /* NOTE: at this point, we are sure that when len_a is zero, * we are not handling an (empty) array. */ const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 && @@ -1537,7 +1537,7 @@ int rna_property_override_diff_default(Main *bmain, const bool no_ownership = (prop_a->rnaprop->flag & PROP_PTR_NO_OWNERSHIP) != 0; - /* Note: we assume we only insert in ptr_a (i.e. we can only get new items in ptr_a), + /* NOTE: we assume we only insert in ptr_a (i.e. we can only get new items in ptr_a), * and that we never remove anything. */ const bool use_collection_insertion = (prop_a->rnaprop->flag_override & PROPOVERRIDE_LIBRARY_INSERTION) && @@ -1564,7 +1564,7 @@ int rna_property_override_diff_default(Main *bmain, const int comp = memcmp(array_a, array_b, sizeof(bool) * len_a); if (do_create && comp != 0) { - /* XXX TODO this will have to be refined to handle array items */ + /* XXX TODO: this will have to be refined to handle array items. */ op = BKE_lib_override_library_property_get(override, rna_path, &created); if (op != NULL && created) { @@ -1625,7 +1625,7 @@ int rna_property_override_diff_default(Main *bmain, const int comp = memcmp(array_a, array_b, sizeof(int) * len_a); if (do_create && comp != 0) { - /* XXX TODO this will have to be refined to handle array items */ + /* XXX TODO: this will have to be refined to handle array items. */ op = BKE_lib_override_library_property_get(override, rna_path, &created); if (op != NULL && created) { @@ -1686,7 +1686,7 @@ int rna_property_override_diff_default(Main *bmain, const int comp = memcmp(array_a, array_b, sizeof(float) * len_a); if (do_create && comp != 0) { - /* XXX TODO this will have to be refined to handle array items */ + /* XXX TODO: this will have to be refined to handle array items. */ op = BKE_lib_override_library_property_get(override, rna_path, &created); if (op != NULL && created) { @@ -1758,7 +1758,7 @@ int rna_property_override_diff_default(Main *bmain, ptr_a, rawprop_a, fixed_a, sizeof(fixed_a), &len_str_a); char *value_b = RNA_property_string_get_alloc( ptr_b, rawprop_b, fixed_b, sizeof(fixed_b), &len_str_b); - /* TODO we could do a check on length too, + /* TODO: we could do a check on length too, * but then we would not have a 'real' string comparison... * Maybe behind a eRNAOverrideMatch flag? */ # if 0 @@ -2079,7 +2079,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain), return changed; } - /* XXX TODO About range limits. + /* XXX TODO: About range limits. * Ideally, it would be great to get rid of RNA range in that specific case. * However, this won't be that easy and will add yet another layer of complexity in * generated code, not to mention that we could most likely *not* bypass custom setters anyway. @@ -2088,7 +2088,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain), * Time will say whether this is acceptable limitation or not. */ switch (RNA_property_type(prop_local)) { case PROP_BOOLEAN: - /* TODO support boolean ops? Really doubt this would ever be useful though... */ + /* TODO: support boolean ops? Really doubt this would ever be useful though. */ BLI_assert(0 && "Boolean properties support no override diff operation"); break; case PROP_INT: { @@ -2306,7 +2306,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain), return true; } case PROP_ENUM: - /* TODO support add/sub, for bitflags? */ + /* TODO: support add/sub, for bitflags? */ BLI_assert(0 && "Enum properties support no override diff operation"); break; case PROP_POINTER: @@ -2316,7 +2316,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain), BLI_assert(0 && "String properties support no override diff operation"); break; case PROP_COLLECTION: - /* XXX TODO support this of course... */ + /* XXX TODO: support this of course... */ BLI_assert(0 && "Collection properties support no override diff operation"); break; default: @@ -2564,7 +2564,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), case IDOVERRIDE_LIBRARY_OP_REPLACE: RNA_property_enum_set(ptr_dst, prop_dst, value); break; - /* TODO support add/sub, for bitflags? */ + /* TODO: support add/sub, for bitflags? */ default: BLI_assert(0 && "Unsupported RNA override operation on enum"); return false; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 503c4a1a1f8..5c9c7b50339 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -190,16 +190,6 @@ const EnumPropertyItem rna_enum_snap_node_element_items[] = { {0, NULL, 0, NULL, NULL}, }; -const EnumPropertyItem rna_enum_snap_seq_element_items[] = { - {SEQ_SNAP_TO_CURRENT_FRAME, - "CURRENT_FRAME", - ICON_NONE, - "Current Frame", - "Snap to current frame"}, - {SEQ_SNAP_TO_STRIP_HOLD, "STRIP_HOLD", ICON_NONE, "Hold Offset", "Snap to strip hold offset"}, - {0, NULL, 0, NULL, NULL}, -}; - #ifndef RNA_RUNTIME static const EnumPropertyItem snap_uv_element_items[] = { {SCE_SNAP_MODE_INCREMENT, @@ -1282,10 +1272,10 @@ static const EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext ID *id = ptr->owner_id; const bool is_render = (id && GS(id->name) == ID_SCE); - /* note, we need to act differently for render + /* NOTE(campbell): we need to act differently for render * where 'BW' will force grayscale even if the output format writes * as RGBA, this is age old blender convention and not sure how useful - * it really is but keep it for now - campbell */ + * it really is but keep it for now. */ char chan_flag = BKE_imtype_valid_channels(imf->imtype, true) | (is_render ? IMA_CHAN_FLAG_BW : 0); @@ -2176,7 +2166,7 @@ static char *rna_MeshStatVis_path(PointerRNA *UNUSED(ptr)) return BLI_strdup("tool_settings.statvis"); } -/* note: without this, when Multi-Paint is activated/deactivated, the colors +/* NOTE: without this, when Multi-Paint is activated/deactivated, the colors * will not change right away when multiple bones are selected, this function * is not for general use and only for the few cases where changing scene * settings and NOT for general purpose updates, possibly this should be @@ -3126,6 +3116,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Snapping", "Snap to strip edges or current frame"); RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1); RNA_def_property_boolean_default(prop, true); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* Publish message-bus. */ prop = RNA_def_property(srna, "snap_elements", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode"); @@ -3527,25 +3518,29 @@ static void rna_def_sequencer_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Fit Method", "Scale fit method"); /* Transform snapping. */ + prop = RNA_def_property(srna, "snap_to_current_frame", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "snap_mode", SEQ_SNAP_TO_CURRENT_FRAME); + RNA_def_property_ui_text(prop, "Current Frame", "Snap to current frame"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - /* Sequencer editor uses own set of snap modes */ - prop = RNA_def_property(srna, "snap_seq_element", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode"); - RNA_def_property_enum_items(prop, rna_enum_snap_seq_element_items); - RNA_def_property_ui_text(prop, "Snap To", "Type of element to snap to"); - RNA_def_property_flag(prop, PROP_ENUM_FLAG); + prop = RNA_def_property(srna, "snap_to_hold_offset", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "snap_mode", SEQ_SNAP_TO_STRIP_HOLD); + RNA_def_property_ui_text(prop, "Hold Offset", "Snap to strip hold offsets"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ prop = RNA_def_property(srna, "snap_ignore_muted", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_IGNORE_MUTED); - RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Ignore Muted Strips", "Don't snap to hidden strips"); prop = RNA_def_property(srna, "snap_ignore_sound", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_IGNORE_SOUND); - RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Ignore Sound Strips", "Don't snap to sound strips"); + prop = RNA_def_property(srna, "use_snap_current_frame_to_strips", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_CURRENT_FRAME_TO_STRIPS); + RNA_def_property_ui_text( + prop, "Snap Current Frame to Strips", "Snap current frame to strip start or end"); + prop = RNA_def_property(srna, "snap_distance", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "snap_distance"); RNA_def_property_int_default(prop, 15); @@ -5397,7 +5392,7 @@ static void rna_def_image_format_stereo3d_format(BlenderRNA *brna) } /* use for render output and image save operator, - * note: there are some cases where the members act differently when this is + * NOTE: there are some cases where the members act differently when this is * used from a scene, video formats can only be selected for render output * for example, this is checked by seeing if the ptr->owner_id is a Scene id */ @@ -7973,10 +7968,10 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "master_collection"); RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_clear_flag(prop, PROP_PTR_NO_OWNERSHIP); - RNA_def_property_ui_text( - prop, - "Collection", - "Scene master collection that objects and other collections in the scene"); + RNA_def_property_ui_text(prop, + "Collection", + "Scene root collection that owns all the objects and other collections " + "instantiated in the scene"); /* Scene Display */ prop = RNA_def_property(srna, "display", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index caecd9a07d8..3e292ea89e2 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -207,7 +207,6 @@ static void rna_Scene_alembic_export(Scene *scene, bool apply_subdiv, bool flatten_hierarchy, bool visible_objects_only, - bool renderable_only, bool face_sets, bool use_subdiv_schema, bool export_hair, @@ -241,7 +240,6 @@ static void rna_Scene_alembic_export(Scene *scene, .apply_subdiv = apply_subdiv, .flatten_hierarchy = flatten_hierarchy, .visible_objects_only = visible_objects_only, - .renderable_only = renderable_only, .face_sets = face_sets, .use_subdiv_schema = use_subdiv_schema, .export_hair = export_hair, @@ -383,11 +381,6 @@ void RNA_api_scene(StructRNA *srna) 0, "Visible layers only", "Export only objects in visible layers"); - RNA_def_boolean(func, - "renderable_only", - 0, - "Renderable objects only", - "Export only objects marked renderable in the outliner"); RNA_def_boolean(func, "face_sets", 0, "Facesets", "Export face sets"); RNA_def_boolean(func, "subdiv_schema", diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index 90029bd14a1..912f47ba9aa 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -495,7 +495,7 @@ static void rna_def_view2d(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "View2D", "Scroll and zoom for a 2D region"); RNA_def_struct_sdna(srna, "View2D"); - /* TODO more View2D properties could be exposed here (read-only) */ + /* TODO: more View2D properties could be exposed here (read-only). */ rna_def_view2d_api(srna); } diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 29100cd7658..b1f0b0d760f 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -28,6 +28,7 @@ #include "DNA_sequence_types.h" #include "DNA_vfont_types.h" +#include "BLI_iterator.h" #include "BLI_math.h" #include "BLT_translation.h" @@ -102,17 +103,6 @@ typedef struct SequenceSearchData { SequenceModifierData *smd; } SequenceSearchData; -/* build a temp reference to the parent */ -static void meta_tmp_ref(Sequence *seq_par, Sequence *seq) -{ - for (; seq; seq = seq->next) { - seq->tmp = seq_par; - if (seq->type == SEQ_TYPE_META) { - meta_tmp_ref(seq, seq->seqbase.first); - } - } -} - static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; @@ -203,46 +193,41 @@ static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *i { Scene *scene = (Scene *)ptr->owner_id; Editing *ed = SEQ_editing_get(scene, false); + SeqCollection *all_strips = SEQ_query_all_strips_recursive(&ed->seqbase); - meta_tmp_ref(NULL, ed->seqbase.first); + BLI_Iterator *bli_iter = MEM_callocN(sizeof(BLI_Iterator), __func__); + bli_iter->data = MEM_callocN(sizeof(SeqIterator), __func__); + iter->internal.custom = bli_iter; - rna_iterator_listbase_begin(iter, &ed->seqbase, NULL); -} - -static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), - Scene *scene, - PointerRNA *UNUSED(ptr)) -{ - Editing *ed = scene->ed; + if (!SEQ_iterator_ensure(all_strips, bli_iter->data, (Sequence **)&bli_iter->current)) { + SEQ_collection_free(all_strips); + } - SEQ_relations_free_imbuf(scene, &ed->seqbase, false); - SEQ_cache_cleanup(scene); + iter->valid = bli_iter->current != NULL; } static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter) { - ListBaseIterator *internal = &iter->internal.listbase; - Sequence *seq = (Sequence *)internal->link; + BLI_Iterator *bli_iter = iter->internal.custom; + bli_iter->current = SEQ_iterator_yield(bli_iter->data); + iter->valid = bli_iter->current != NULL; +} - if (seq->seqbase.first) { - internal->link = (Link *)seq->seqbase.first; - } - else if (seq->next) { - internal->link = (Link *)seq->next; - } - else { - internal->link = NULL; +static PointerRNA rna_SequenceEditor_sequences_all_get(CollectionPropertyIterator *iter) +{ + Sequence *seq = ((BLI_Iterator *)iter->internal.custom)->current; + return rna_pointer_inherit_refine(&iter->parent, &RNA_Sequence, seq); +} - do { - seq = seq->tmp; /* XXX - seq's don't reference their parents! */ - if (seq && seq->next) { - internal->link = (Link *)seq->next; - break; - } - } while (seq); +static void rna_SequenceEditor_sequences_all_end(CollectionPropertyIterator *iter) +{ + BLI_Iterator *bli_iter = iter->internal.custom; + SeqIterator *seq_iter = bli_iter->data; + if (seq_iter->collection != NULL) { + SEQ_collection_free(seq_iter->collection); } - - iter->valid = (internal->link != NULL); + MEM_freeN(seq_iter); + MEM_freeN(bli_iter); } static int rna_SequenceEditor_sequences_all_lookup_string(PointerRNA *ptr, @@ -260,6 +245,16 @@ static int rna_SequenceEditor_sequences_all_lookup_string(PointerRNA *ptr, return false; } +static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), + Scene *scene, + PointerRNA *UNUSED(ptr)) +{ + Editing *ed = scene->ed; + + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); + SEQ_cache_cleanup(scene); +} + /* internal use */ static int rna_SequenceEditor_elements_length(PointerRNA *ptr) { @@ -308,7 +303,7 @@ static void do_sequence_frame_change_update(Scene *scene, Sequence *seq) } if (SEQ_transform_test_overlap(seqbase, seq)) { - SEQ_transform_seqbase_shuffle(seqbase, seq, scene); /* XXX - BROKEN!, uses context seqbasep */ + SEQ_transform_seqbase_shuffle(seqbase, seq, scene); /* XXX: BROKEN!, uses context seqbasep. */ } SEQ_sort(seqbase); } @@ -488,7 +483,7 @@ static void rna_Sequence_channel_set(PointerRNA *ptr, int value) seq->machine = value; if (SEQ_transform_test_overlap(seqbase, seq)) { - /* XXX - BROKEN!, uses context seqbasep */ + /* XXX: BROKEN!, uses context seqbasep. */ SEQ_transform_seqbase_shuffle_ex(seqbase, seq, scene, channel_delta); } SEQ_sort(seqbase); @@ -739,16 +734,10 @@ static char *rna_Sequence_path(PointerRNA *ptr) } } -static IDProperty *rna_Sequence_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_Sequence_idprops(PointerRNA *ptr) { Sequence *seq = ptr->data; - - if (create && !seq->prop) { - IDPropertyTemplate val = {0}; - seq->prop = IDP_New(IDP_GROUP, &val, "Sequence ID properties"); - } - - return seq->prop; + return &seq->prop; } static bool rna_MovieSequence_reload_if_needed(ID *scene_id, Sequence *seq, Main *bmain) @@ -799,7 +788,7 @@ static PointerRNA rna_SequenceEditor_meta_stack_get(CollectionPropertyIterator * return rna_pointer_inherit_refine(&iter->parent, &RNA_Sequence, ms->parseq); } -/* TODO, expose seq path setting as a higher level sequencer BKE function */ +/* TODO: expose seq path setting as a higher level sequencer BKE function. */ static void rna_Sequence_filepath_set(PointerRNA *ptr, const char *value) { Sequence *seq = (Sequence *)(ptr->data); @@ -2009,8 +1998,8 @@ static void rna_def_editor(BlenderRNA *brna) RNA_def_property_collection_funcs(prop, "rna_SequenceEditor_sequences_all_begin", "rna_SequenceEditor_sequences_all_next", - NULL, - NULL, + "rna_SequenceEditor_sequences_all_end", + "rna_SequenceEditor_sequences_all_get", NULL, NULL, "rna_SequenceEditor_sequences_all_lookup_string", @@ -2513,7 +2502,7 @@ static void rna_def_movieclip(BlenderRNA *brna) srna, "MovieClip Sequence", "Sequence strip to load a video from the clip editor"); RNA_def_struct_sdna(srna, "Sequence"); - /* TODO - add clip property? */ + /* TODO: add clip property? */ prop = RNA_def_property(srna, "undistort", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "clip_flag", SEQ_MOVIECLIP_RENDER_UNDISTORTED); diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 8aab0c079a3..057f49c0319 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -30,6 +30,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "SEQ_edit.h" + #include "rna_internal.h" #ifdef RNA_RUNTIME @@ -99,6 +101,24 @@ static void rna_Sequences_move_strip_to_meta( WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); } +static Sequence *rna_Sequence_split( + ID *id, Sequence *seq, Main *bmain, int frame, int split_method) +{ + Scene *scene = (Scene *)id; + Editing *ed = SEQ_editing_get(scene, false); + ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); + + Sequence *r_seq = SEQ_edit_strip_split(bmain, scene, seqbase, seq, frame, split_method); + + /* Update depsgraph. */ + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); + + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); + + return r_seq; +} + static Sequence *rna_Sequences_new_clip(ID *id, ListBase *seqbase, Main *bmain, @@ -635,6 +655,12 @@ void RNA_api_sequence_strip(StructRNA *srna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem seq_split_method_items[] = { + {SEQ_SPLIT_SOFT, "SOFT", 0, "Soft", ""}, + {SEQ_SPLIT_HARD, "HARD", 0, "Hard", ""}, + {0, NULL, 0, NULL, NULL}, + }; + func = RNA_def_function(srna, "update", "rna_Sequence_update_rnafunc"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Update the strip dimensions"); @@ -676,6 +702,18 @@ void RNA_api_sequence_strip(StructRNA *srna) "Invalidate cached images for strip and all dependent strips"); parm = RNA_def_enum(func, "type", seq_cahce_type_items, 0, "Type", "Cache Type"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + + func = RNA_def_function(srna, "split", "rna_Sequence_split"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); + RNA_def_function_ui_description(func, "Split Sequence"); + parm = RNA_def_int( + func, "frame", 0, INT_MIN, INT_MAX, "", "Frame where to split the strip", INT_MIN, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_enum(func, "split_method", seq_split_method_items, 0, "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + /* Retirn type. */ + parm = RNA_def_pointer(func, "sequence", "Sequence", "", "Right side Sequence"); + RNA_def_function_return(func, parm); } void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop) diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c index 4a6cb0d740a..7c5212073ab 100644 --- a/source/blender/makesrna/intern/rna_shader_fx.c +++ b/source/blender/makesrna/intern/rna_shader_fx.c @@ -649,12 +649,12 @@ static void rna_def_shader_fx_flip(BlenderRNA *brna) RNA_define_lib_overridable(true); - prop = RNA_def_property(srna, "flip_horizontal", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_FLIP_HORIZONTAL); RNA_def_property_ui_text(prop, "Horizontal", "Flip image horizontally"); RNA_def_property_update(prop, NC_OBJECT | ND_SHADERFX, "rna_ShaderFx_update"); - prop = RNA_def_property(srna, "flip_vertical", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_FLIP_VERTICAL); RNA_def_property_ui_text(prop, "Vertical", "Flip image vertically"); RNA_def_property_update(prop, NC_OBJECT | ND_SHADERFX, "rna_ShaderFx_update"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d0a7e4aeea3..f2d2b190d87 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -509,6 +509,7 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = { #ifdef RNA_RUNTIME # include "DNA_anim_types.h" +# include "DNA_asset_types.h" # include "DNA_scene_types.h" # include "DNA_screen_types.h" # include "DNA_userdef_types.h" @@ -1041,16 +1042,10 @@ static bool rna_RegionView3D_is_orthographic_side_view_get(PointerRNA *ptr) return RV3D_VIEW_IS_AXIS(rv3d->view); } -static IDProperty *rna_View3DShading_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_View3DShading_idprops(PointerRNA *ptr) { View3DShading *shading = ptr->data; - - if (create && !shading->prop) { - IDPropertyTemplate val = {0}; - shading->prop = IDP_New(IDP_GROUP, &val, "View3DShading ID properties"); - } - - return shading->prop; + return &shading->prop; } static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -1839,7 +1834,7 @@ static void rna_SpaceTextEditor_updateEdited(Main *UNUSED(bmain), /* Space Properties */ -/* note: this function exists only to avoid id refcounting */ +/* NOTE: this function exists only to avoid id refcounting. */ static void rna_SpaceProperties_pin_id_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) @@ -2106,7 +2101,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr) switch (saction->mode) { case SACTCONT_ACTION: /* TODO: context selector could help decide this with more control? */ - adt = BKE_animdata_add_id(&obact->id); + adt = BKE_animdata_ensure_id(&obact->id); id = &obact->id; break; case SACTCONT_SHAPEKEY: { @@ -2114,7 +2109,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr) if (key == NULL) { return; } - adt = BKE_animdata_add_id(&key->id); + adt = BKE_animdata_ensure_id(&key->id); id = &key->id; break; } @@ -2136,7 +2131,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr) return; } - /* Exit editmode first - we cannot change actions while in tweakmode. */ + /* Exit editmode first - we cannot change actions while in tweak-mode. */ BKE_nla_tweakmode_exit(adt); /* To prevent data loss (i.e. if users flip between actions using the Browse menu), @@ -2567,6 +2562,8 @@ static PointerRNA rna_FileSelectParams_filter_id_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_FileSelectIDFilter, ptr->data); } +/* TODO use rna_def_asset_library_reference_common() */ + static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr) { FileAssetSelectParams *params = ptr->data; @@ -2574,7 +2571,7 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr) BLI_assert(ptr->type == &RNA_FileAssetSelectParams); /* Simple case: Predefined repo, just set the value. */ - if (params->asset_library.type < FILE_ASSET_LIBRARY_CUSTOM) { + if (params->asset_library.type < ASSET_LIBRARY_CUSTOM) { return params->asset_library.type; } @@ -2583,11 +2580,11 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr) const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( &U, params->asset_library.custom_library_index); if (user_library) { - return FILE_ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index; + return ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index; } BLI_assert(0); - return FILE_ASSET_LIBRARY_LOCAL; + return ASSET_LIBRARY_LOCAL; } static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int value) @@ -2595,26 +2592,26 @@ static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int val FileAssetSelectParams *params = ptr->data; /* Simple case: Predefined repo, just set the value. */ - if (value < FILE_ASSET_LIBRARY_CUSTOM) { + if (value < ASSET_LIBRARY_CUSTOM) { params->asset_library.type = value; params->asset_library.custom_library_index = -1; - BLI_assert(ELEM(value, FILE_ASSET_LIBRARY_LOCAL)); + BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL)); return; } const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( - &U, value - FILE_ASSET_LIBRARY_CUSTOM); + &U, value - ASSET_LIBRARY_CUSTOM); /* Note that the path isn't checked for validity here. If an invalid library path is used, the * Asset Browser can give a nice hint on what's wrong. */ const bool is_valid = (user_library->name[0] && user_library->path[0]); if (!user_library) { - params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL; + params->asset_library.type = ASSET_LIBRARY_LOCAL; params->asset_library.custom_library_index = -1; } else if (user_library && is_valid) { - params->asset_library.custom_library_index = value - FILE_ASSET_LIBRARY_CUSTOM; - params->asset_library.type = FILE_ASSET_LIBRARY_CUSTOM; + params->asset_library.custom_library_index = value - ASSET_LIBRARY_CUSTOM; + params->asset_library.type = ASSET_LIBRARY_CUSTOM; } } @@ -2623,8 +2620,8 @@ static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf( { const EnumPropertyItem predefined_items[] = { /* For the future. */ - // {FILE_ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"}, - {FILE_ASSET_LIBRARY_LOCAL, + // {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"}, + {ASSET_LIBRARY_LOCAL, "LOCAL", ICON_BLENDER, "Current File", @@ -2652,7 +2649,7 @@ static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf( } /* Use library path as description, it's a nice hint for users. */ - EnumPropertyItem tmp = {FILE_ASSET_LIBRARY_CUSTOM + i, + EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i, user_library->name, ICON_NONE, user_library->name, @@ -2697,6 +2694,32 @@ static int rna_FileBrowser_FileSelectEntry_name_length(PointerRNA *ptr) return (int)strlen(entry->name); } +static const EnumPropertyItem *rna_FileBrowser_FileSelectEntry_id_type_itemf( + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) +{ + const FileDirEntry *entry = ptr->data; + if (entry->blentype == 0) { + static const EnumPropertyItem none_items[] = { + {0, "NONE", 0, "None", ""}, + }; + return none_items; + } + + return rna_enum_id_type_items; +} + +static int rna_FileBrowser_FileSelectEntry_id_type_get(PointerRNA *ptr) +{ + const FileDirEntry *entry = ptr->data; + return entry->blentype; +} + +static PointerRNA rna_FileBrowser_FileSelectEntry_local_id_get(PointerRNA *ptr) +{ + const FileDirEntry *entry = ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_ID, entry->id); +} + static int rna_FileBrowser_FileSelectEntry_preview_icon_id_get(PointerRNA *ptr) { const FileDirEntry *entry = ptr->data; @@ -2721,7 +2744,7 @@ static StructRNA *rna_FileBrowser_params_typef(PointerRNA *ptr) return &RNA_FileAssetSelectParams; } - BLI_assert(!"Could not identify file select parameters"); + BLI_assert_msg(0, "Could not identify file select parameters"); return NULL; } @@ -2756,7 +2779,7 @@ static void rna_FileBrowser_FSMenuEntry_path_set(PointerRNA *ptr, const char *va { FSMenuEntry *fsm = ptr->data; - /* Note: this will write to file immediately. + /* NOTE: this will write to file immediately. * Not nice (and to be fixed ultimately), but acceptable in this case for now. */ ED_fsmenu_entry_set_path(fsm, value); } @@ -2775,7 +2798,7 @@ static void rna_FileBrowser_FSMenuEntry_name_set(PointerRNA *ptr, const char *va { FSMenuEntry *fsm = ptr->data; - /* Note: this will write to file immediately. + /* NOTE: this will write to file immediately. * Not nice (and to be fixed ultimately), but acceptable in this case for now. */ ED_fsmenu_entry_set_name(fsm, value); } @@ -2980,7 +3003,7 @@ static void rna_FileBrowser_FSMenu_active_range(PointerRNA *UNUSED(ptr), static void rna_FileBrowser_FSMenu_active_update(struct bContext *C, PointerRNA *ptr) { ScrArea *area = rna_area_from_space(ptr); - ED_file_change_dir_ex(C, (bScreen *)ptr->owner_id, area); + ED_file_change_dir_ex(C, area); } static int rna_FileBrowser_FSMenuSystem_active_get(PointerRNA *ptr) @@ -3177,11 +3200,9 @@ static void rna_spreadsheet_context_update(Main *UNUSED(bmain), } } -static void rna_spreadsheet_set_geometry_node_context(SpaceSpreadsheet *sspreadsheet, - SpaceNode *snode, - bNode *node) +static void rna_SpaceSpreadsheet_context_path_guess(SpaceSpreadsheet *sspreadsheet, bContext *C) { - ED_spreadsheet_set_geometry_node_context(sspreadsheet, snode, node); + ED_spreadsheet_context_path_guess(C, sspreadsheet); ED_spreadsheet_context_path_update_tag(sspreadsheet); WM_main_add_notifier(NC_SPACE | ND_SPACE_SPREADSHEET, NULL); } @@ -3196,6 +3217,45 @@ static const EnumPropertyItem dt_uv_items[] = { {0, NULL, 0, NULL, NULL}, }; +static struct IDFilterEnumPropertyItem rna_enum_space_file_id_filter_categories[] = { + /* Categories */ + {FILTER_ID_SCE, "category_scene", ICON_SCENE_DATA, "Scenes", "Show scenes"}, + {FILTER_ID_AC, "category_animation", ICON_ANIM_DATA, "Animations", "Show animation data"}, + {FILTER_ID_OB | FILTER_ID_GR, + "category_object", + ICON_OUTLINER_COLLECTION, + "Objects & Collections", + "Show objects and collections"}, + {FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_HA | + FILTER_ID_PT | FILTER_ID_VO, + "category_geometry", + ICON_NODETREE, + "Geometry", + "Show meshes, curves, lattice, armatures and metaballs data"}, + {FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE, + "category_shading", + ICON_MATERIAL_DATA, + "Shading", + "Show materials, nodetrees, textures and Freestyle's linestyles"}, + {FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO, + "category_image", + ICON_IMAGE_DATA, + "Images & Sounds", + "Show images, movie clips, sounds and masks"}, + {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_LP | FILTER_ID_SPK | FILTER_ID_WO, + "category_environment", + ICON_WORLD_DATA, + "Environment", + "Show worlds, lights, cameras and speakers"}, + {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | + FILTER_ID_VF | FILTER_ID_CF | FILTER_ID_WS, + "category_misc", + ICON_GREASEPENCIL, + "Miscellaneous", + "Show other data types"}, + {0, NULL, 0, NULL, NULL}, +}; + static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int region_type_mask) { PropertyRNA *prop; @@ -3438,7 +3498,7 @@ static void rna_def_space_image_uv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "UV Opacity", "Opacity of UV overlays"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); - /* todo: move edge and face drawing options here from G.f */ + /* TODO: move edge and face drawing options here from `G.f`. */ prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, pixel_snap_mode_items); @@ -5073,7 +5133,7 @@ static void rna_def_space_properties(BlenderRNA *brna) prop = RNA_def_property(srna, "pin_id", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "pinid"); RNA_def_property_struct_type(prop, "ID"); - /* note: custom set function is ONLY to avoid rna setting a user for this. */ + /* NOTE: custom set function is ONLY to avoid rna setting a user for this. */ RNA_def_property_pointer_funcs( prop, NULL, "rna_SpaceProperties_pin_id_set", "rna_SpaceProperties_pin_id_typef", NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK); @@ -6143,142 +6203,6 @@ static void rna_def_space_console(BlenderRNA *brna) /* Filter for datablock types in link/append. */ static void rna_def_fileselect_idfilter(BlenderRNA *brna) { - struct IDFilterBoolean { - /* 64 bit, so we can't use bitflag enum. */ - const uint64_t flag; - const char *identifier; - const int icon; - const char *name; - const char *description; - }; - - static const struct IDFilterBoolean booleans[] = { - /* Datablocks */ - {FILTER_ID_AC, "filter_action", ICON_ANIM_DATA, "Actions", "Show Action data-blocks"}, - {FILTER_ID_AR, - "filter_armature", - ICON_ARMATURE_DATA, - "Armatures", - "Show Armature data-blocks"}, - {FILTER_ID_BR, "filter_brush", ICON_BRUSH_DATA, "Brushes", "Show Brushes data-blocks"}, - {FILTER_ID_CA, "filter_camera", ICON_CAMERA_DATA, "Cameras", "Show Camera data-blocks"}, - {FILTER_ID_CF, "filter_cachefile", ICON_FILE, "Cache Files", "Show Cache File data-blocks"}, - {FILTER_ID_CU, "filter_curve", ICON_CURVE_DATA, "Curves", "Show Curve data-blocks"}, - {FILTER_ID_GD, - "filter_grease_pencil", - ICON_GREASEPENCIL, - "Grease Pencil", - "Show Grease pencil data-blocks"}, - {FILTER_ID_GR, - "filter_group", - ICON_OUTLINER_COLLECTION, - "Collections", - "Show Collection data-blocks"}, - {FILTER_ID_HA, "filter_hair", ICON_HAIR_DATA, "Hairs", "Show/hide Hair data-blocks"}, - {FILTER_ID_IM, "filter_image", ICON_IMAGE_DATA, "Images", "Show Image data-blocks"}, - {FILTER_ID_LA, "filter_light", ICON_LIGHT_DATA, "Lights", "Show Light data-blocks"}, - {FILTER_ID_LP, - "filter_light_probe", - ICON_OUTLINER_DATA_LIGHTPROBE, - "Light Probes", - "Show Light Probe data-blocks"}, - {FILTER_ID_LS, - "filter_linestyle", - ICON_LINE_DATA, - "Freestyle Linestyles", - "Show Freestyle's Line Style data-blocks"}, - {FILTER_ID_LT, "filter_lattice", ICON_LATTICE_DATA, "Lattices", "Show Lattice data-blocks"}, - {FILTER_ID_MA, - "filter_material", - ICON_MATERIAL_DATA, - "Materials", - "Show Material data-blocks"}, - {FILTER_ID_MB, "filter_metaball", ICON_META_DATA, "Metaballs", "Show Metaball data-blocks"}, - {FILTER_ID_MC, - "filter_movie_clip", - ICON_TRACKER_DATA, - "Movie Clips", - "Show Movie Clip data-blocks"}, - {FILTER_ID_ME, "filter_mesh", ICON_MESH_DATA, "Meshes", "Show Mesh data-blocks"}, - {FILTER_ID_MSK, "filter_mask", ICON_MOD_MASK, "Masks", "Show Mask data-blocks"}, - {FILTER_ID_NT, - "filter_node_tree", - ICON_NODETREE, - "Node Trees", - "Show Node Tree data-blocks"}, - {FILTER_ID_OB, "filter_object", ICON_OBJECT_DATA, "Objects", "Show Object data-blocks"}, - {FILTER_ID_PA, - "filter_particle_settings", - ICON_PARTICLE_DATA, - "Particles Settings", - "Show Particle Settings data-blocks"}, - {FILTER_ID_PAL, "filter_palette", ICON_COLOR, "Palettes", "Show Palette data-blocks"}, - {FILTER_ID_PC, - "filter_paint_curve", - ICON_CURVE_BEZCURVE, - "Paint Curves", - "Show Paint Curve data-blocks"}, - {FILTER_ID_PT, - "filter_pointcloud", - ICON_POINTCLOUD_DATA, - "Point Clouds", - "Show/hide Point Cloud data-blocks"}, - {FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"}, - {FILTER_ID_SIM, - "filter_simulation", - ICON_PHYSICS, - "Simulations", - "Show Simulation data-blocks"}, /* TODO: Use correct icon. */ - {FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"}, - {FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"}, - {FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"}, - {FILTER_ID_TXT, "filter_text", ICON_TEXT, "Texts", "Show Text data-blocks"}, - {FILTER_ID_VF, "filter_font", ICON_FONT_DATA, "Fonts", "Show Font data-blocks"}, - {FILTER_ID_VO, "filter_volume", ICON_VOLUME_DATA, "Volumes", "Show/hide Volume data-blocks"}, - {FILTER_ID_WO, "filter_world", ICON_WORLD_DATA, "Worlds", "Show World data-blocks"}, - {FILTER_ID_WS, - "filter_work_space", - ICON_WORKSPACE, - "Workspaces", - "Show workspace data-blocks"}, - - /* Categories */ - {FILTER_ID_SCE, "category_scene", ICON_SCENE_DATA, "Scenes", "Show scenes"}, - {FILTER_ID_AC, "category_animation", ICON_ANIM_DATA, "Animations", "Show animation data"}, - {FILTER_ID_OB | FILTER_ID_GR, - "category_object", - ICON_OUTLINER_COLLECTION, - "Objects & Collections", - "Show objects and collections"}, - {FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_HA | - FILTER_ID_PT | FILTER_ID_VO, - "category_geometry", - ICON_NODETREE, - "Geometry", - "Show meshes, curves, lattice, armatures and metaballs data"}, - {FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE, - "category_shading", - ICON_MATERIAL_DATA, - "Shading", - "Show materials, nodetrees, textures and Freestyle's linestyles"}, - {FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO, - "category_image", - ICON_IMAGE_DATA, - "Images & Sounds", - "Show images, movie clips, sounds and masks"}, - {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_LP | FILTER_ID_SPK | FILTER_ID_WO, - "category_environment", - ICON_WORLD_DATA, - "Environment", - "Show worlds, lights, cameras and speakers"}, - {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | - FILTER_ID_VF | FILTER_ID_CF | FILTER_ID_WS, - "category_misc", - ICON_GREASEPENCIL, - "Miscellaneous", - "Show other data types"}, - - {0, NULL, 0, NULL, NULL}}; StructRNA *srna = RNA_def_struct(brna, "FileSelectIDFilter", NULL); RNA_def_struct_sdna(srna, "FileSelectParams"); @@ -6286,12 +6210,23 @@ static void rna_def_fileselect_idfilter(BlenderRNA *brna) RNA_def_struct_ui_text( srna, "File Select ID Filter", "Which ID types to show/hide, when browsing a library"); - for (int i = 0; booleans[i].identifier; i++) { - PropertyRNA *prop = RNA_def_property(srna, booleans[i].identifier, PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "filter_id", booleans[i].flag); - RNA_def_property_ui_text(prop, booleans[i].name, booleans[i].description); - RNA_def_property_ui_icon(prop, booleans[i].icon, 0); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + const struct IDFilterEnumPropertyItem *individual_ids_and_categories[] = { + rna_enum_id_type_filter_items, + rna_enum_space_file_id_filter_categories, + NULL, + }; + for (uint i = 0; individual_ids_and_categories[i]; i++) { + for (int j = 0; individual_ids_and_categories[i][j].identifier; j++) { + PropertyRNA *prop = RNA_def_property( + srna, individual_ids_and_categories[i][j].identifier, PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "filter_id", individual_ids_and_categories[i][j].flag); + RNA_def_property_ui_text(prop, + individual_ids_and_categories[i][j].name, + individual_ids_and_categories[i][j].description); + RNA_def_property_ui_icon(prop, individual_ids_and_categories[i][j].icon, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + } } } @@ -6311,6 +6246,28 @@ static void rna_def_fileselect_entry(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_struct_name_property(srna, prop); + prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_id_type_items); + RNA_def_property_enum_funcs(prop, + "rna_FileBrowser_FileSelectEntry_id_type_get", + NULL, + "rna_FileBrowser_FileSelectEntry_id_type_itemf"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, + "Data-block Type", + "The type of the data-block, if the file represents one ('NONE' otherwise)"); + + prop = RNA_def_property(srna, "local_id", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ID"); + RNA_def_property_pointer_funcs( + prop, "rna_FileBrowser_FileSelectEntry_local_id_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, + "", + "The local data-block this file represents; only valid if that is a " + "data-block in this file"); + RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_int( srna, "preview_icon_id", @@ -6547,7 +6504,7 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - /* XXX copied from rna_def_fileselect_idfilter. */ + /* XXX copied from rna_enum_id_type_filter_items. */ static const EnumPropertyItem asset_category_items[] = { {FILTER_ID_SCE, "SCENES", ICON_SCENE_DATA, "Scenes", "Show scenes"}, {FILTER_ID_AC, "ANIMATIONS", ICON_ANIM_DATA, "Animations", "Show animation data"}, @@ -7646,13 +7603,16 @@ static void rna_def_space_spreadsheet_context_path(BlenderRNA *brna, PropertyRNA func = RNA_def_function(srna, "clear", "rna_SpaceSpreadsheet_context_path_clear"); RNA_def_function_ui_description(func, "Clear entire context path"); + + func = RNA_def_function(srna, "guess", "rna_SpaceSpreadsheet_context_path_guess"); + RNA_def_function_ui_description(func, "Guess the context path from the current context"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); } static void rna_def_space_spreadsheet(BlenderRNA *brna) { - PropertyRNA *prop, *parm; + PropertyRNA *prop; StructRNA *srna; - FunctionRNA *func; static const EnumPropertyItem geometry_component_type_items[] = { {GEO_COMPONENT_TYPE_MESH, @@ -7689,6 +7649,11 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna) ICON_NONE, "Original", "Use data from original object without any modifiers applied"}, + {SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE, + "VIEWER_NODE", + ICON_NONE, + "Viewer Node", + "Use intermediate data from viewer node"}, {0, NULL, 0, NULL, NULL}, }; @@ -7764,16 +7729,6 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna) RNA_def_property_struct_type(prop, "SpreadsheetRowFilter"); RNA_def_property_ui_text(prop, "Row Filters", "Filters to remove rows from the displayed data"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL); - - func = RNA_def_function( - srna, "set_geometry_node_context", "rna_spreadsheet_set_geometry_node_context"); - RNA_def_function_ui_description( - func, "Update context_path to point to a specific node in a node editor"); - parm = RNA_def_pointer( - func, "node_editor", "SpaceNodeEditor", "", "Editor to take the context from"); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - parm = RNA_def_pointer(func, "node", "Node", "", ""); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } void RNA_def_space(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c index c0bd9fd92a2..223e6389942 100644 --- a/source/blender/makesrna/intern/rna_timeline.c +++ b/source/blender/makesrna/intern/rna_timeline.c @@ -33,16 +33,10 @@ # include "BKE_idprop.h" # include "WM_api.h" -static IDProperty *rna_TimelineMarker_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_TimelineMarker_idprops(PointerRNA *ptr) { TimeMarker *marker = ptr->data; - - if (create && marker->prop == NULL) { - IDPropertyTemplate val = {0}; - marker->prop = IDP_New(IDP_GROUP, &val, "Marker ID properties"); - } - - return marker->prop; + return &marker->prop; } static void rna_TimelineMarker_update(Main *UNUSED(bmain), diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index acf580e3ddf..a88b100435a 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -452,15 +452,31 @@ static unsigned int rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA *UNUSED(p return UILST_FLT_ITEM; } -static IDProperty *rna_UIList_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_UIList_idprops(PointerRNA *ptr) { uiList *ui_list = (uiList *)ptr->data; - if (create && !ui_list->properties) { - IDPropertyTemplate val = {0}; - ui_list->properties = IDP_New(IDP_GROUP, &val, "RNA_UIList IDproperties group"); + return &ui_list->properties; +} + +static void rna_UIList_list_id_get(PointerRNA *ptr, char *value) +{ + uiList *ui_list = (uiList *)ptr->data; + if (!ui_list->type) { + value[0] = '\0'; + return; + } + + strcpy(value, WM_uilisttype_list_id_get(ui_list->type, ui_list)); +} + +static int rna_UIList_list_id_length(PointerRNA *ptr) +{ + uiList *ui_list = (uiList *)ptr->data; + if (!ui_list->type) { + return 0; } - return ui_list->properties; + return strlen(WM_uilisttype_list_id_get(ui_list->type, ui_list)); } static void uilist_draw_item(uiList *ui_list, @@ -553,7 +569,7 @@ static void uilist_filter_items(uiList *ui_list, RNA_parameter_dynamic_length_get(&list, parm), "filter_flags", len); - /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ + /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ filter_flags = NULL; } else { @@ -569,7 +585,7 @@ static void uilist_filter_items(uiList *ui_list, RNA_parameter_dynamic_length_get(&list, parm), "filter_neworder", len); - /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ + /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ filter_neworder = NULL; } else { @@ -638,7 +654,7 @@ static void uilist_filter_items(uiList *ui_list, RNA_parameter_list_free(&list); } -static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type) +static void rna_UIList_unregister(Main *bmain, StructRNA *type) { uiListType *ult = RNA_struct_blender_type_get(type); @@ -649,7 +665,7 @@ static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type) RNA_struct_free_extension(type, &ult->rna_ext); RNA_struct_free(&BLENDER_RNA, type); - WM_uilisttype_freelink(ult); + WM_uilisttype_remove_ptr(bmain, ult); /* update while blender is running */ WM_main_add_notifier(NC_WINDOW, NULL); @@ -1019,7 +1035,7 @@ static void rna_Panel_bl_description_set(PointerRNA *ptr, const char *value) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */ } else { - BLI_assert(!"setting the bl_description on a non-builtin panel"); + BLI_assert_msg(0, "setting the bl_description on a non-builtin panel"); } } @@ -1031,7 +1047,7 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */ } else { - BLI_assert(!"setting the bl_description on a non-builtin menu"); + BLI_assert_msg(0, "setting the bl_description on a non-builtin menu"); } } @@ -1540,6 +1556,16 @@ static void rna_def_uilist(BlenderRNA *brna) "script, then bl_idname = \"OBJECT_UL_vgroups\")"); /* Data */ + /* Note that this is the "non-full" list-ID as obtained through #WM_uilisttype_list_id_get(), + * which differs from the (internal) `uiList.list_id`. */ + prop = RNA_def_property(srna, "list_id", PROP_STRING, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_string_funcs(prop, "rna_UIList_list_id_get", "rna_UIList_list_id_length", NULL); + RNA_def_property_ui_text(prop, + "List Name", + "Identifier of the list, if any was passed to the \"list_id\" " + "parameter of \"template_list()\""); + prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_uilist_layout_type_items); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index aa235b599b7..e06cc39a88b 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -50,6 +50,8 @@ const EnumPropertyItem rna_enum_icon_items[] = { #ifdef RNA_RUNTIME +# include "DNA_asset_types.h" + const char *rna_translate_ui_text( const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, bool translate) { @@ -525,6 +527,46 @@ static void rna_uiTemplateAnyID(uiLayout *layout, uiTemplateAnyID(layout, ptr, propname, proptypename, name); } +void rna_uiTemplateList(uiLayout *layout, + struct bContext *C, + const char *listtype_name, + const char *list_id, + struct PointerRNA *dataptr, + const char *propname, + struct PointerRNA *active_dataptr, + const char *active_propname, + const char *item_dyntip_propname, + const int rows, + const int maxrows, + const int layout_type, + const int columns, + const bool sort_reverse, + const bool sort_lock) +{ + int flags = UI_TEMPLATE_LIST_FLAG_NONE; + if (sort_reverse) { + flags |= UI_TEMPLATE_LIST_SORT_REVERSE; + } + if (sort_lock) { + flags |= UI_TEMPLATE_LIST_SORT_LOCK; + } + + uiTemplateList(layout, + C, + listtype_name, + list_id, + dataptr, + propname, + active_dataptr, + active_propname, + item_dyntip_propname, + rows, + maxrows, + layout_type, + columns, + flags); +} + static void rna_uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, @@ -570,6 +612,69 @@ static void rna_uiTemplateEventFromKeymapItem( uiTemplateEventFromKeymapItem(layout, name, kmi, true); } +static void rna_uiTemplateAssetView(uiLayout *layout, + bContext *C, + const char *list_id, + PointerRNA *asset_library_dataptr, + const char *asset_library_propname, + PointerRNA *assets_dataptr, + const char *assets_propname, + PointerRNA *active_dataptr, + const char *active_propname, + int filter_id_types, + const char *activate_opname, + PointerRNA *r_activate_op_properties, + const char *drag_opname, + PointerRNA *r_drag_op_properties) +{ + AssetFilterSettings filter_settings = { + .id_types = filter_id_types ? filter_id_types : FILTER_ID_ALL, + }; + uiTemplateAssetView(layout, + C, + list_id, + asset_library_dataptr, + asset_library_propname, + assets_dataptr, + assets_propname, + active_dataptr, + active_propname, + &filter_settings, + activate_opname, + r_activate_op_properties, + drag_opname, + r_drag_op_properties); +} + +/** + * XXX Remove filter items that require more than 32 bits for storage. RNA enums don't support + * that currently. + */ +static const EnumPropertyItem *rna_uiTemplateAssetView_filter_id_types_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + EnumPropertyItem *items = NULL; + int totitem = 0; + + for (int i = 0; rna_enum_id_type_filter_items[i].identifier; i++) { + if (rna_enum_id_type_filter_items[i].flag > (1ULL << 31)) { + continue; + } + + EnumPropertyItem tmp = {0, "", 0, "", ""}; + tmp.value = rna_enum_id_type_filter_items[i].flag; + tmp.identifier = rna_enum_id_type_filter_items[i].identifier; + tmp.icon = rna_enum_id_type_filter_items[i].icon; + tmp.name = rna_enum_id_type_filter_items[i].name; + tmp.description = rna_enum_id_type_filter_items[i].description; + RNA_enum_item_add(&items, &totitem, &tmp); + } + RNA_enum_item_end(&items, &totitem); + + *r_free = true; + return items; +} + static uiLayout *rna_uiLayoutRowWithHeading( uiLayout *layout, bool align, const char *heading, const char *heading_ctxt, bool translate) { @@ -1508,7 +1613,7 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_pointer(func, "clip_user", "MovieClipUser", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); - func = RNA_def_function(srna, "template_list", "uiTemplateList"); + func = RNA_def_function(srna, "template_list", "rna_uiTemplateList"); RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups."); RNA_def_function_flag(func, FUNC_USE_CONTEXT); parm = RNA_def_string(func, "listtype_name", NULL, 0, "", "Identifier of the list type to use"); @@ -1689,6 +1794,81 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_property_ui_text(parm, "Item", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); api_ui_item_common_text(func); + + func = RNA_def_function(srna, "template_asset_view", "rna_uiTemplateAssetView"); + RNA_def_function_ui_description(func, "Item. A scrollable list of assets in a grid view"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm = RNA_def_string(func, + "list_id", + NULL, + 0, + "", + "Identifier of this asset view. Necessary to tell apart different asset " + "views and to idenify an asset view read from a .blend"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, + "asset_library_dataptr", + "AnyType", + "", + "Data from which to take the active asset library property"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + parm = RNA_def_string( + func, "asset_library_propname", NULL, 0, "", "Identifier of the asset library property"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "assets_dataptr", "AnyType", "", "Data from which to take the asset list property"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + parm = RNA_def_string( + func, "assets_propname", NULL, 0, "", "Identifier of the asset list property"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, + "active_dataptr", + "AnyType", + "", + "Data from which to take the integer property, index of the active item"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + parm = RNA_def_string( + func, + "active_propname", + NULL, + 0, + "", + "Identifier of the integer property in active_data, index of the active item"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_property(func, "filter_id_types", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(parm, DummyRNA_NULL_items); + RNA_def_property_enum_funcs(parm, NULL, NULL, "rna_uiTemplateAssetView_filter_id_types_itemf"); + RNA_def_property_flag(parm, PROP_ENUM_FLAG); + RNA_def_string(func, + "activate_operator", + NULL, + 0, + "", + "Name of a custom operator to invoke when activating an item"); + parm = RNA_def_pointer( + func, + "activate_operator_properties", + "OperatorProperties", + "", + "Operator properties to fill in for the custom activate operator passed to the template"); + RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + RNA_def_function_output(func, parm); + RNA_def_string(func, + "drag_operator", + NULL, + 0, + "", + "Name of a custom operator to invoke when starting to drag an item. Never " + "invoked together with the `active_operator` (if set), it's either the drag or " + "the activate one"); + parm = RNA_def_pointer( + func, + "drag_operator_properties", + "OperatorProperties", + "", + "Operator properties to fill in for the custom drag operator passed to the template"); + RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + RNA_def_function_output(func, parm); } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 3b7af07479c..d29a90a1886 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -809,14 +809,9 @@ static const EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C } # endif -static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_AddonPref_idprops(PointerRNA *ptr) { - if (create && !ptr->data) { - IDPropertyTemplate val = {0}; - ptr->data = IDP_New(IDP_GROUP, &val, "RNA_AddonPreferences group"); - } - - return ptr->data; + return (IDProperty **)&ptr->data; } static PointerRNA rna_Addon_preferences_get(PointerRNA *ptr) @@ -1105,7 +1100,7 @@ int rna_show_statusbar_vram_editable(struct PointerRNA *UNUSED(ptr), const char static size_t max_memory_in_megabytes(void) { /* Maximum addressable bytes on this platform. */ - const size_t limit_bytes = (((size_t)1) << ((sizeof(size_t[8])) - 1)); + const size_t limit_bytes = (((size_t)1) << (sizeof(size_t[8]) - 1)); /* Convert it to megabytes and return. */ return (limit_bytes >> 20); } @@ -3460,7 +3455,7 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text( prop, "Keyframe Scale Factor", "Scale factor for adjusting the height of keyframes"); - /* Note: These limits prevent buttons overlapping (min), and excessive size... (max) */ + /* NOTE: These limits prevent buttons overlapping (min), and excessive size... (max). */ RNA_def_property_range(prop, 0.8f, 5.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, "rna_userdef_theme_update"); @@ -6161,7 +6156,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) "Python Scripts Directory", "Alternate script path, matching the default layout with subdirectories: " "startup, addons, modules, and presets (requires restart)"); - /* TODO, editing should reset sys.path! */ + /* TODO: editing should reset sys.path! */ prop = RNA_def_property(srna, "i18n_branches_directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "i18ndir"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index a563541b968..2a4abac04f8 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -568,14 +568,9 @@ static StructRNA *rna_OperatorProperties_refine(PointerRNA *ptr) } } -static IDProperty *rna_OperatorProperties_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_OperatorProperties_idprops(PointerRNA *ptr) { - if (create && !ptr->data) { - IDPropertyTemplate val = {0}; - ptr->data = IDP_New(IDP_GROUP, &val, "RNA_OperatorProperties group"); - } - - return ptr->data; + return (IDProperty **)&ptr->data; } static void rna_Operator_name_get(PointerRNA *ptr, char *value) @@ -1120,13 +1115,9 @@ static PointerRNA rna_wmKeyConfig_preferences_get(PointerRNA *ptr) } } -static IDProperty *rna_wmKeyConfigPref_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_wmKeyConfigPref_idprops(PointerRNA *ptr) { - if (create && !ptr->data) { - IDPropertyTemplate val = {0}; - ptr->data = IDP_New(IDP_GROUP, &val, "RNA_KeyConfigPreferences group"); - } - return ptr->data; + return (IDProperty **)&ptr->data; } static void rna_wmKeyConfigPref_unregister(Main *UNUSED(bmain), StructRNA *type) @@ -1774,7 +1765,7 @@ static void rna_Operator_bl_idname_set(PointerRNA *ptr, const char *value) BLI_strncpy(str, value, OP_MAX_TYPENAME); /* utf8 already ensured */ } else { - BLI_assert(!"setting the bl_idname on a non-builtin operator"); + BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator"); } } @@ -1786,7 +1777,7 @@ static void rna_Operator_bl_label_set(PointerRNA *ptr, const char *value) BLI_strncpy(str, value, OP_MAX_TYPENAME); /* utf8 already ensured */ } else { - BLI_assert(!"setting the bl_label on a non-builtin operator"); + BLI_assert_msg(0, "setting the bl_label on a non-builtin operator"); } } diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index e7ca41bb5be..bde15daa682 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -641,7 +641,7 @@ static wmEvent *rna_Window_event_add_simulate(wmWindow *win, e.is_repeat = false; e.x = x; e.y = y; - /* Note: KM_MOD_FIRST, KM_MOD_SECOND aren't used anywhere, set as bools */ + /* NOTE: KM_MOD_FIRST, KM_MOD_SECOND aren't used anywhere, set as bools. */ e.shift = shift; e.ctrl = ctrl; e.alt = alt; diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index e91df38c96e..6a1574f3dbe 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -244,7 +244,7 @@ static void rna_Gizmo_bl_idname_set(PointerRNA *ptr, const char *value) BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */ } else { - BLI_assert(!"setting the bl_idname on a non-builtin operator"); + BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator"); } } @@ -293,14 +293,9 @@ static StructRNA *rna_GizmoProperties_refine(PointerRNA *ptr) } } -static IDProperty *rna_GizmoProperties_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_GizmoProperties_idprops(PointerRNA *ptr) { - if (create && !ptr->data) { - IDPropertyTemplate val = {0}; - ptr->data = IDP_New(IDP_GROUP, &val, "RNA_GizmoProperties group"); - } - - return ptr->data; + return (IDProperty **)&ptr->data; } static PointerRNA rna_Gizmo_properties_get(PointerRNA *ptr) @@ -585,14 +580,9 @@ static StructRNA *rna_GizmoGroupProperties_refine(PointerRNA *ptr) } } -static IDProperty *rna_GizmoGroupProperties_idprops(PointerRNA *ptr, bool create) +static IDProperty **rna_GizmoGroupProperties_idprops(PointerRNA *ptr) { - if (create && !ptr->data) { - IDPropertyTemplate val = {0}; - ptr->data = IDP_New(IDP_GROUP, &val, "RNA_GizmoGroupProperties group"); - } - - return ptr->data; + return (IDProperty **)&ptr->data; } static wmGizmo *rna_GizmoGroup_gizmo_new(wmGizmoGroup *gzgroup, @@ -653,7 +643,7 @@ static void rna_GizmoGroup_bl_idname_set(PointerRNA *ptr, const char *value) BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */ } else { - BLI_assert(!"setting the bl_idname on a non-builtin operator"); + BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator"); } } @@ -665,7 +655,7 @@ static void rna_GizmoGroup_bl_label_set(PointerRNA *ptr, const char *value) BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */ } else { - BLI_assert(!"setting the bl_label on a non-builtin operator"); + BLI_assert_msg(0, "setting the bl_label on a non-builtin operator"); } } @@ -1097,7 +1087,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); parm = RNA_def_pointer(func, "event", "Event", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); - /* TODO, should be a enum-flag */ + /* TODO: should be a enum-flag. */ parm = RNA_def_enum_flag(func, "tweak", tweak_actions, 0, "Tweak", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_enum_flag( diff --git a/source/blender/makesrna/intern/rna_wm_gizmo_api.c b/source/blender/makesrna/intern/rna_wm_gizmo_api.c index b4b7e02a95b..d6f2ffca65f 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo_api.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo_api.c @@ -263,7 +263,7 @@ void RNA_api_gizmo(StructRNA *srna) /* Property API */ /* Define Properties */ - /* note, 'target_set_handler' is defined in 'bpy_rna_gizmo.c' */ + /* NOTE: 'target_set_handler' is defined in `bpy_rna_gizmo.c`. */ func = RNA_def_function(srna, "target_set_prop", "rna_gizmo_target_set_prop"); RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, ""); @@ -292,7 +292,7 @@ void RNA_api_gizmo(StructRNA *srna) RNA_def_function_return(func, parm); /* Access Properties */ - /* note, 'target_get', 'target_set' is defined in 'bpy_rna_gizmo.c' */ + /* NOTE: 'target_get', 'target_set' is defined in `bpy_rna_gizmo.c`. */ func = RNA_def_function(srna, "target_is_valid", "rna_gizmo_target_is_valid"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_string(func, "property", NULL, 0, "", "Property identifier"); diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c index 6b52a38c2da..b053bb0ff62 100644 --- a/source/blender/makesrna/intern/rna_workspace.c +++ b/source/blender/makesrna/intern/rna_workspace.c @@ -107,6 +107,18 @@ static void rna_WorkSpace_owner_ids_clear(WorkSpace *workspace) WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, workspace); } +static int rna_WorkSpace_active_asset_library_get(PointerRNA *ptr) +{ + const WorkSpace *workspace = ptr->data; + return rna_asset_library_reference_get(&workspace->active_asset_library); +} + +static void rna_WorkSpace_active_asset_library_set(PointerRNA *ptr, int value) +{ + WorkSpace *workspace = ptr->data; + rna_asset_library_reference_set(&workspace->active_asset_library, value); +} + static bToolRef *rna_WorkSpace_tools_from_tkey(WorkSpace *workspace, const bToolKey *tkey, bool create) @@ -407,6 +419,14 @@ static void rna_def_workspace(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use UI Tags", "Filter the UI by tags"); RNA_def_property_update(prop, 0, "rna_window_update_all"); + prop = rna_def_asset_library_reference_common( + srna, "rna_WorkSpace_active_asset_library_get", "rna_WorkSpace_active_asset_library_set"); + RNA_def_property_ui_text(prop, + "Asset Library", + "Active asset library to show in the UI, not used by the Asset Browser " + "(which has its own active asset library)"); + RNA_def_property_update(prop, NC_ASSET | ND_ASSET_LIST_READING, NULL); + RNA_api_workspace(srna); } diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner.py b/source/blender/makesrna/rna_cleanup/rna_cleaner.py index 61622f281a6..f5e5e32ee76 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner.py @@ -229,7 +229,7 @@ def sort(props_list, sort_priority): def file_basename(input_filename): - # if needed will use os.path + # If needed will use `os.path`. if input_filename.endswith(".txt"): if input_filename.endswith("_work.txt"): base_filename = input_filename.replace("_work.txt", "") diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 649d36e3d57..828b8b79664 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -37,6 +37,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_context.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" @@ -122,7 +123,8 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte /* If neither vertex groups nor envelopes are used, the modifier has no bone dependencies. */ if ((amd->deformflag & ARM_DEF_VGROUP) != 0) { /* Enumerate groups that match existing bones. */ - LISTBASE_FOREACH (bDeformGroup *, dg, &ctx->object->defbase) { + const ListBase *defbase = BKE_object_defgroup_list(ctx->object); + LISTBASE_FOREACH (bDeformGroup *, dg, defbase) { if (BKE_pose_channel_find_name(amd->object->pose, dg->name) != NULL) { /* Can't check BONE_NO_DEFORM because it can be animated. */ DEG_add_bone_relation( diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index c5e3833aa4a..722614c4831 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -427,7 +427,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } } - /* Build up offset array, cumulating all settings options */ + /* Build up offset array, accumulating all settings options. */ unit_m4(offset); src_mvert = mesh->mvert; diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index 4b9b24e4e47..bdb791dc8e7 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -109,7 +109,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u { BooleanModifierData *bmd = (BooleanModifierData *)md; - walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_USER); walk(userData, ob, (ID **)&bmd->object, IDWALK_CB_NOP); } diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index c38e5126f6b..52f21e3d3d0 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -101,7 +101,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct range_vn_i(faceMap, numPoly_src, 0); struct Scene *scene = DEG_get_input_scene(ctx->depsgraph); - frac = (BKE_scene_frame_get(scene) - bmd->start) / bmd->length; + frac = (BKE_scene_ctime_get(scene) - bmd->start) / bmd->length; CLAMP(frac, 0.0f, 1.0f); if (bmd->flag & MOD_BUILD_FLAG_REVERSE) { frac = 1.0f - frac; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 40d027f3044..4487adcfdda 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -206,6 +206,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tclmd->point_cache->step = clmd->point_cache->step; tclmd->point_cache->startframe = clmd->point_cache->startframe; tclmd->point_cache->endframe = clmd->point_cache->endframe; + tclmd->point_cache->flag |= (clmd->point_cache->flag & PTCACHE_FLAGS_COPY); } } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index fef235b456b..9e8f5bee396 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -267,7 +267,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, { const float eps = FLT_EPSILON * 10.0f; const uint numEdges = (uint)mesh->totedge; - /* note: the way this smoothing method works, its approx half as strong as the simple-smooth, + /* NOTE: the way this smoothing method works, its approx half as strong as the simple-smooth, * and 2.0 rarely spikes, double the value for consistent behavior. */ const float lambda = csmd->lambda * 2.0f; const MEdge *edges = mesh->medge; diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 20dbb299767..aae6d257766 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -167,7 +167,7 @@ static void deformVertsEM(ModifierData *md, int defgrp_index = -1; if (ctx->object->type == OB_MESH && cmd->name[0] != '\0') { - defgrp_index = BKE_object_defgroup_name_index(ctx->object, cmd->name); + defgrp_index = BKE_id_defgroup_name_index(&mesh->id, cmd->name); if (defgrp_index != -1) { use_dverts = true; } diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index dbdc76f0edc..e2b2cc58d48 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -203,7 +203,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BKE_reports_init(&reports, RPT_STORE); - /* Note: no islands precision for now here. */ + /* NOTE: no islands precision for now here. */ if (BKE_object_data_transfer_ex(ctx->depsgraph, scene, ob_source, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 4e53243d820..bf197dca7e5 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -756,9 +756,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) /* override original facepa (original pointer is saved in caller function) */ - /* BMESH_TODO, (totfsplit * 2) over allocation is used since the quads are + /* TODO(campbell): `(totfsplit * 2)` over allocation is used since the quads are * later interpreted as tri's, for this to work right I think we probably - * have to stop using tessface - campbell */ + * have to stop using tessface. */ facepa = MEM_calloc_arrayN((totface + (totfsplit * 2)), sizeof(int), "explode_facepa"); // memcpy(facepa, emd->facepa, totface*sizeof(int)); @@ -919,7 +919,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, EdgeHashIterator *ehi; float *vertco = NULL, imat[4][4]; float rot[4]; - float cfra; + float ctime; /* float timestep; */ const int *facepa = emd->facepa; int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0; @@ -940,7 +940,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* timestep = psys_get_timestep(&sim); */ - cfra = BKE_scene_frame_get(scene); + ctime = BKE_scene_ctime_get(scene); /* hash table for vertice <-> particle relations */ vertpahash = BLI_edgehash_new(__func__); @@ -962,7 +962,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* do mindex + totvert to ensure the vertex index to be the first * with BLI_edgehashIterator_getKey */ - if (pa == NULL || cfra < pa->time) { + if (pa == NULL || ctime < pa->time) { mindex = totvert + totpart; } else { @@ -1022,7 +1022,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, psys_get_birth_coords(&sim, pa, &birth, 0, 0); - state.time = cfra; + state.time = ctime; psys_get_particle_state(&sim, ed_v2, &state, 1); vertco = explode->mvert[v].co; @@ -1076,7 +1076,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, orig_v4 = source.v4; /* Same as above in the first loop over mesh's faces. */ - if (pa == NULL || cfra < pa->time) { + if (pa == NULL || ctime < pa->time) { mindex = totvert + totpart; } else { @@ -1096,7 +1096,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* override uv channel for particle age */ if (mtface) { - float age = (pa != NULL) ? (cfra - pa->time) / pa->lifetime : 0.0f; + float age = (pa != NULL) ? (ctime - pa->time) / pa->lifetime : 0.0f; /* Clamp to this range to avoid flipping to the other side of the coordinates. */ CLAMP(age, 0.001f, 0.999f); diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index ff581e92cdd..18ce37c5d85 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -94,7 +94,7 @@ static void requiredDataMask(Object *UNUSED(ob), r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; } if (hmd->indexar != NULL) { - /* TODO check which origindex are actually needed? */ + /* TODO: check which origindex are actually needed? */ r_cddata_masks->vmask |= CD_MASK_ORIGINDEX; r_cddata_masks->emask |= CD_MASK_ORIGINDEX; r_cddata_masks->pmask |= CD_MASK_ORIGINDEX; diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index a77f6cfe8ba..9aa8e3dd7c8 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -119,7 +119,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte /* A vertex will be in the mask if a selected bone influences it more than a certain threshold. */ static void compute_vertex_mask__armature_mode(MDeformVert *dvert, - Object *ob, + Mesh *mesh, Object *armature_ob, float threshold, MutableSpan<bool> r_vertex_mask) @@ -127,7 +127,7 @@ static void compute_vertex_mask__armature_mode(MDeformVert *dvert, /* Element i is true if there is a selected bone that uses vertex group i. */ Vector<bool> selected_bone_uses_group; - for (bDeformGroup *def : ListBaseWrapper<bDeformGroup>(ob->defbase)) { + LISTBASE_FOREACH (bDeformGroup *, def, &mesh->vertex_group_names) { bPoseChannel *pchan = BKE_pose_channel_find_name(armature_ob->pose, def->name); bool bone_for_group_exists = pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED); selected_bone_uses_group.append(bone_for_group_exists); @@ -325,10 +325,9 @@ void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, * 2. Find edges and polygons only using those vertices. * 3. Create a new mesh that only uses the found vertices, edges and polygons. */ -static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md); - Object *ob = ctx->object; const bool invert_mask = mmd->flag & MOD_MASK_INV; /* Return empty or input mesh when there are no vertex groups. */ @@ -339,7 +338,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Quick test to see if we can return early. */ if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (mesh->totvert == 0) || - BLI_listbase_is_empty(&ob->defbase)) { + BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } @@ -348,15 +347,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Object *armature_ob = mmd->ob_arm; /* Return input mesh if there is no armature with bones. */ - if (ELEM(NULL, armature_ob, armature_ob->pose, ob->defbase.first)) { + if (ELEM(NULL, armature_ob, armature_ob->pose)) { return mesh; } vertex_mask = Array<bool>(mesh->totvert); - compute_vertex_mask__armature_mode(dvert, ob, armature_ob, mmd->threshold, vertex_mask); + compute_vertex_mask__armature_mode(dvert, mesh, armature_ob, mmd->threshold, vertex_mask); } else { - int defgrp_index = BKE_object_defgroup_name_index(ob, mmd->vgroup); + int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, mmd->vgroup); /* Return input mesh if the vertex group does not exist. */ if (defgrp_index == -1) { diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 6ec3277ee7a..e0507320628 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -104,20 +104,20 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* -------------------------------------------------------------------- */ /* Interpret Time (the reading functions also do some of this ) */ if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) { - const float cfra = BKE_scene_frame_get(scene); + const float ctime = BKE_scene_ctime_get(scene); switch (mcmd->time_mode) { case MOD_MESHCACHE_TIME_FRAME: { - time = cfra; + time = ctime; break; } case MOD_MESHCACHE_TIME_SECONDS: { - time = cfra / fps; + time = ctime / fps; break; } case MOD_MESHCACHE_TIME_FACTOR: default: { - time = cfra / fps; + time = ctime / fps; break; } } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index f7f7c7b0276..87fce26c45e 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -48,6 +48,7 @@ #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" +#include "BKE_attribute_math.hh" #include "BKE_customdata.h" #include "BKE_geometry_set_instances.hh" #include "BKE_global.h" @@ -56,7 +57,6 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_modifier.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "BKE_pointcloud.h" #include "BKE_screen.h" @@ -83,8 +83,10 @@ #include "NOD_derived_node_tree.hh" #include "NOD_geometry.h" +#include "NOD_geometry_nodes_eval_log.hh" #include "NOD_node_tree_multi_function.hh" +using blender::destruct_ptr; using blender::float3; using blender::FunctionRef; using blender::IndexRange; @@ -97,6 +99,7 @@ using blender::Vector; using blender::fn::GMutablePointer; using blender::fn::GPointer; using blender::nodes::GeoNodeExecParams; +using blender::threading::EnumerableThreadSpecific; using namespace blender::fn::multi_function_types; using namespace blender::nodes::derived_node_tree_types; @@ -734,19 +737,6 @@ static void initialize_group_input(NodesModifierData &nmd, property_type->init_cpp_value(*property, r_value); } -static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> trees, - const Object &object, - const ModifierData &modifier) -{ - const NodeTreeEvaluationContext context = {object, modifier}; - - for (const blender::nodes::NodeTreeRef *tree : trees) { - bNodeTree *btree_cow = tree->btree(); - bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow); - BKE_nodetree_ui_storage_free_for_context(*btree_original, context); - } -} - static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) { wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; @@ -766,24 +756,6 @@ static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) return spreadsheets; } -using PreviewSocketMap = blender::MultiValueMap<DSocket, uint64_t>; - -static DSocket try_find_preview_socket_in_node(const DNode node) -{ - for (const SocketRef *socket : node->outputs()) { - if (socket->bsocket()->type == SOCK_GEOMETRY) { - return {node.context(), socket}; - } - } - for (const SocketRef *socket : node->inputs()) { - if (socket->bsocket()->type == SOCK_GEOMETRY && - (socket->bsocket()->flag & SOCK_MULTI_INPUT) == 0) { - return {node.context(), socket}; - } - } - return {}; -} - static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadsheet, NodesModifierData *nmd, const ModifierEvalContext *ctx, @@ -837,9 +809,10 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre } const NodeTreeRef &tree_ref = context->tree(); - for (const NodeRef *node_ref : tree_ref.nodes()) { + for (const NodeRef *node_ref : tree_ref.nodes_by_type("GeometryNodeViewer")) { if (node_ref->name() == last_context->node_name) { - return try_find_preview_socket_in_node({context, node_ref}); + const DNode viewer_node{context, node_ref}; + return viewer_node.input(0); } } return {}; @@ -848,7 +821,7 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre static void find_sockets_to_preview(NodesModifierData *nmd, const ModifierEvalContext *ctx, const DerivedNodeTree &tree, - PreviewSocketMap &r_sockets_to_preview) + Set<DSocket> &r_sockets_to_preview) { Main *bmain = DEG_get_bmain(ctx->depsgraph); @@ -858,51 +831,16 @@ static void find_sockets_to_preview(NodesModifierData *nmd, for (SpaceSpreadsheet *sspreadsheet : spreadsheets) { const DSocket socket = try_get_socket_to_preview_for_spreadsheet(sspreadsheet, nmd, ctx, tree); if (socket) { - const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet); - r_sockets_to_preview.add_non_duplicates(socket, key); + r_sockets_to_preview.add(socket); } } } -static void log_preview_socket_value(const Span<GPointer> values, - Object *object, - Span<uint64_t> keys) +static void clear_runtime_data(NodesModifierData *nmd) { - GeometrySet geometry_set = *(const GeometrySet *)values[0].get(); - geometry_set.ensure_owns_direct_data(); - for (uint64_t key : keys) { - BKE_object_preview_geometry_set_add(object, key, new GeometrySet(geometry_set)); - } -} - -static void log_ui_hints(const DSocket socket, - const Span<GPointer> values, - Object *self_object, - NodesModifierData *nmd) -{ - const DNode node = socket.node(); - if (node->is_reroute_node() || socket->typeinfo()->type != SOCK_GEOMETRY) { - return; - } - bNodeTree *btree_cow = node->btree(); - bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow); - const NodeTreeEvaluationContext context{*self_object, nmd->modifier}; - for (const GPointer &data : values) { - if (data.type() == &CPPType::get<GeometrySet>()) { - const GeometrySet &geometry_set = *(const GeometrySet *)data.get(); - blender::bke::geometry_set_instances_attribute_foreach( - geometry_set, - [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) { - BKE_nodetree_attribute_hint_add(*btree_original, - context, - *node->bnode(), - attribute_name, - meta_data.domain, - meta_data.data_type); - return true; - }, - 8); - } + if (nmd->runtime_eval_log != nullptr) { + delete (geo_log::ModifierLog *)nmd->runtime_eval_log; + nmd->runtime_eval_log = nullptr; } } @@ -958,30 +896,32 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree, Vector<DInputSocket> group_outputs; group_outputs.append({root_context, &socket_to_compute}); - PreviewSocketMap preview_sockets; - find_sockets_to_preview(nmd, ctx, tree, preview_sockets); - - auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) { - if (!logging_enabled(ctx)) { - return; - } - Span<uint64_t> keys = preview_sockets.lookup(socket); - if (!keys.is_empty()) { - log_preview_socket_value(values, ctx->object, keys); - } - log_ui_hints(socket, values, ctx->object, nmd); - }; + std::optional<geo_log::GeoLogger> geo_logger; blender::modifiers::geometry_nodes::GeometryNodesEvaluationParams eval_params; + + if (logging_enabled(ctx)) { + Set<DSocket> preview_sockets; + find_sockets_to_preview(nmd, ctx, tree, preview_sockets); + eval_params.force_compute_sockets.extend(preview_sockets.begin(), preview_sockets.end()); + geo_logger.emplace(std::move(preview_sockets)); + } + eval_params.input_values = group_inputs; eval_params.output_sockets = group_outputs; eval_params.mf_by_node = &mf_by_node; eval_params.modifier_ = nmd; eval_params.depsgraph = ctx->depsgraph; eval_params.self_object = ctx->object; - eval_params.log_socket_value_fn = log_socket_value; + eval_params.geo_logger = geo_logger.has_value() ? &*geo_logger : nullptr; blender::modifiers::geometry_nodes::evaluate_geometry_nodes(eval_params); + if (geo_logger.has_value()) { + NodesModifierData *nmd_orig = (NodesModifierData *)BKE_modifier_get_original(&nmd->modifier); + clear_runtime_data(nmd_orig); + nmd_orig->runtime_eval_log = new geo_log::ModifierLog(*geo_logger); + } + BLI_assert(eval_params.r_output_values.size() == 1); GMutablePointer result = eval_params.r_output_values[0]; return result.relocate_out<GeometrySet>(); @@ -1071,10 +1011,6 @@ static void modifyGeometry(ModifierData *md, return; } - if (logging_enabled(ctx)) { - reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md); - } - geometry_set = compute_geometry( tree, input_nodes, *group_outputs[0], std::move(geometry_set), nmd, ctx); } @@ -1082,13 +1018,14 @@ static void modifyGeometry(ModifierData *md, static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { GeometrySet geometry_set = GeometrySet::create_with_mesh(mesh, GeometryOwnershipType::Editable); - geometry_set.get_component_for_write<MeshComponent>().copy_vertex_group_names_from_object( - *ctx->object); + modifyGeometry(md, ctx, geometry_set); - /* This function is only called when applying modifiers. In this case it makes sense to realize - * instances, otherwise in some cases there might be no results when applying the modifier. */ - geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set); + if (ctx->flag & MOD_APPLY_TO_BASE_MESH) { + /* In this case it makes sense to realize instances, otherwise in some cases there might be no + * results when applying the modifier. */ + geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set); + } Mesh *new_mesh = geometry_set.get_component_for_write<MeshComponent>().release(); if (new_mesh == nullptr) { @@ -1219,6 +1156,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md); BLO_read_data_address(reader, &nmd->settings.properties); IDP_BlendDataRead(reader, &nmd->settings.properties); + nmd->runtime_eval_log = nullptr; } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -1228,6 +1166,8 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla BKE_modifier_copydata_generic(md, target, flag); + tnmd->runtime_eval_log = nullptr; + if (nmd->settings.properties != nullptr) { tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag); } @@ -1240,6 +1180,8 @@ static void freeData(ModifierData *md) IDP_FreeProperty_ex(nmd->settings.properties, false); nmd->settings.properties = nullptr; } + + clear_runtime_data(nmd); } static void requiredDataMask(Object *UNUSED(ob), diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index c2f2f358b9e..cf18f60ec22 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -411,6 +411,9 @@ class GeometryNodesEvaluator { for (const DInputSocket &socket : params_.output_sockets) { nodes_to_check.push(socket.node()); } + for (const DSocket &socket : params_.force_compute_sockets) { + nodes_to_check.push(socket.node()); + } /* Use the local allocator because the states do not need to outlive the evaluator. */ LinearAllocator<> &allocator = local_allocators_.local(); while (!nodes_to_check.is_empty()) { @@ -544,7 +547,8 @@ class GeometryNodesEvaluator { }, {}); if (output_state.potential_users == 0) { - /* If it does not have any potential users, it is unused. */ + /* If it does not have any potential users, it is unused. It might become required again in + * `schedule_initial_nodes`. */ output_state.output_usage = ValueUsage::Unused; } } @@ -622,11 +626,11 @@ class GeometryNodesEvaluator { for (auto &&item : params_.input_values.items()) { const DOutputSocket socket = item.key; GMutablePointer value = item.value; - this->log_socket_value(socket, value); const DNode node = socket.node(); if (!node_states_.contains_as(node)) { /* The socket is not connected to any output. */ + this->log_socket_value({socket}, value); value.destruct(); continue; } @@ -644,6 +648,20 @@ class GeometryNodesEvaluator { this->set_input_required(locked_node, socket); }); } + for (const DSocket socket : params_.force_compute_sockets) { + const DNode node = socket.node(); + NodeState &node_state = this->get_node_state(node); + this->with_locked_node(node, node_state, [&](LockedNode &locked_node) { + if (socket->is_input()) { + this->set_input_required(locked_node, DInputSocket(socket)); + } + else { + OutputState &output_state = node_state.outputs[socket->index()]; + output_state.output_usage = ValueUsage::Required; + this->schedule_node(locked_node); + } + }); + } } void schedule_node(LockedNode &locked_node) @@ -830,7 +848,6 @@ class GeometryNodesEvaluator { /* Checks if all the linked sockets have been provided already. */ if (multi_value.items.size() == multi_value.expected_size) { input_state.was_ready_for_execution = true; - this->log_socket_value(socket, input_state, multi_value.items); } else if (is_required) { /* The input is required but is not fully provided yet. Therefore the node cannot be @@ -842,7 +859,6 @@ class GeometryNodesEvaluator { SingleInputValue &single_value = *input_state.value.single; if (single_value.value != nullptr) { input_state.was_ready_for_execution = true; - this->log_socket_value(socket, GPointer{input_state.type, single_value.value}); } else if (is_required) { /* The input is required but has not been provided yet. Therefore the node cannot be @@ -1192,10 +1208,14 @@ class GeometryNodesEvaluator { this->with_locked_node(node, node_state, [&](LockedNode &locked_node) { output_state.potential_users -= 1; if (output_state.potential_users == 0) { - /* The output socket has no users anymore. */ - output_state.output_usage = ValueUsage::Unused; - /* Schedule the origin node in case it wants to set its inputs as unused as well. */ - this->schedule_node(locked_node); + /* The socket might be required even though the output is not used by other sockets. That + * can happen when the socket is forced to be computed. */ + if (output_state.output_usage != ValueUsage::Required) { + /* The output socket has no users anymore. */ + output_state.output_usage = ValueUsage::Unused; + /* Schedule the origin node in case it wants to set its inputs as unused as well. */ + this->schedule_node(locked_node); + } } }); } @@ -1216,16 +1236,17 @@ class GeometryNodesEvaluator { { BLI_assert(value_to_forward.get() != nullptr); + Vector<DSocket> sockets_to_log_to; + sockets_to_log_to.append(from_socket); + Vector<DInputSocket> to_sockets; auto handle_target_socket_fn = [&, this](const DInputSocket to_socket) { if (this->should_forward_to_socket(to_socket)) { to_sockets.append(to_socket); } }; - auto handle_skipped_socket_fn = [&, this](const DSocket socket) { - /* Log socket value on intermediate sockets to support e.g. attribute search or spreadsheet - * breadcrumbs on group nodes. */ - this->log_socket_value(socket, value_to_forward); + auto handle_skipped_socket_fn = [&](const DSocket socket) { + sockets_to_log_to.append(socket); }; from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn); @@ -1238,11 +1259,18 @@ class GeometryNodesEvaluator { if (from_type == to_type) { /* All target sockets that do not need a conversion will be handled afterwards. */ to_sockets_same_type.append(to_socket); + /* Multi input socket values are logged once all values are available. */ + if (!to_socket->is_multi_input_socket()) { + sockets_to_log_to.append(to_socket); + } continue; } this->forward_to_socket_with_different_type( allocator, value_to_forward, from_socket, to_socket, to_type); } + + this->log_socket_value(sockets_to_log_to, value_to_forward); + this->forward_to_sockets_with_same_type( allocator, to_sockets_same_type, value_to_forward, from_socket); } @@ -1273,6 +1301,7 @@ class GeometryNodesEvaluator { /* Allocate a buffer for the converted value. */ void *buffer = allocator.allocate(to_type.size(), to_type.alignment()); + GMutablePointer value{to_type, buffer}; if (conversions_.is_convertible(from_type, to_type)) { /* Do the conversion if possible. */ @@ -1282,7 +1311,11 @@ class GeometryNodesEvaluator { /* Cannot convert, use default value instead. */ to_type.copy_construct(to_type.default_value(), buffer); } - this->add_value_to_input_socket(to_socket, from_socket, {to_type, buffer}); + /* Multi input socket values are logged once all values are available. */ + if (!to_socket->is_multi_input_socket()) { + this->log_socket_value({to_socket}, value); + } + this->add_value_to_input_socket(to_socket, from_socket, value); } void forward_to_sockets_with_same_type(LinearAllocator<> &allocator, @@ -1330,6 +1363,10 @@ class GeometryNodesEvaluator { /* Add a new value to the multi-input. */ MultiInputValue &multi_value = *input_state.value.multi; multi_value.items.append({origin, value.get()}); + + if (multi_value.expected_size == multi_value.items.size()) { + this->log_socket_value({socket}, input_state, multi_value.items); + } } else { /* Assign the value to the input. */ @@ -1360,10 +1397,14 @@ class GeometryNodesEvaluator { if (input_socket->is_multi_input_socket()) { MultiInputValue &multi_value = *input_state.value.multi; multi_value.items.append({origin_socket, value.get()}); + if (multi_value.expected_size == multi_value.items.size()) { + this->log_socket_value({input_socket}, input_state, multi_value.items); + } } else { SingleInputValue &single_value = *input_state.value.single; single_value.value = value.get(); + this->log_socket_value({input_socket}, value); } } @@ -1416,29 +1457,27 @@ class GeometryNodesEvaluator { return *node_states_.lookup_key_as(node).state; } - void log_socket_value(const DSocket socket, Span<GPointer> values) + void log_socket_value(DSocket socket, InputState &input_state, Span<MultiInputValueItem> values) { - if (params_.log_socket_value_fn) { - params_.log_socket_value_fn(socket, values); + if (params_.geo_logger == nullptr) { + return; } - } - void log_socket_value(const DSocket socket, - InputState &input_state, - Span<MultiInputValueItem> values) - { Vector<GPointer, 16> value_pointers; value_pointers.reserve(values.size()); const CPPType &type = *input_state.type; for (const MultiInputValueItem &item : values) { value_pointers.append({type, item.value}); } - this->log_socket_value(socket, value_pointers); + params_.geo_logger->local().log_multi_value_socket(socket, value_pointers); } - void log_socket_value(const DSocket socket, GPointer value) + void log_socket_value(Span<DSocket> sockets, GPointer value) { - this->log_socket_value(socket, Span<GPointer>(&value, 1)); + if (params_.geo_logger == nullptr) { + return; + } + params_.geo_logger->local().log_value_for_sockets(sockets, value); } /* In most cases when `NodeState` is accessed, the node has to be locked first to avoid race @@ -1477,6 +1516,7 @@ NodeParamsProvider::NodeParamsProvider(GeometryNodesEvaluator &evaluator, this->self_object = evaluator.params_.self_object; this->modifier = &evaluator.params_.modifier_->modifier; this->depsgraph = evaluator.params_.depsgraph; + this->logger = evaluator.params_.geo_logger; } bool NodeParamsProvider::can_get_input(StringRef identifier) const @@ -1576,8 +1616,6 @@ void NodeParamsProvider::set_output(StringRef identifier, GMutablePointer value) const DOutputSocket socket = this->dnode.output_by_identifier(identifier); BLI_assert(socket); - evaluator_.log_socket_value(socket, value); - OutputState &output_state = node_state_.outputs[socket->index()]; BLI_assert(!output_state.has_been_computed); evaluator_.forward_output(socket, value); diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh index 84249e4244e..f4ee6242dcb 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh @@ -19,30 +19,37 @@ #include "BLI_map.hh" #include "NOD_derived_node_tree.hh" +#include "NOD_geometry_nodes_eval_log.hh" #include "NOD_node_tree_multi_function.hh" #include "FN_generic_pointer.hh" #include "DNA_modifier_types.h" +namespace geo_log = blender::nodes::geometry_nodes_eval_log; + namespace blender::modifiers::geometry_nodes { using namespace nodes::derived_node_tree_types; using fn::GMutablePointer; using fn::GPointer; -using LogSocketValueFn = std::function<void(DSocket, Span<GPointer>)>; - struct GeometryNodesEvaluationParams { blender::LinearAllocator<> allocator; Map<DOutputSocket, GMutablePointer> input_values; Vector<DInputSocket> output_sockets; + /* These sockets will be computed but are not part of the output. Their value can be retrieved in + * `log_socket_value_fn`. These sockets are not part of `output_sockets` because then the + * evaluator would have to keep the socket values in memory until the end, which might not be + * necessary in all cases. Sometimes `log_socket_value_fn` might just want to look at the value + * and then it can be freed. */ + Vector<DSocket> force_compute_sockets; nodes::MultiFunctionByNode *mf_by_node; const NodesModifierData *modifier_; Depsgraph *depsgraph; Object *self_object; - LogSocketValueFn log_socket_value_fn; + geo_log::GeoLogger *geo_logger; Vector<GMutablePointer> r_output_values; }; diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 4bfd6aba4b2..54bb68dc21a 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -335,7 +335,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, if (do_polynors_fix && polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) { - /* XXX TODO is this still needed? */ + /* XXX TODO: is this still needed? */ // mesh->dirty |= DM_DIRTY_TESS_CDLAYERS; /* We need to recompute vertex normals! */ BKE_mesh_calc_normals(mesh); diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 3de6bb62c8a..8f3206da5be 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -455,7 +455,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes /* displace the geometry */ - /* Note: tried to parallelized that one and previous foam loop, + /* NOTE: tried to parallelized that one and previous foam loop, * but gives 20% slower results... odd. */ { const int num_verts = result->totvert; diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 62ac9d4452d..49b5dabe72d 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -182,7 +182,7 @@ static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *ps totpart = psys->totpart + psys->totchild; - /* TODO make randomization optional? */ + /* TODO: make randomization optional? */ randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart; minp = (int)(totpart * pimd->particle_offset) % (totpart + 1); @@ -442,7 +442,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mul_qt_qtqt(frame, frame, rot); } - /* note: direction is same as normal vector currently, + /* NOTE: direction is same as normal vector currently, * but best to keep this separate so the frame can be * rotated later if necessary */ diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 38cce5e6a50..ef70f3fe6f4 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -120,7 +120,6 @@ static void deformVerts(ModifierData *md, Mesh *mesh_src = mesh; ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; ParticleSystem *psys = NULL; - /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */ if (ctx->object->particlesystem.first) { psys = psmd->psys; diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index b90bf91dcb8..0819b314e32 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -357,7 +357,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1); /* Will the screw be closed? - * Note! smaller than `FLT_EPSILON * 100` + * NOTE: smaller than `FLT_EPSILON * 100` * gives problems with float precision so its never closed. */ if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f) && step_tot > 3) { diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 58d70ef3a4a..543cee18868 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -296,7 +296,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe) bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "convex_hull input=%hv", BM_ELEM_TAG); BMO_op_exec(bm, &op); - if (BMO_error_occurred(bm)) { + if (BMO_error_occurred_at_level(bm, BMO_ERROR_CANCEL)) { BMO_op_finish(bm, &op); return false; } @@ -1202,7 +1202,7 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, BMVert **orig_ slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); - /* Note: could probably calculate merges in one go to be + /* NOTE: could probably calculate merges in one go to be * faster */ v_safe = shortest_edge->v1; diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 95fb87bb54c..e97190b1878 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -242,9 +242,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; - const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object, - smd->shell_defgrp_name); - const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name); + const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name); + const int rim_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->rim_defgrp_name); /* array size is doubled in case of using a shell */ const uint stride = do_shell ? 2 : 1; @@ -505,7 +504,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } } - /* note, copied vertex layers don't have flipped normals yet. do this after applying offset */ + /* NOTE: copied vertex layers don't have flipped normals yet. do this after applying offset. */ if ((smd->flag & MOD_SOLIDIFY_EVEN) == 0) { /* no even thickness, very simple */ float scalar_short; @@ -1028,14 +1027,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (do_rim) { uint i; - /* bugger, need to re-calculate the normals for the new edge faces. + /* NOTE(campbell): Unfortunately re-calculate the normals for the new edge faces is necessary. * This could be done in many ways, but probably the quickest way * is to calculate the average normals for side faces only. * Then blend them with the normals of the edge verts. * - * at the moment its easiest to allocate an entire array for every vertex, - * even though we only need edge verts - campbell - */ + * At the moment its easiest to allocate an entire array for every vertex, + * even though we only need edge verts. */ #define SOLIDIFY_SIDE_NORMALS @@ -1200,7 +1198,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex short *nor_short; int k; - /* note, only the first vertex (lower half of the index) is calculated */ + /* NOTE: only the first vertex (lower half of the index) is calculated. */ BLI_assert(ed->v1 < numVerts); normalize_v3_v3(nor_cpy, edge_vert_nos[ed_orig->v1]); diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 0f8503eddde..b872f04b60f 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -181,9 +181,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; - const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object, - smd->shell_defgrp_name); - const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name); + const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name); + const int rim_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->rim_defgrp_name); MOD_get_vgroup(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index); @@ -913,7 +912,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint unassigned_edges_len = 0; for (uint j = 0; j < tot_adj_edges; j++) { NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]]; - /* TODO check where the null pointer come from, + /* TODO: check where the null pointer come from, * because there should not be any... */ if (new_edges) { /* count the number of new edges around the original vert */ @@ -1107,7 +1106,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(unassigned_edges); - /* TODO reshape the edge_groups array to its actual size + /* TODO: reshape the edge_groups array to its actual size * after writing is finished to save on memory. */ } @@ -1374,7 +1373,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(vert_adj_edges); } - /* TODO create_regions if fix_intersections. */ + /* TODO: create_regions if fix_intersections. */ /* General use pointer for #EdgeGroup iteration. */ EdgeGroup **gs_ptr; @@ -1854,7 +1853,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(null_faces); } - /* TODO create vertdata for intersection fixes (intersection fixing per topology region). */ + /* TODO: create vertdata for intersection fixes (intersection fixing per topology region). */ /* Correction for adjacent one sided groups around a vert to * prevent edge duplicates and null polys. */ @@ -2018,7 +2017,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, * - new_edge value should have no duplicates * - every old_edge value should appear twice * - every group should have at least two members (edges) - * Note: that there can be vertices that only have one group. They are called singularities. + * NOTE: that there can be vertices that only have one group. They are called singularities. * These vertices will only have one side (there is no way of telling apart front * from back like on a mobius strip) */ diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index dd011a293ee..ec6de8f8387 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -94,6 +94,11 @@ typedef struct SDefBindCalcData { float imat[4][4]; const float falloff; int success; + /** Vertex group lookup data. */ + const MDeformVert *const dvert; + int const defgrp_index; + bool const invert_vgroup; + bool const sparse_bind; } SDefBindCalcData; /** @@ -218,7 +223,7 @@ static void freeData(ModifierData *md) SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { if (smd->verts[i].binds) { for (int j = 0; j < smd->verts[i].numbinds; j++) { MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds); @@ -243,7 +248,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla if (smd->verts) { tsmd->verts = MEM_dupallocN(smd->verts); - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { if (smd->verts[i].binds) { tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds); @@ -963,12 +968,32 @@ static void bindVert(void *__restrict userdata, SDefBindPoly *bpoly; SDefBind *sdbind; + sdvert->vertex_idx = index; + if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) { sdvert->binds = NULL; sdvert->numbinds = 0; return; } + if (data->sparse_bind) { + float weight = 0.0f; + + if (data->dvert && data->defgrp_index != -1) { + weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index); + } + + if (data->invert_vgroup) { + weight = 1.0f - weight; + } + + if (weight <= 0) { + sdvert->binds = NULL; + sdvert->numbinds = 0; + return; + } + } + copy_v3_v3(point_co, data->vertexCos[index]); bwdata = computeBindWeights(data, point_co); @@ -1135,6 +1160,21 @@ static void bindVert(void *__restrict userdata, freeBindData(bwdata); } +/* Remove vertices without bind data from the bind array. */ +static void compactSparseBinds(SurfaceDeformModifierData *smd) +{ + smd->num_bind_verts = 0; + + for (uint i = 0; i < smd->num_mesh_verts; i++) { + if (smd->verts[i].numbinds > 0) { + smd->verts[smd->num_bind_verts++] = smd->verts[i]; + } + } + + smd->verts = MEM_reallocN_id( + smd->verts, sizeof(*smd->verts) * smd->num_bind_verts, "SDefBindVerts (sparse)"); +} + static bool surfacedeformBind(Object *ob, SurfaceDeformModifierData *smd_orig, SurfaceDeformModifierData *smd_eval, @@ -1142,7 +1182,8 @@ static bool surfacedeformBind(Object *ob, uint numverts, uint tnumpoly, uint tnumverts, - Mesh *target) + Mesh *target, + Mesh *mesh) { BVHTreeFromMesh treeData = {NULL}; const MVert *mvert = target->mvert; @@ -1205,9 +1246,15 @@ static bool surfacedeformBind(Object *ob, return false; } - smd_orig->numverts = numverts; + smd_orig->num_mesh_verts = numverts; smd_orig->numpoly = tnumpoly; + int defgrp_index; + MDeformVert *dvert; + MOD_get_vgroup(ob, mesh, smd_orig->defgrp_name, &dvert, &defgrp_index); + const bool invert_vgroup = (smd_orig->flags & MOD_SDEF_INVERT_VGROUP) != 0; + const bool sparse_bind = (smd_orig->flags & MOD_SDEF_SPARSE_BIND) != 0; + SDefBindCalcData data = { .treeData = &treeData, .vert_edges = vert_edges, @@ -1221,6 +1268,10 @@ static bool surfacedeformBind(Object *ob, .vertexCos = vertexCos, .falloff = smd_orig->falloff, .success = MOD_SDEF_BIND_RESULT_SUCCESS, + .dvert = dvert, + .defgrp_index = defgrp_index, + .invert_vgroup = invert_vgroup, + .sparse_bind = sparse_bind, }; if (data.targetCos == NULL) { @@ -1242,6 +1293,13 @@ static bool surfacedeformBind(Object *ob, MEM_freeN(data.targetCos); + if (sparse_bind) { + compactSparseBinds(smd_orig); + } + else { + smd_orig->num_bind_verts = numverts; + } + if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); @@ -1267,6 +1325,11 @@ static bool surfacedeformBind(Object *ob, BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } + else if (smd_orig->num_bind_verts == 0 || !smd_orig->verts) { + data.success = MOD_SDEF_BIND_RESULT_GENERIC_ERR; + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "No vertices were bound"); + freeData((ModifierData *)smd_orig); + } freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); @@ -1281,14 +1344,15 @@ static void deformVert(void *__restrict userdata, const SDefDeformData *const data = (SDefDeformData *)userdata; const SDefBind *sdbind = data->bind_verts[index].binds; const int num_binds = data->bind_verts[index].numbinds; - float *const vertexCos = data->vertexCos[index]; + const unsigned int vertex_idx = data->bind_verts[index].vertex_idx; + float *const vertexCos = data->vertexCos[vertex_idx]; float norm[3], temp[3], offset[3]; /* Retrieve the value of the weight vertex group if specified. */ float weight = 1.0f; if (data->dvert && data->defgrp_index != -1) { - weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index); + weight = BKE_defvert_find_weight(&data->dvert[vertex_idx], data->defgrp_index); if (data->invert_vgroup) { weight = 1.0f - weight; @@ -1423,7 +1487,8 @@ static void surfacedeformModifier_do(ModifierData *md, /* Avoid converting edit-mesh data, binding is an exception. */ BKE_mesh_wrapper_ensure_mdata(target); - if (!surfacedeformBind(ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { + if (!surfacedeformBind( + ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target, mesh)) { smd->flags &= ~MOD_SDEF_BIND; } /* Early abort, this is binding 'call', no need to perform whole evaluation. */ @@ -1431,8 +1496,9 @@ static void surfacedeformModifier_do(ModifierData *md, } /* Poly count checks */ - if (smd->numverts != numverts) { - BKE_modifier_set_error(ob, md, "Vertices changed from %u to %u", smd->numverts, numverts); + if (smd->num_mesh_verts != numverts) { + BKE_modifier_set_error( + ob, md, "Vertices changed from %u to %u", smd->num_mesh_verts, numverts); return; } if (smd->numpoly != tnumpoly) { @@ -1468,8 +1534,8 @@ static void surfacedeformModifier_do(ModifierData *md, TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (numverts > 10000); - BLI_task_parallel_range(0, numverts, &data, deformVert, &settings); + settings.use_threading = (smd->num_bind_verts > 10000); + BLI_task_parallel_range(0, smd->num_bind_verts, &data, deformVert, &settings); MEM_freeN(data.targetCos); } @@ -1554,6 +1620,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); + col = uiLayoutColumn(layout, false); + uiLayoutSetEnabled(col, !is_bound); + uiLayoutSetActive(col, !is_bound && RNA_string_length(ptr, "vertex_group") != 0); + uiItemR(col, ptr, "use_sparse_bind", 0, NULL, ICON_NONE); + uiItemS(layout); col = uiLayoutColumn(layout, false); @@ -1576,10 +1647,10 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) { const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md; - BLO_write_struct_array(writer, SDefVert, smd->numverts, smd->verts); + BLO_write_struct_array(writer, SDefVert, smd->num_bind_verts, smd->verts); if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { BLO_write_struct_array(writer, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds); if (smd->verts[i].binds) { @@ -1607,7 +1678,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) BLO_read_data_address(reader, &smd->verts); if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { BLO_read_data_address(reader, &smd->verts[i].binds); if (smd->verts[i].binds) { diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 55409cba114..5b97d0eb259 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -71,7 +71,7 @@ void MOD_init_texture(MappingInfoModifierData *dmd, const ModifierEvalContext *c } } -/* TODO to be renamed to get_texture_coords once we are done with moving modifiers to Mesh. */ +/* TODO: to be renamed to get_texture_coords once we are done with moving modifiers to Mesh. */ /** \param cos: may be NULL, in which case we use directly mesh vertices' coordinates. */ void MOD_get_texture_coords(MappingInfoModifierData *dmd, const ModifierEvalContext *UNUSED(ctx), @@ -254,15 +254,22 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, void MOD_get_vgroup( Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index) { - *defgrp_index = BKE_object_defgroup_name_index(ob, name); - *dvert = NULL; - - if (*defgrp_index != -1) { - if (ob->type == OB_LATTICE) { + if (mesh) { + *defgrp_index = BKE_id_defgroup_name_index(&mesh->id, name); + if (*defgrp_index != -1) { + *dvert = mesh->dvert; + } + else { + *dvert = NULL; + } + } + else { + *defgrp_index = BKE_object_defgroup_name_index(ob, name); + if (*defgrp_index != -1 && ob->type == OB_LATTICE) { *dvert = BKE_lattice_deform_verts_get(ob); } - else if (mesh) { - *dvert = mesh->dvert; + else { + *dvert = NULL; } } } diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 5742144b6dd..3f161d339c2 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -233,7 +233,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * settings.use_threading = (numPolys > 1000); BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings); - /* XXX TODO is this still needed? */ + /* XXX TODO: is this still needed? */ // me_eval->dirty |= DM_DIRTY_TESS_CDLAYERS; mesh->runtime.is_original = false; diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 2f2da7d6554..bbdd7d0e647 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -378,7 +378,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, * But this is not exactly trivial change, better to keep this optimization for later... */ if (!has_vgroup) { - /* Note: in theory, we could avoid this extra allocation & copying... + /* NOTE: in theory, we could avoid this extra allocation & copying... * But think we can live with it for now, * and it makes code simpler & cleaner. */ float(*vert_normals)[3] = MEM_calloc_arrayN( diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index c5e2ecb9660..696c4c855c7 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -230,7 +230,7 @@ void weightvg_do_mask(const ModifierEvalContext *ctx, MEM_freeN(tex_co); } - else if ((ref_didx = BKE_object_defgroup_name_index(ob, defgrp_name)) != -1) { + else if ((ref_didx = BKE_id_defgroup_name_index(&mesh->id, defgrp_name)) != -1) { MDeformVert *dvert = NULL; /* Check whether we want to set vgroup weights from a constant weight factor or a vertex diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index b5f72c88800..093fa118ee0 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -194,12 +194,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) { + if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } /* Get vgroup idx from its name. */ - const int defgrp_index = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); if (defgrp_index == -1) { return mesh; } diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index a71a2f3b480..7aae089fa18 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -245,19 +245,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) { + if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } /* Get vgroup idx from its name. */ - const int defgrp_index = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name_a); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_a); if (defgrp_index == -1) { return mesh; } /* Get second vgroup idx from its name, if given. */ int defgrp_index_other = -1; if (wmd->defgrp_name_b[0] != '\0') { - defgrp_index_other = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name_b); + defgrp_index_other = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_b); if (defgrp_index_other == -1) { return mesh; } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index cd03175f16c..6e78774269a 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -174,7 +174,7 @@ static void get_vert2geom_distance(int numVerts, BVHTreeFromMesh treeData_f = {NULL}; if (dist_v) { - /* Create a bvh-tree of the given target's verts. */ + /* Create a BVH-tree of the given target's verts. */ BKE_bvhtree_from_mesh_get(&treeData_v, target, BVHTREE_FROM_VERTS, 2); if (treeData_v.tree == NULL) { OUT_OF_MEMORY(); @@ -182,7 +182,7 @@ static void get_vert2geom_distance(int numVerts, } } if (dist_e) { - /* Create a bvh-tree of the given target's edges. */ + /* Create a BVH-tree of the given target's edges. */ BKE_bvhtree_from_mesh_get(&treeData_e, target, BVHTREE_FROM_EDGES, 2); if (treeData_e.tree == NULL) { OUT_OF_MEMORY(); @@ -190,7 +190,7 @@ static void get_vert2geom_distance(int numVerts, } } if (dist_f) { - /* Create a bvh-tree of the given target's faces. */ + /* Create a BVH-tree of the given target's faces. */ BKE_bvhtree_from_mesh_get(&treeData_f, target, BVHTREE_FROM_LOOPTRI, 2); if (treeData_f.tree == NULL) { OUT_OF_MEMORY(); @@ -468,7 +468,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) { + if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } @@ -479,11 +479,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } /* Get vgroup idx from its name. */ - defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); + defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); if (defgrp_index == -1) { return mesh; } - const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT); /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ /* As this modifier never add vertices to vgroup, just return. */ diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index 1590f342666..fe2d699aea8 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -1573,11 +1573,12 @@ struct WeldVertexCluster { uint merged_verts; }; -static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *weldModifier_doWeld(WeldModifierData *wmd, + const ModifierEvalContext *UNUSED(ctx), + Mesh *mesh) { Mesh *result = mesh; - Object *ob = ctx->object; BLI_bitmap *v_mask = NULL; int v_mask_act = 0; @@ -1590,7 +1591,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex totvert = mesh->totvert; /* Vertex Group. */ - const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); if (defgrp_index != -1) { MDeformVert *dvert, *dv; dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT); diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 16bf1f7d763..e188a61e975 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -76,7 +76,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh * Mesh *result; BMesh *bm; - const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); bm = BKE_mesh_to_bmesh_ex(mesh, &(struct BMeshCreateParams){0}, diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index d27f45c4d98..929b1c3e6b2 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -134,6 +134,7 @@ set(SRC function/nodes/node_fn_boolean_math.cc function/nodes/node_fn_float_compare.cc + function/nodes/node_fn_float_to_int.cc function/nodes/node_fn_input_string.cc function/nodes/node_fn_input_vector.cc function/nodes/node_fn_random_float.cc @@ -165,17 +166,20 @@ set(SRC geometry/nodes/node_geo_collection_info.cc geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_convex_hull.cc - geometry/nodes/node_geo_curve_length.cc + geometry/nodes/node_geo_curve_endpoints.cc + geometry/nodes/node_geo_curve_length.cc geometry/nodes/node_geo_curve_primitive_bezier_segment.cc geometry/nodes/node_geo_curve_primitive_circle.cc + geometry/nodes/node_geo_curve_primitive_line.cc geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc + geometry/nodes/node_geo_curve_primitive_quadrilateral.cc geometry/nodes/node_geo_curve_primitive_spiral.cc geometry/nodes/node_geo_curve_primitive_star.cc - geometry/nodes/node_geo_curve_to_mesh.cc - geometry/nodes/node_geo_curve_to_points.cc geometry/nodes/node_geo_curve_resample.cc geometry/nodes/node_geo_curve_reverse.cc geometry/nodes/node_geo_curve_subdivide.cc + geometry/nodes/node_geo_curve_to_mesh.cc + geometry/nodes/node_geo_curve_to_points.cc geometry/nodes/node_geo_delete_geometry.cc geometry/nodes/node_geo_edge_split.cc geometry/nodes/node_geo_input_material.cc @@ -191,6 +195,7 @@ set(SRC geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc geometry/nodes/node_geo_mesh_primitive_line.cc geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc + geometry/nodes/node_geo_mesh_subdivide.cc geometry/nodes/node_geo_mesh_to_curve.cc geometry/nodes/node_geo_object_info.cc geometry/nodes/node_geo_point_distribute.cc @@ -203,11 +208,11 @@ set(SRC geometry/nodes/node_geo_raycast.cc geometry/nodes/node_geo_select_by_material.cc geometry/nodes/node_geo_separate_components.cc - geometry/nodes/node_geo_subdivide.cc geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_switch.cc geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc + geometry/nodes/node_geo_viewer.cc geometry/nodes/node_geo_volume_to_mesh.cc geometry/node_geometry_exec.cc geometry/node_geometry_tree.cc @@ -333,6 +338,7 @@ set(SRC texture/node_texture_util.c intern/derived_node_tree.cc + intern/geometry_nodes_eval_log.cc intern/math_functions.cc intern/attribute_ref.cc intern/node_common.c @@ -358,6 +364,7 @@ set(SRC NOD_function.h NOD_geometry.h NOD_geometry_exec.hh + NOD_geometry_nodes_eval_log.hh NOD_math_functions.hh NOD_node_tree_multi_function.hh NOD_node_tree_ref.hh @@ -418,6 +425,11 @@ if(WITH_TBB) ${TBB_INCLUDE_DIRS} ) add_definitions(-DWITH_TBB) + if(WIN32) + # TBB includes Windows.h which will define min/max macros + # that will collide with the stl versions. + add_definitions(-DNOMINMAX) + endif() endif() if(WITH_IMAGE_OPENEXR) diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h index b31b5326d66..29f1a465491 100644 --- a/source/blender/nodes/NOD_function.h +++ b/source/blender/nodes/NOD_function.h @@ -22,6 +22,7 @@ extern "C" { void register_node_type_fn_boolean_math(void); void register_node_type_fn_float_compare(void); +void register_node_type_fn_float_to_int(void); void register_node_type_fn_input_string(void); void register_node_type_fn_input_vector(void); void register_node_type_fn_random_float(void); diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 788978c4246..3b546d208e4 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -43,27 +43,30 @@ void register_node_type_geo_attribute_math(void); void register_node_type_geo_attribute_mix(void); void register_node_type_geo_attribute_proximity(void); void register_node_type_geo_attribute_randomize(void); +void register_node_type_geo_attribute_remove(void); void register_node_type_geo_attribute_separate_xyz(void); void register_node_type_geo_attribute_transfer(void); void register_node_type_geo_attribute_vector_math(void); void register_node_type_geo_attribute_vector_rotate(void); -void register_node_type_geo_attribute_remove(void); void register_node_type_geo_attribute_set(void); void register_node_type_geo_boolean(void); void register_node_type_geo_bounding_box(void); void register_node_type_geo_collection_info(void); void register_node_type_geo_convex_hull(void); +void register_node_type_geo_curve_endpoints(void); void register_node_type_geo_curve_length(void); void register_node_type_geo_curve_primitive_bezier_segment(void); void register_node_type_geo_curve_primitive_circle(void); +void register_node_type_geo_curve_primitive_line(void); void register_node_type_geo_curve_primitive_quadratic_bezier(void); +void register_node_type_geo_curve_primitive_quadrilateral(void); void register_node_type_geo_curve_primitive_spiral(void); void register_node_type_geo_curve_primitive_star(void); -void register_node_type_geo_curve_to_mesh(void); -void register_node_type_geo_curve_to_points(void); void register_node_type_geo_curve_resample(void); void register_node_type_geo_curve_reverse(void); void register_node_type_geo_curve_subdivide(void); +void register_node_type_geo_curve_to_mesh(void); +void register_node_type_geo_curve_to_points(void); void register_node_type_geo_delete_geometry(void); void register_node_type_geo_edge_split(void); void register_node_type_geo_input_material(void); @@ -79,6 +82,7 @@ void register_node_type_geo_mesh_primitive_grid(void); void register_node_type_geo_mesh_primitive_ico_sphere(void); void register_node_type_geo_mesh_primitive_line(void); void register_node_type_geo_mesh_primitive_uv_sphere(void); +void register_node_type_geo_mesh_subdivide(void); void register_node_type_geo_mesh_to_curve(void); void register_node_type_geo_object_info(void); void register_node_type_geo_point_distribute(void); @@ -92,11 +96,11 @@ void register_node_type_geo_raycast(void); void register_node_type_geo_sample_texture(void); void register_node_type_geo_select_by_material(void); void register_node_type_geo_separate_components(void); -void register_node_type_geo_subdivide(void); void register_node_type_geo_subdivision_surface(void); void register_node_type_geo_switch(void); void register_node_type_geo_transform(void); void register_node_type_geo_triangulate(void); +void register_node_type_geo_viewer(void); void register_node_type_geo_volume_to_mesh(void); #ifdef __cplusplus diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index caefccfdba0..cc01465f4e5 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -21,12 +21,12 @@ #include "BKE_attribute_access.hh" #include "BKE_geometry_set.hh" #include "BKE_geometry_set_instances.hh" -#include "BKE_node_ui_storage.hh" #include "DNA_node_types.h" #include "NOD_attribute_ref.hh" #include "NOD_derived_node_tree.hh" +#include "NOD_geometry_nodes_eval_log.hh" struct Depsgraph; struct ModifierData; @@ -53,10 +53,11 @@ using fn::GVMutableArray; using fn::GVMutableArray_GSpan; using fn::GVMutableArray_Typed; using fn::GVMutableArrayPtr; +using geometry_nodes_eval_log::NodeWarningType; /** - * This class exists to separate the memory management details of the geometry nodes evaluator from - * the node execution functions and related utilities. + * This class exists to separate the memory management details of the geometry nodes evaluator + * from the node execution functions and related utilities. */ class GeoNodeExecParamsProvider { public: @@ -64,6 +65,7 @@ class GeoNodeExecParamsProvider { const Object *self_object = nullptr; const ModifierData *modifier = nullptr; Depsgraph *depsgraph = nullptr; + geometry_nodes_eval_log::GeoLogger *logger = nullptr; /** * Returns true when the node is allowed to get/extract the input value. The identifier is diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh new file mode 100644 index 00000000000..b85862a0176 --- /dev/null +++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh @@ -0,0 +1,309 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#pragma once + +/** + * Many geometry nodes related UI features need access to data produced during evaluation. Not only + * is the final output required but also the intermediate results. Those features include + * attribute search, node warnings, socket inspection and the viewer node. + * + * This file provides the framework for logging data during evaluation and accessing the data after + * evaluation. + * + * During logging every thread gets its own local logger to avoid too much locking (logging + * generally happens for every socket). After geometry nodes evaluation is done, the thread-local + * logging information is combined and post-processed to make it easier for the UI to lookup. + * necessary information. + */ + +#include "BLI_enumerable_thread_specific.hh" +#include "BLI_linear_allocator.hh" +#include "BLI_map.hh" + +#include "BKE_geometry_set.hh" + +#include "FN_generic_pointer.hh" + +#include "NOD_derived_node_tree.hh" + +struct SpaceNode; +struct SpaceSpreadsheet; + +namespace blender::nodes::geometry_nodes_eval_log { + +using fn::GMutablePointer; +using fn::GPointer; + +/** Contains information about a value that has been computed during geometry nodes evaluation. */ +class ValueLog { + public: + virtual ~ValueLog() = default; +}; + +/** Contains an owned copy of a value of a generic type. */ +class GenericValueLog : public ValueLog { + private: + GMutablePointer data_; + + public: + GenericValueLog(GMutablePointer data) : data_(data) + { + } + + ~GenericValueLog() + { + data_.destruct(); + } + + GPointer value() const + { + return data_; + } +}; + +struct GeometryAttributeInfo { + std::string name; + AttributeDomain domain; + CustomDataType data_type; +}; + +/** Contains information about a geometry set. In most cases this does not store the entire + * geometry set as this would require too much memory. */ +class GeometryValueLog : public ValueLog { + private: + Vector<GeometryAttributeInfo> attributes_; + Vector<GeometryComponentType> component_types_; + std::unique_ptr<GeometrySet> full_geometry_; + + public: + struct MeshInfo { + int tot_verts, tot_edges, tot_faces; + }; + struct CurveInfo { + int tot_splines; + }; + struct PointCloudInfo { + int tot_points; + }; + struct InstancesInfo { + int tot_instances; + }; + + std::optional<MeshInfo> mesh_info; + std::optional<CurveInfo> curve_info; + std::optional<PointCloudInfo> pointcloud_info; + std::optional<InstancesInfo> instances_info; + + GeometryValueLog(const GeometrySet &geometry_set, bool log_full_geometry); + + Span<GeometryAttributeInfo> attributes() const + { + return attributes_; + } + + Span<GeometryComponentType> component_types() const + { + return component_types_; + } + + const GeometrySet *full_geometry() const + { + return full_geometry_.get(); + } +}; + +enum class NodeWarningType { + Error, + Warning, + Info, +}; + +struct NodeWarning { + NodeWarningType type; + std::string message; +}; + +struct NodeWithWarning { + DNode node; + NodeWarning warning; +}; + +/** The same value can be referenced by multiple sockets when they are linked. */ +struct ValueOfSockets { + Span<DSocket> sockets; + destruct_ptr<ValueLog> value; +}; + +class GeoLogger; +class ModifierLog; + +/** Every thread has its own local logger to avoid having to communicate between threads during + * evaluation. After evaluation the individual logs are combined. */ +class LocalGeoLogger { + private: + /* Back pointer to the owner of this local logger. */ + GeoLogger *main_logger_; + /* Allocator for the many small allocations during logging. This is in a `unique_ptr` so that + * ownership can be transferred later on. */ + std::unique_ptr<LinearAllocator<>> allocator_; + Vector<ValueOfSockets> values_; + Vector<NodeWithWarning> node_warnings_; + + friend ModifierLog; + + public: + LocalGeoLogger(GeoLogger &main_logger) : main_logger_(&main_logger) + { + this->allocator_ = std::make_unique<LinearAllocator<>>(); + } + + void log_value_for_sockets(Span<DSocket> sockets, GPointer value); + void log_multi_value_socket(DSocket socket, Span<GPointer> values); + void log_node_warning(DNode node, NodeWarningType type, std::string message); +}; + +/** The root logger class. */ +class GeoLogger { + private: + /** The entire geometry of sockets in this set should be cached, because e.g. the spreadsheet + * displays the data. We don't log the entire geometry at all places, because that would require + * way too much memory. */ + Set<DSocket> log_full_geometry_sockets_; + threading::EnumerableThreadSpecific<LocalGeoLogger> threadlocals_; + + friend LocalGeoLogger; + + public: + GeoLogger(Set<DSocket> log_full_geometry_sockets) + : log_full_geometry_sockets_(std::move(log_full_geometry_sockets)), + threadlocals_([this]() { return LocalGeoLogger(*this); }) + { + } + + LocalGeoLogger &local() + { + return threadlocals_.local(); + } + + auto begin() + { + return threadlocals_.begin(); + } + + auto end() + { + return threadlocals_.end(); + } +}; + +/** Contains information that has been logged for one specific socket. */ +class SocketLog { + private: + ValueLog *value_ = nullptr; + + friend ModifierLog; + + public: + const ValueLog *value() const + { + return value_; + } +}; + +/** Contains information that has been logged for one specific node. */ +class NodeLog { + private: + Vector<SocketLog> input_logs_; + Vector<SocketLog> output_logs_; + Vector<NodeWarning, 0> warnings_; + + friend ModifierLog; + + public: + const SocketLog *lookup_socket_log(eNodeSocketInOut in_out, int index) const; + const SocketLog *lookup_socket_log(const bNode &node, const bNodeSocket &socket) const; + + Span<SocketLog> input_logs() const + { + return input_logs_; + } + + Span<SocketLog> output_logs() const + { + return output_logs_; + } + + Span<NodeWarning> warnings() const + { + return warnings_; + } + + Vector<const GeometryAttributeInfo *> lookup_available_attributes() const; +}; + +/** Contains information that has been logged for one specific tree. */ +class TreeLog { + private: + Map<std::string, destruct_ptr<NodeLog>> node_logs_; + Map<std::string, destruct_ptr<TreeLog>> child_logs_; + + friend ModifierLog; + + public: + const NodeLog *lookup_node_log(StringRef node_name) const; + const NodeLog *lookup_node_log(const bNode &node) const; + const TreeLog *lookup_child_log(StringRef node_name) const; +}; + +/** Contains information about an entire geometry nodes evaluation. */ +class ModifierLog { + private: + LinearAllocator<> allocator_; + /* Allocators of the individual loggers. */ + Vector<std::unique_ptr<LinearAllocator<>>> logger_allocators_; + destruct_ptr<TreeLog> root_tree_logs_; + Vector<destruct_ptr<ValueLog>> logged_values_; + + public: + ModifierLog(GeoLogger &logger); + + const TreeLog &root_tree() const + { + return *root_tree_logs_; + } + + /* Utilities to find logged information for a specific context. */ + static const ModifierLog *find_root_by_node_editor_context(const SpaceNode &snode); + static const TreeLog *find_tree_by_node_editor_context(const SpaceNode &snode); + static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode, + const bNode &node); + static const SocketLog *find_socket_by_node_editor_context(const SpaceNode &snode, + const bNode &node, + const bNodeSocket &socket); + static const NodeLog *find_node_by_spreadsheet_editor_context( + const SpaceSpreadsheet &sspreadsheet); + + private: + using LogByTreeContext = Map<const DTreeContext *, TreeLog *>; + + TreeLog &lookup_or_add_tree_log(LogByTreeContext &log_by_tree_context, + const DTreeContext &tree_context); + NodeLog &lookup_or_add_node_log(LogByTreeContext &log_by_tree_context, DNode node); + SocketLog &lookup_or_add_socket_log(LogByTreeContext &log_by_tree_context, DSocket socket); +}; + +} // namespace blender::nodes::geometry_nodes_eval_log diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index f5f8f77f2a1..60a10d2c508 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -210,7 +210,7 @@ DefNode(CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIPS DefNode(CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE", BokehImage, "Bokeh Image", "" ) DefNode(CompositorNode, CMP_NODE_BOKEHBLUR, def_cmp_bokehblur, "BOKEHBLUR", BokehBlur, "Bokeh Blur", "" ) DefNode(CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH", Switch, "Switch", "" ) -DefNode(CompositorNode, CMP_NODE_SWITCH_VIEW, def_cmp_switch_view, "VIEWSWITCH", SwitchView, "View Switch", "" ) +DefNode(CompositorNode, CMP_NODE_SWITCH_VIEW, def_cmp_switch_view, "VIEWSWITCH", SwitchView, "Switch View", "" ) DefNode(CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "Color Correction", "" ) DefNode(CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" ) DefNode(CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYINGSCREEN", KeyingScreen, "Keying Screen", "" ) @@ -263,6 +263,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "") DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE", FloatCompare, "Float Compare", "") +DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "") DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING", InputString, "String", "") DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "") DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", RandomFloat, "Random Float", "") @@ -294,7 +295,9 @@ DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLEC DefNode(GeometryNode, GEO_NODE_CONVEX_HULL, 0, "CONVEX_HULL", ConvexHull, "Convex Hull", "") DefNode(GeometryNode, GEO_NODE_CURVE_LENGTH, 0, "CURVE_LENGTH", CurveLength, "Curve Length", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT, def_geo_curve_primitive_bezier_segment, "CURVE_PRIMITIVE_BEZIER_SEGMENT", CurvePrimitiveBezierSegment, "Bezier Segment", "") -DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, def_geo_curve_primitive_circle, "CURVE_PRIMITIVE_CIRCLE", CurvePrimitiveCircle, "Circle", "") +DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, def_geo_curve_primitive_circle, "CURVE_PRIMITIVE_CIRCLE", CurvePrimitiveCircle, "Curve Circle", "") +DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_LINE, def_geo_curve_primitive_line, "CURVE_PRIMITIVE_LINE", CurvePrimitiveLine, "Curve Line", "") +DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL, def_geo_curve_primitive_quadrilateral, "CURVE_PRIMITIVE_QUADRILATERAL", CurvePrimitiveQuadrilateral, "Quadrilateral", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER, 0, "CURVE_PRIMITIVE_QUADRATIC_BEZIER", CurveQuadraticBezier, "Quadratic Bezier", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_STAR, 0, "CURVE_PRIMITIVE_STAR", CurveStar, "Star", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_SPIRAL, 0, "CURVE_PRIMITIVE_SPIRAL", CurveSpiral, "Curve Spiral", "") @@ -303,6 +306,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_ DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "") DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "") +DefNode(GeometryNode, GEO_NODE_CURVE_ENDPOINTS, 0, "CURVE_ENDPOINTS", CurveEndpoints, "Curve Endpoints", "") DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, 0, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "") DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "") DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "") @@ -310,13 +314,13 @@ DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Vi DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") DefNode(GeometryNode, GEO_NODE_MATERIAL_ASSIGN, 0, "MATERIAL_ASSIGN", MaterialAssign, "Material Assign", "") DefNode(GeometryNode, GEO_NODE_MATERIAL_REPLACE, 0, "MATERIAL_REPLACE", MaterialReplace, "Material Replace", "") -DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Circle", "") +DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Mesh Circle", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CUBE, 0, "MESH_PRIMITIVE_CUBE", MeshCube, "Cube", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CYLINDER, def_geo_mesh_cylinder, "MESH_PRIMITIVE_CYLINDER", MeshCylinder, "Cylinder", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_GRID, 0, "MESH_PRIMITIVE_GRID", MeshGrid, "Grid", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, 0, "MESH_PRIMITIVE_ICO_SPHERE", MeshIcoSphere, "Ico Sphere", "") -DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Line", "") +DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Mesh Line", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, 0, "MESH_PRIMITIVE_UV_SPHERE", MeshUVSphere, "UV Sphere", "") DefNode(GeometryNode, GEO_NODE_MESH_TO_CURVE, 0, "MESH_TO_CURVE", MeshToCurve, "Mesh to Curve", "") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO", ObjectInfo, "Object Info", "") @@ -330,11 +334,12 @@ DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, def_geo_points_to_volume, "POIN DefNode(GeometryNode, GEO_NODE_RAYCAST, def_geo_raycast, "RAYCAST", Raycast, "Raycast", "") DefNode(GeometryNode, GEO_NODE_SELECT_BY_MATERIAL, 0, "SELECT_BY_MATERIAL", SelectByMaterial, "Select by Material", "") DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS", SeparateComponents, "Separate Components", "") -DefNode(GeometryNode, GEO_NODE_SUBDIVIDE, 0, "SUBDIVIDE", Subdivide, "Subdivide", "") +DefNode(GeometryNode, GEO_NODE_MESH_SUBDIVIDE, 0, "MESH_SUBDIVIDE", MeshSubdivide, "Mesh Subdivide", "") DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "") DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "") DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "") DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "") +DefNode(GeometryNode, GEO_NODE_VIEWER, 0, "VIEWER", Viewer, "Viewer", "") DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "") /* undefine macros */ diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 19815d01278..013d196e1c8 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -205,10 +205,11 @@ static void composite_node_add_init(bNodeTree *UNUSED(bnodetree), bNode *bnode) } } -static bool composite_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool composite_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); + return nodeIsStaticSocketType(socket_type) && + ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); } bNodeTreeType *ntreeType_Composite; diff --git a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c index 7437496d878..fa276e9a794 100644 --- a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c +++ b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c @@ -42,9 +42,9 @@ static void node_composit_init_antialiasing(bNodeTree *UNUSED(ntree), bNode *nod { NodeAntiAliasingData *data = MEM_callocN(sizeof(NodeAntiAliasingData), "node antialiasing data"); - data->threshold = 1.0f; - data->contrast_limit = 0.2f; - data->corner_rounding = 0.25f; + data->threshold = CMP_DEFAULT_SMAA_THRESHOLD; + data->contrast_limit = CMP_DEFAULT_SMAA_CONTRAST_LIMIT; + data->corner_rounding = CMP_DEFAULT_SMAA_CORNER_ROUNDING; node->storage = data; } diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c index be1359f795f..5041b16c303 100644 --- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c +++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c @@ -24,7 +24,7 @@ #include "node_composite_util.h" /* **************** Z COMBINE ******************** */ -/* lazy coder note: node->custom2 is abused to send signal */ +/* lazy coder NOTE: node->custom2 is abused to send signal. */ static bNodeSocketTemplate cmp_node_zcombine_in[] = { {SOCK_RGBA, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {SOCK_FLOAT, N_("Z"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 10000.0f, PROP_NONE}, diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc new file mode 100644 index 00000000000..26cde576400 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc @@ -0,0 +1,95 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <cmath> + +#include "BLI_string.h" + +#include "RNA_enum_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_function_util.hh" + +static bNodeSocketTemplate fn_node_float_to_int_in[] = { + {SOCK_FLOAT, N_("Float"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_float_to_int_out[] = { + {SOCK_INT, N_("Integer")}, + {-1, ""}, +}; + +static void fn_node_float_to_int_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "rounding_mode", 0, "", ICON_NONE); +} + +static void node_float_to_int_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) +{ + const char *name; + bool enum_label = RNA_enum_name(rna_enum_node_float_to_int_items, node->custom1, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); +} + +static const blender::fn::MultiFunction &get_multi_function(bNode &bnode) +{ + static blender::fn::CustomMF_SI_SO<float, int> round_fn{"Round", + [](float a) { return (int)round(a); }}; + static blender::fn::CustomMF_SI_SO<float, int> floor_fn{"Floor", + [](float a) { return (int)floor(a); }}; + static blender::fn::CustomMF_SI_SO<float, int> ceil_fn{"Ceiling", + [](float a) { return (int)ceil(a); }}; + static blender::fn::CustomMF_SI_SO<float, int> trunc_fn{"Truncate", + [](float a) { return (int)trunc(a); }}; + + switch (static_cast<FloatToIntRoundingMode>(bnode.custom1)) { + case FN_NODE_FLOAT_TO_INT_ROUND: + return round_fn; + case FN_NODE_FLOAT_TO_INT_FLOOR: + return floor_fn; + case FN_NODE_FLOAT_TO_INT_CEIL: + return ceil_fn; + case FN_NODE_FLOAT_TO_INT_TRUNCATE: + return trunc_fn; + } + + BLI_assert_unreachable(); + return blender::fn::dummy_multi_function; +} + +static void node_float_to_int_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + const blender::fn::MultiFunction &fn = get_multi_function(builder.bnode()); + builder.set_matching_fn(fn); +} + +void register_node_type_fn_float_to_int() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_FLOAT_TO_INT, "Float to Integer", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, fn_node_float_to_int_in, fn_node_float_to_int_out); + node_type_label(&ntype, node_float_to_int_label); + ntype.expand_in_mf_network = node_float_to_int_expand_in_mf_network; + ntype.draw_buttons = fn_node_float_to_int_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/node_geometry_tree.cc b/source/blender/nodes/geometry/node_geometry_tree.cc index f36d5b3c9ca..5f10cd87049 100644 --- a/source/blender/nodes/geometry/node_geometry_tree.cc +++ b/source/blender/nodes/geometry/node_geometry_tree.cc @@ -108,22 +108,22 @@ static bool geometry_node_tree_validate_link(bNodeTree *UNUSED(ntree), bNodeLink return (link->tosock->type == link->fromsock->type); } -static bool geometry_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool geometry_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, - SOCK_FLOAT, - SOCK_VECTOR, - SOCK_RGBA, - SOCK_BOOLEAN, - SOCK_INT, - SOCK_STRING, - SOCK_OBJECT, - SOCK_GEOMETRY, - SOCK_COLLECTION, - SOCK_TEXTURE, - SOCK_MATERIAL, - SOCK_ATTRIBUTE); + return nodeIsStaticSocketType(socket_type) && ELEM(socket_type->type, + SOCK_FLOAT, + SOCK_VECTOR, + SOCK_RGBA, + SOCK_BOOLEAN, + SOCK_INT, + SOCK_STRING, + SOCK_OBJECT, + SOCK_GEOMETRY, + SOCK_COLLECTION, + SOCK_TEXTURE, + SOCK_MATERIAL, + SOCK_ATTRIBUTE); } void register_node_tree_type_geo(void) diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 67d32d540a8..98c92eac98f 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -79,4 +79,26 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, Span<bool> masks, const bool invert); +struct CurveToPointsResults { + int result_size; + MutableSpan<float3> positions; + MutableSpan<float> radii; + MutableSpan<float> tilts; + + Map<std::string, GMutableSpan> point_attributes; + + MutableSpan<float3> tangents; + MutableSpan<float3> normals; + MutableSpan<float3> rotations; +}; +/** + * Create references for all result point cloud attributes to simplify accessing them later on. + */ +CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points, + const CurveEval &curve); + +void curve_create_default_rotation_attribute(Span<float3> tangents, + Span<float3> normals, + MutableSpan<float3> rotations); + } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc index 06a4327a6c5..3b951bda95e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc @@ -108,15 +108,14 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } - /* Otherwise use the input attribute's domain if it exists. */ - ReadAttributeLookup input_attribute = component.attribute_try_get_for_read(input_name); - if (input_attribute) { - return input_attribute.domain; + std::optional<AttributeMetaData> input_info = component.attribute_get_meta_data(input_name); + if (input_info) { + return input_info->domain; } return ATTR_DOMAIN_POINT; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc index b7863d38fc2..d71cb09f1bd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc @@ -143,8 +143,7 @@ static bool bvh_from_mesh(const Mesh *target_mesh, break; } - /* This only updates a cache and can be considered to be logically const. */ - BKE_bvhtree_from_mesh_get(&r_tree_data_mesh, const_cast<Mesh *>(target_mesh), bvh_type, 2); + BKE_bvhtree_from_mesh_get(&r_tree_data_mesh, target_mesh, bvh_type, 2); if (r_tree_data_mesh.tree == nullptr) { return false; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc index d1114713672..756f93f154f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc @@ -162,7 +162,7 @@ static void get_closest_mesh_points(const Mesh &mesh, { BLI_assert(mesh.totvert > 0); BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(&mesh), BVHTREE_FROM_VERTS, 2); + BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_VERTS, 2); get_closest_in_bvhtree(tree_data, positions, r_point_indices, r_distances_sq, r_positions); free_bvhtree_from_mesh(&tree_data); } @@ -175,7 +175,7 @@ static void get_closest_mesh_edges(const Mesh &mesh, { BLI_assert(mesh.totedge > 0); BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(&mesh), BVHTREE_FROM_EDGES, 2); + BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_EDGES, 2); get_closest_in_bvhtree(tree_data, positions, r_edge_indices, r_distances_sq, r_positions); free_bvhtree_from_mesh(&tree_data); } @@ -188,7 +188,7 @@ static void get_closest_mesh_looptris(const Mesh &mesh, { BLI_assert(mesh.totpoly > 0); BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(&mesh), BVHTREE_FROM_LOOPTRI, 2); + BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 2); get_closest_in_bvhtree(tree_data, positions, r_looptri_indices, r_distances_sq, r_positions); free_bvhtree_from_mesh(&tree_data); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index b1b17a321b8..4286db52115 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -82,7 +82,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords) copy_v3_v3(result->mvert[i].co, co); } else { - BLI_assert(!"Unexpected new vertex in hull output"); + BLI_assert_msg(0, "Unexpected new vertex in hull output"); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc new file mode 100644 index 00000000000..1f878259f30 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc @@ -0,0 +1,223 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_task.hh" +#include "BLI_timeit.hh" + +#include "BKE_pointcloud.h" +#include "BKE_spline.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_curve_endpoints_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_endpoints_out[] = { + {SOCK_GEOMETRY, N_("Start Points")}, + {SOCK_GEOMETRY, N_("End Points")}, + {-1, ""}, +}; + +namespace blender::nodes { + +/** + * Evaluate splines in parallel to speed up the rest of the node's execution. + */ +static void evaluate_splines(Span<SplinePtr> splines) +{ + threading::parallel_for_each(splines, [](const SplinePtr &spline) { + /* These functions fill the corresponding caches on each spline. */ + spline->evaluated_positions(); + spline->evaluated_tangents(); + spline->evaluated_normals(); + spline->evaluated_lengths(); + }); +} + +/** + * \note Use attributes from the curve component rather than the attribute data directly on the + * attribute storage to allow reading the virtual spline attributes like "cyclic" and "resolution". + */ +static void copy_spline_domain_attributes(const CurveComponent &curve_component, + Span<int> offsets, + PointCloudComponent &points) +{ + curve_component.attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { + if (meta_data.domain != ATTR_DOMAIN_CURVE) { + return true; + } + GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( + name, ATTR_DOMAIN_CURVE, meta_data.data_type); + + OutputAttribute result_attribute = points.attribute_try_get_for_output_only( + name, ATTR_DOMAIN_POINT, meta_data.data_type); + GMutableSpan result = result_attribute.as_span(); + + /* Only copy the attributes of splines in the offsets. */ + for (const int i : offsets.index_range()) { + spline_attribute->get(offsets[i], result[i]); + } + + result_attribute.save(); + return true; + }); +} + +/** + * Get the offsets for the splines whose endpoints we want to output. + * Filter those which are cyclic, or that evaluate to empty. + * Could be easily adapted to include a selection argument to support attribute selection. + */ +static blender::Vector<int> get_endpoint_spline_offsets(Span<SplinePtr> splines) +{ + blender::Vector<int> spline_offsets; + spline_offsets.reserve(splines.size()); + + for (const int i : splines.index_range()) { + if (!(splines[i]->is_cyclic() || splines[i]->evaluated_points_size() == 0)) { + spline_offsets.append(i); + } + } + + return spline_offsets; +} + +/** + * Copy the endpoint attributes from the correct positions at the splines at the offsets to + * the start and end attributes. + */ +static void copy_endpoint_attributes(Span<SplinePtr> splines, + Span<int> offsets, + CurveToPointsResults &start_data, + CurveToPointsResults &end_data) +{ + threading::parallel_for(offsets.index_range(), 64, [&](IndexRange range) { + for (const int i : range) { + const Spline &spline = *splines[offsets[i]]; + + /* Copy the start and end point data over. */ + start_data.positions[i] = spline.evaluated_positions().first(); + start_data.tangents[i] = spline.evaluated_tangents().first(); + start_data.normals[i] = spline.evaluated_normals().first(); + start_data.radii[i] = spline.radii().first(); + start_data.tilts[i] = spline.tilts().first(); + + end_data.positions[i] = spline.evaluated_positions().last(); + end_data.tangents[i] = spline.evaluated_tangents().last(); + end_data.normals[i] = spline.evaluated_normals().last(); + end_data.radii[i] = spline.radii().last(); + end_data.tilts[i] = spline.tilts().last(); + + /* Copy the point attribute data over. */ + for (const auto &item : start_data.point_attributes.items()) { + const StringRef name = item.key; + GMutableSpan point_span = item.value; + + BLI_assert(spline.attributes.get_for_read(name)); + GSpan spline_span = *spline.attributes.get_for_read(name); + blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]); + } + + for (const auto &item : end_data.point_attributes.items()) { + const StringRef name = item.key; + GMutableSpan point_span = item.value; + + BLI_assert(spline.attributes.get_for_read(name)); + GSpan spline_span = *spline.attributes.get_for_read(name); + blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]); + } + } + }); +} + +static void geo_node_curve_endpoints_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + + geometry_set = bke::geometry_set_realize_instances(geometry_set); + + if (!geometry_set.has_curve()) { + params.set_output("Start Points", GeometrySet()); + params.set_output("End Points", GeometrySet()); + return; + } + + const CurveComponent &curve_component = *geometry_set.get_component_for_read<CurveComponent>(); + const CurveEval &curve = *curve_component.get_for_read(); + const Span<SplinePtr> splines = curve.splines(); + curve.assert_valid_point_attributes(); + + evaluate_splines(splines); + + const Vector<int> offsets = get_endpoint_spline_offsets(splines); + const int total_size = offsets.size(); + + if (total_size == 0) { + params.set_output("Start Points", GeometrySet()); + params.set_output("End Points", GeometrySet()); + return; + } + + GeometrySet start_result = GeometrySet::create_with_pointcloud( + BKE_pointcloud_new_nomain(total_size)); + GeometrySet end_result = GeometrySet::create_with_pointcloud( + BKE_pointcloud_new_nomain(total_size)); + PointCloudComponent &start_point_component = + start_result.get_component_for_write<PointCloudComponent>(); + PointCloudComponent &end_point_component = + end_result.get_component_for_write<PointCloudComponent>(); + + CurveToPointsResults start_attributes = curve_to_points_create_result_attributes( + start_point_component, curve); + CurveToPointsResults end_attributes = curve_to_points_create_result_attributes( + end_point_component, curve); + + copy_endpoint_attributes(splines, offsets.as_span(), start_attributes, end_attributes); + copy_spline_domain_attributes(curve_component, offsets.as_span(), start_point_component); + curve_create_default_rotation_attribute( + start_attributes.tangents, start_attributes.normals, start_attributes.rotations); + curve_create_default_rotation_attribute( + end_attributes.tangents, end_attributes.normals, end_attributes.rotations); + + /* The default radius is way too large for points, divide by 10. */ + for (float &radius : start_attributes.radii) { + radius *= 0.1f; + } + for (float &radius : end_attributes.radii) { + radius *= 0.1f; + } + + params.set_output("Start Points", std::move(start_result)); + params.set_output("End Points", std::move(end_result)); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_endpoints() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_CURVE_ENDPOINTS, "Curve Endpoints", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_curve_endpoints_in, geo_node_curve_endpoints_out); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_endpoints_exec; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc index 963c48b7536..ae947b7aeed 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc @@ -83,9 +83,10 @@ static bool colinear_f3_f3_f3(const float3 p1, const float3 p2, const float3 p3) } static std::unique_ptr<CurveEval> create_point_circle_curve( - const float3 p1, const float3 p2, const float3 p3, const int resolution, float center_out[3]) + const float3 p1, const float3 p2, const float3 p3, const int resolution, float3 &r_center) { if (colinear_f3_f3_f3(p1, p2, p3)) { + r_center = float3(0); return nullptr; } @@ -118,6 +119,7 @@ static std::unique_ptr<CurveEval> create_point_circle_curve( /* If the 3 planes do not intersect at one point, just return empty geometry. */ if (!isect_plane_plane_plane_v3(plane_1, plane_2, plane_3, center)) { + r_center = float3(0); return nullptr; } @@ -126,7 +128,7 @@ static std::unique_ptr<CurveEval> create_point_circle_curve( const float theta_step = ((2 * M_PI) / (float)resolution); for (const int i : IndexRange(resolution)) { - /* Formula for a circle around a point and 2 unit vectors perpendicular. + /* Formula for a circle around a point and 2 unit vectors perpendicular * to each other and the axis of the circle from: * https://math.stackexchange.com/questions/73237/parametric-equation-of-a-circle-in-3d-space */ @@ -141,7 +143,7 @@ static std::unique_ptr<CurveEval> create_point_circle_curve( curve->add_spline(std::move(spline)); curve->attributes.reallocate(curve->splines().size()); - copy_v3_v3(center_out, center); + r_center = center; return curve; } @@ -179,18 +181,13 @@ static void geo_node_curve_primitive_circle_exec(GeoNodeExecParams params) std::unique_ptr<CurveEval> curve; if (mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS) { - float center_point[3]; + float3 center_point; curve = create_point_circle_curve(params.extract_input<float3>("Point 1"), params.extract_input<float3>("Point 2"), params.extract_input<float3>("Point 3"), std::max(params.extract_input<int>("Resolution"), 3), center_point); - if (curve) { - params.set_output("Center", float3(center_point)); - } - else { - params.set_output("Center", float3(0, 0, 0)); - } + params.set_output("Center", center_point); } else if (mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_RADIUS) { curve = create_radius_circle_curve(std::max(params.extract_input<int>("Resolution"), 3), @@ -210,7 +207,8 @@ static void geo_node_curve_primitive_circle_exec(GeoNodeExecParams params) void register_node_type_geo_curve_primitive_circle() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, "Circle", NODE_CLASS_GEOMETRY, 0); + geo_node_type_base( + &ntype, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, "Curve Circle", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates( &ntype, geo_node_curve_primitive_circle_in, geo_node_curve_primitive_circle_out); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc new file mode 100644 index 00000000000..eed3a998ef6 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc @@ -0,0 +1,146 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_spline.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_curve_primitive_line_in[] = { + {SOCK_VECTOR, N_("Start"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION}, + {SOCK_VECTOR, N_("End"), 0.0f, 0.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION}, + {SOCK_VECTOR, N_("Direction"), 0.0f, 0.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_FLOAT, N_("Length"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_primitive_line_out[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {-1, ""}, +}; + +static void geo_node_curve_primitive_line_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_curve_primitive_line_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCurvePrimitiveLine *data = (NodeGeometryCurvePrimitiveLine *)MEM_callocN( + sizeof(NodeGeometryCurvePrimitiveLine), __func__); + + data->mode = GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS; + node->storage = data; +} + +static void geo_node_curve_primitive_line_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + const NodeGeometryCurvePrimitiveLine *node_storage = (NodeGeometryCurvePrimitiveLine *) + node->storage; + const GeometryNodeCurvePrimitiveLineMode mode = (const GeometryNodeCurvePrimitiveLineMode) + node_storage->mode; + + bNodeSocket *p2_socket = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *direction_socket = p2_socket->next; + bNodeSocket *length_socket = direction_socket->next; + + nodeSetSocketAvailability(p2_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS); + nodeSetSocketAvailability(direction_socket, + mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION); + nodeSetSocketAvailability(length_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION); +} + +static std::unique_ptr<CurveEval> create_point_line_curve(const float3 start, const float3 end) +{ + std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); + std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>(); + + spline->resize(2); + MutableSpan<float3> positions = spline->positions(); + positions[0] = start; + positions[1] = end; + spline->radii().fill(1.0f); + spline->tilts().fill(0.0f); + curve->add_spline(std::move(spline)); + curve->attributes.reallocate(curve->splines().size()); + return curve; +} + +static std::unique_ptr<CurveEval> create_direction_line_curve(const float3 start, + const float3 direction, + const float length) +{ + std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); + std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>(); + + spline->resize(2); + MutableSpan<float3> positions = spline->positions(); + positions[0] = start; + positions[1] = direction.normalized() * length + start; + + spline->radii().fill(1.0f); + spline->tilts().fill(0.0f); + curve->add_spline(std::move(spline)); + curve->attributes.reallocate(curve->splines().size()); + return curve; +} + +static void geo_node_curve_primitive_line_exec(GeoNodeExecParams params) +{ + + const NodeGeometryCurvePrimitiveLine *node_storage = + (NodeGeometryCurvePrimitiveLine *)params.node().storage; + + GeometryNodeCurvePrimitiveLineMode mode = (GeometryNodeCurvePrimitiveLineMode)node_storage->mode; + + std::unique_ptr<CurveEval> curve; + if (mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS) { + curve = create_point_line_curve(params.extract_input<float3>("Start"), + params.extract_input<float3>("End")); + } + else if (mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION) { + curve = create_direction_line_curve(params.extract_input<float3>("Start"), + params.extract_input<float3>("Direction"), + params.extract_input<float>("Length")); + } + + params.set_output("Curve", GeometrySet::create_with_curve(curve.release())); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_primitive_line() +{ + static bNodeType ntype; + geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_LINE, "Curve Line", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates( + &ntype, geo_node_curve_primitive_line_in, geo_node_curve_primitive_line_out); + node_type_init(&ntype, blender::nodes::geo_node_curve_primitive_line_init); + node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_line_update); + node_type_storage(&ntype, + "NodeGeometryCurvePrimitiveLine", + node_free_standard_storage, + node_copy_standard_storage); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_line_exec; + ntype.draw_buttons = geo_node_curve_primitive_line_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc new file mode 100644 index 00000000000..5f3f159c305 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc @@ -0,0 +1,241 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_spline.hh" +#include "UI_interface.h" +#include "UI_resources.h" +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_curve_primitive_quadrilateral_in[] = { + {SOCK_FLOAT, N_("Width"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, + {SOCK_FLOAT, N_("Height"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, + {SOCK_FLOAT, N_("Bottom Width"), 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, + {SOCK_FLOAT, N_("Top Width"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, + {SOCK_FLOAT, N_("Offset"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {SOCK_FLOAT, N_("Bottom Height"), 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, + {SOCK_FLOAT, N_("Top Height"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {SOCK_VECTOR, N_("Point 1"), -1.0f, 1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {SOCK_VECTOR, N_("Point 2"), 1.0f, 1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {SOCK_VECTOR, N_("Point 3"), 1.0f, -1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {SOCK_VECTOR, N_("Point 4"), -1.0f, -1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_primitive_quadrilateral_out[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {-1, ""}, +}; + +static void geo_node_curve_primitive_quadrilateral_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); +} + +static void geo_node_curve_primitive_quadrilateral_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCurvePrimitiveQuad *data = (NodeGeometryCurvePrimitiveQuad *)MEM_callocN( + sizeof(NodeGeometryCurvePrimitiveQuad), __func__); + data->mode = GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE; + node->storage = data; +} + +namespace blender::nodes { + +static void geo_node_curve_primitive_quadrilateral_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeGeometryCurvePrimitiveQuad &node_storage = *(NodeGeometryCurvePrimitiveQuad *)node->storage; + GeometryNodeCurvePrimitiveQuadMode mode = static_cast<GeometryNodeCurvePrimitiveQuadMode>( + node_storage.mode); + + bNodeSocket *width = ((bNodeSocket *)node->inputs.first); + bNodeSocket *height = width->next; + bNodeSocket *bottom = height->next; + bNodeSocket *top = bottom->next; + bNodeSocket *offset = top->next; + bNodeSocket *bottom_height = offset->next; + bNodeSocket *top_height = bottom_height->next; + bNodeSocket *p1 = top_height->next; + bNodeSocket *p2 = p1->next; + bNodeSocket *p3 = p2->next; + bNodeSocket *p4 = p3->next; + + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + nodeSetSocketAvailability(sock, false); + } + + if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE) { + nodeSetSocketAvailability(width, true); + nodeSetSocketAvailability(height, true); + } + else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM) { + nodeSetSocketAvailability(width, true); + nodeSetSocketAvailability(height, true); + nodeSetSocketAvailability(offset, true); + } + else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID) { + nodeSetSocketAvailability(bottom, true); + nodeSetSocketAvailability(top, true); + nodeSetSocketAvailability(offset, true); + nodeSetSocketAvailability(height, true); + } + else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE) { + nodeSetSocketAvailability(width, true); + nodeSetSocketAvailability(bottom_height, true); + nodeSetSocketAvailability(top_height, true); + } + else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS) { + nodeSetSocketAvailability(p1, true); + nodeSetSocketAvailability(p2, true); + nodeSetSocketAvailability(p3, true); + nodeSetSocketAvailability(p4, true); + } +} + +static void create_rectangle_curve(MutableSpan<float3> positions, + const float height, + const float width) +{ + positions[0] = float3(width / 2.0f, -height / 2.0f, 0.0f); + positions[1] = float3(-width / 2.0f, -height / 2.0f, 0.0f); + positions[2] = float3(-width / 2.0f, height / 2.0f, 0.0f); + positions[3] = float3(width / 2.0f, height / 2.0f, 0.0f); +} + +static void create_points_curve(MutableSpan<float3> positions, + const float3 &p1, + const float3 &p2, + const float3 &p3, + const float3 &p4) +{ + positions[0] = p1; + positions[1] = p2; + positions[2] = p3; + positions[3] = p4; +} + +static void create_parallelogram_curve(MutableSpan<float3> positions, + const float height, + const float width, + const float offset) +{ + positions[0] = float3(width / 2.0f - offset / 2.0f, -height / 2.0f, 0.0f); + positions[1] = float3(-width / 2.0f - offset / 2.0f, -height / 2.0f, 0.0f); + positions[2] = float3(-width / 2.0f + offset / 2.0f, height / 2.0f, 0.0f); + positions[3] = float3(width / 2.0f + offset / 2.0f, height / 2.0f, 0.0f); +} +static void create_trapezoid_curve(MutableSpan<float3> positions, + const float bottom, + const float top, + const float offset, + const float height) +{ + positions[0] = float3(bottom / 2.0f, -height / 2.0f, 0.0f); + positions[1] = float3(-bottom / 2.0f, -height / 2.0f, 0.0f); + positions[2] = float3(-top / 2.0f + offset, height / 2.0f, 0.0f); + positions[3] = float3(top / 2.0f + offset, height / 2.0f, 0.0f); +} + +static void create_kite_curve(MutableSpan<float3> positions, + const float width, + const float bottom_height, + const float top_height) +{ + positions[0] = float3(-width / 2.0f, 0, 0); + positions[1] = float3(0, top_height, 0); + positions[2] = float3(width / 2, 0, 0); + positions[3] = float3(0, -bottom_height, 0); +} + +static void geo_node_curve_primitive_quadrilateral_exec(GeoNodeExecParams params) +{ + const NodeGeometryCurvePrimitiveQuad &node_storage = + *(NodeGeometryCurvePrimitiveQuad *)(params.node()).storage; + const GeometryNodeCurvePrimitiveQuadMode mode = static_cast<GeometryNodeCurvePrimitiveQuadMode>( + node_storage.mode); + + std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); + std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>(); + spline->resize(4); + spline->radii().fill(1.0f); + spline->tilts().fill(0.0f); + spline->set_cyclic(true); + MutableSpan<float3> positions = spline->positions(); + + switch (mode) { + case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE: + create_rectangle_curve(positions, + std::max(params.extract_input<float>("Height"), 0.0f), + std::max(params.extract_input<float>("Width"), 0.0f)); + break; + + case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM: + create_parallelogram_curve(positions, + std::max(params.extract_input<float>("Height"), 0.0f), + std::max(params.extract_input<float>("Width"), 0.0f), + params.extract_input<float>("Offset")); + break; + case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID: + create_trapezoid_curve(positions, + std::max(params.extract_input<float>("Bottom Width"), 0.0f), + std::max(params.extract_input<float>("Top Width"), 0.0f), + params.extract_input<float>("Offset"), + std::max(params.extract_input<float>("Height"), 0.0f)); + break; + case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE: + create_kite_curve(positions, + std::max(params.extract_input<float>("Width"), 0.0f), + std::max(params.extract_input<float>("Bottom Height"), 0.0f), + params.extract_input<float>("Top Height")); + break; + case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS: + create_points_curve(positions, + params.extract_input<float3>("Point 1"), + params.extract_input<float3>("Point 2"), + params.extract_input<float3>("Point 3"), + params.extract_input<float3>("Point 4")); + break; + default: + params.set_output("Curve", GeometrySet()); + return; + } + + curve->add_spline(std::move(spline)); + curve->attributes.reallocate(curve->splines().size()); + params.set_output("Curve", GeometrySet::create_with_curve(curve.release())); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_primitive_quadrilateral() +{ + static bNodeType ntype; + geo_node_type_base( + &ntype, GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL, "Quadrilateral", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, + geo_node_curve_primitive_quadrilateral_in, + geo_node_curve_primitive_quadrilateral_out); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_quadrilateral_exec; + ntype.draw_buttons = geo_node_curve_primitive_quadrilateral_layout; + node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_quadrilateral_update); + node_type_init(&ntype, geo_node_curve_primitive_quadrilateral_init); + node_type_storage(&ntype, + "NodeGeometryCurvePrimitiveQuad", + node_free_standard_storage, + node_copy_standard_storage); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc index 367da3bc3c2..2e2bb247e2b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc @@ -19,7 +19,7 @@ #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_curve_primitive_star_in[] = { - {SOCK_INT, N_("Points"), 8.0f, 0.0f, 0.0f, 0.0f, 4, 256, PROP_UNSIGNED}, + {SOCK_INT, N_("Points"), 8.0f, 0.0f, 0.0f, 0.0f, 3, 256, PROP_UNSIGNED}, {SOCK_FLOAT, N_("Inner Radius"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, {SOCK_FLOAT, N_("Outer Radius"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, {SOCK_FLOAT, N_("Twist"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_ANGLE}, @@ -64,7 +64,7 @@ static void geo_node_curve_primitive_star_exec(GeoNodeExecParams params) std::max(params.extract_input<float>("Inner Radius"), 0.0f), std::max(params.extract_input<float>("Outer Radius"), 0.0f), params.extract_input<float>("Twist"), - std::max(params.extract_input<int>("Points"), 4)); + std::max(params.extract_input<int>("Points"), 3)); params.set_output("Curve", GeometrySet::create_with_curve(curve.release())); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index fc65d1754e9..ad0c453c2af 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -87,6 +87,23 @@ static SplinePtr resample_spline(const Spline &input_spline, const int count) input_spline.tilts().first(), input_spline.radii().first()); output_spline->attributes.reallocate(1); + input_spline.attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = input_spline.attributes.get_for_read(name); + BLI_assert(src); + if (!output_spline->attributes.create(name, meta_data.data_type)) { + BLI_assert_unreachable(); + return false; + } + std::optional<GMutableSpan> dst = output_spline->attributes.get_for_write(name); + if (!dst) { + BLI_assert_unreachable(); + return false; + } + src->type().copy_assign(src->data(), dst->data()); + return true; + }, + ATTR_DOMAIN_POINT); return output_spline; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index 3de2604cd0a..7908c26e2dc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -116,38 +116,6 @@ static void subdivide_attribute(Span<T> src, } /** - * De Casteljau Bezier subdivision. - * - * <pre> - * handle_prev handle_next - * O----------------O - * / \ - * / x---O---x \ - * / new_* \ - * / \ - * O O - * point_prev point_next - * </pre> - */ -static void calculate_new_bezier_point(const float3 &point_prev, - float3 &handle_prev, - float3 &new_left_handle, - float3 &new_position, - float3 &new_right_handle, - float3 &handle_next, - const float3 &point_next, - const float parameter) -{ - const float3 center_point = float3::interpolate(handle_prev, handle_next, parameter); - - handle_prev = float3::interpolate(point_prev, handle_prev, parameter); - handle_next = float3::interpolate(handle_next, point_next, parameter); - new_left_handle = float3::interpolate(handle_prev, center_point, parameter); - new_right_handle = float3::interpolate(center_point, handle_next, parameter); - new_position = float3::interpolate(new_left_handle, new_right_handle, parameter); -} - -/** * In order to generate a Bezier spline with the same shape as the input spline, apply the * De Casteljau algorithm iteratively for the provided number of cuts, constantly updating the * previous result point's right handle and the left handle at the end of the segment. @@ -171,6 +139,10 @@ static void subdivide_bezier_segment(const BezierSpline &src, { const bool is_last_cyclic_segment = index == (src.size() - 1); const int next_index = is_last_cyclic_segment ? 0 : index + 1; + + /* The first point in the segment is always copied. */ + dst_positions[offset] = src_positions[index]; + if (src.segment_is_vector(index)) { if (is_last_cyclic_segment) { dst_type_left.first() = BezierSpline::HandleType::Vector; @@ -178,7 +150,6 @@ static void subdivide_bezier_segment(const BezierSpline &src, dst_type_left.slice(offset + 1, result_size).fill(BezierSpline::HandleType::Vector); dst_type_right.slice(offset, result_size).fill(BezierSpline::HandleType::Vector); - dst_positions[offset] = src_positions[index]; const float factor_delta = 1.0f / result_size; for (const int cut : IndexRange(result_size)) { const float factor = cut * factor_delta; @@ -194,21 +165,38 @@ static void subdivide_bezier_segment(const BezierSpline &src, dst_type_right.slice(offset, result_size).fill(BezierSpline::HandleType::Free); const int i_segment_last = is_last_cyclic_segment ? 0 : offset + result_size; - dst_positions[offset] = src_positions[index]; - dst_handles_right[offset] = src_handles_right[index]; - dst_handles_left[i_segment_last] = src_handles_left[next_index]; + + /* Create a Bezier segment to update iteratively for every subdivision + * and references to the meaningful values for ease of use. */ + BezierSpline temp; + temp.resize(2); + float3 &segment_start = temp.positions().first(); + float3 &segment_end = temp.positions().last(); + float3 &handle_prev = temp.handle_positions_right().first(); + float3 &handle_next = temp.handle_positions_left().last(); + segment_start = src_positions[index]; + segment_end = src_positions[next_index]; + handle_prev = src_handles_right[index]; + handle_next = src_handles_left[next_index]; for (const int cut : IndexRange(result_size - 1)) { const float parameter = 1.0f / (result_size - cut); - calculate_new_bezier_point(dst_positions[offset + cut], - dst_handles_right[offset + cut], - dst_handles_left[offset + cut + 1], - dst_positions[offset + cut + 1], - dst_handles_right[offset + cut + 1], - dst_handles_left[i_segment_last], - src_positions[next_index], - parameter); + const BezierSpline::InsertResult insert = temp.calculate_segment_insertion(0, 1, parameter); + + /* Copy relevant temporary data to the result. */ + dst_handles_right[offset + cut] = insert.handle_prev; + dst_handles_left[offset + cut + 1] = insert.left_handle; + dst_positions[offset + cut + 1] = insert.position; + + /* Update the segment to prepare it for the next subdivision. */ + segment_start = insert.position; + handle_prev = insert.right_handle; + handle_next = insert.handle_next; } + + /* Copy the handles for the last segment from the temporary spline. */ + dst_handles_right[offset + result_size - 1] = handle_prev; + dst_handles_left[i_segment_last] = handle_next; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc index c0d817385e2..f1bcb4ed47f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc @@ -337,7 +337,17 @@ static void geo_node_curve_to_mesh_exec(GeoNodeExecParams params) curve_set = bke::geometry_set_realize_instances(curve_set); profile_set = bke::geometry_set_realize_instances(profile_set); + /* NOTE: Theoretically an "is empty" check would be more correct for errors. */ + if (profile_set.has_mesh() && !profile_set.has_curve()) { + params.error_message_add(NodeWarningType::Warning, + TIP_("No curve data available in profile input")); + } + if (!curve_set.has_curve()) { + if (curve_set.has_mesh()) { + params.error_message_add(NodeWarningType::Warning, + TIP_("No curve data available in curve input")); + } params.set_output("Mesh", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index e37822bd262..bb8f560f92d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -118,22 +118,6 @@ static Array<int> calculate_spline_point_offsets(GeoNodeExecParams ¶ms, return {0}; } -/** - * \note This doesn't store a map for spline domain attributes. - */ -struct ResultAttributes { - int result_size; - MutableSpan<float3> positions; - MutableSpan<float> radii; - MutableSpan<float> tilts; - - Map<std::string, GMutableSpan> point_attributes; - - MutableSpan<float3> tangents; - MutableSpan<float3> normals; - MutableSpan<float3> rotations; -}; - static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &points, const StringRef name, const CustomDataType data_type) @@ -153,13 +137,10 @@ static MutableSpan<T> create_attribute_and_retrieve_span(PointCloudComponent &po return attribute.typed<T>(); } -/** - * Create references for all result point cloud attributes to simplify accessing them later on. - */ -static ResultAttributes create_point_attributes(PointCloudComponent &points, - const CurveEval &curve) +CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points, + const CurveEval &curve) { - ResultAttributes attributes; + CurveToPointsResults attributes; attributes.result_size = points.attribute_domain_size(ATTR_DOMAIN_POINT); @@ -190,7 +171,7 @@ static ResultAttributes create_point_attributes(PointCloudComponent &points, */ static void copy_evaluated_point_attributes(Span<SplinePtr> splines, Span<int> offsets, - ResultAttributes &data) + CurveToPointsResults &data) { threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) { for (const int i : range) { @@ -221,7 +202,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines, static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines, Span<int> offsets, - ResultAttributes &data) + CurveToPointsResults &data) { threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) { for (const int i : range) { @@ -307,13 +288,14 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component, }); } -static void create_default_rotation_attribute(ResultAttributes &data) +void curve_create_default_rotation_attribute(Span<float3> tangents, + Span<float3> normals, + MutableSpan<float3> rotations) { - threading::parallel_for(IndexRange(data.result_size), 512, [&](IndexRange range) { + threading::parallel_for(IndexRange(rotations.size()), 512, [&](IndexRange range) { for (const int i : range) { - data.rotations[i] = float4x4::from_normalized_axis_data( - {0, 0, 0}, data.normals[i], data.tangents[i]) - .to_euler(); + rotations[i] = + float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler(); } }); } @@ -348,8 +330,8 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params) GeometrySet result = GeometrySet::create_with_pointcloud(BKE_pointcloud_new_nomain(total_size)); PointCloudComponent &point_component = result.get_component_for_write<PointCloudComponent>(); - ResultAttributes new_attributes = create_point_attributes(point_component, curve); - + CurveToPointsResults new_attributes = curve_to_points_create_result_attributes(point_component, + curve); switch (mode) { case GEO_NODE_CURVE_SAMPLE_COUNT: case GEO_NODE_CURVE_SAMPLE_LENGTH: @@ -361,7 +343,8 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params) } copy_spline_domain_attributes(curve_component, offsets, point_component); - create_default_rotation_attribute(new_attributes); + curve_create_default_rotation_attribute( + new_attributes.tangents, new_attributes.normals, new_attributes.rotations); /* The default radius is way too large for points, divide by 10. */ for (float &radius : new_attributes.radii) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index b1da2dcd3c4..8c697275f88 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -627,7 +627,7 @@ static void delete_mesh_selection(MeshComponent &component, mesh_out = nullptr; break; } - component.replace_mesh_but_keep_vertex_group_names(mesh_out); + component.replace(mesh_out); } static void geo_node_delete_geometry_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc index 2915a17d2c8..667e1c931bd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc @@ -228,7 +228,8 @@ void register_node_type_geo_mesh_primitive_circle() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Circle", NODE_CLASS_GEOMETRY, 0); + geo_node_type_base( + &ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Mesh Circle", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates( &ntype, geo_node_mesh_primitive_circle_in, geo_node_mesh_primitive_circle_out); node_type_init(&ntype, geo_node_mesh_primitive_circle_init); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc index e841455e58c..a193c05daa1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc @@ -177,7 +177,7 @@ void register_node_type_geo_mesh_primitive_line() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_LINE, "Line", NODE_CLASS_GEOMETRY, 0); + geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_LINE, "Mesh Line", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates( &ntype, geo_node_mesh_primitive_line_in, geo_node_mesh_primitive_line_out); node_type_init(&ntype, geo_node_mesh_primitive_line_init); diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc index a4c6522c57a..245d7800621 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc @@ -14,8 +14,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// #include "MEM_guardedalloc.h" - #include "BKE_mesh.h" #include "BKE_subdiv.h" #include "BKE_subdiv_mesh.h" @@ -25,20 +23,20 @@ #include "node_geometry_util.hh" -static bNodeSocketTemplate geo_node_subdivide_in[] = { +static bNodeSocketTemplate geo_node_mesh_subdivide_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_INT, N_("Level"), 1, 0, 0, 0, 0, 6}, {-1, ""}, }; -static bNodeSocketTemplate geo_node_subdivide_out[] = { +static bNodeSocketTemplate geo_node_mesh_subdivide_out[] = { {SOCK_GEOMETRY, N_("Geometry")}, {-1, ""}, }; namespace blender::nodes { -static void geo_node_subdivide_exec(GeoNodeExecParams params) +static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); geometry_set = geometry_set_realize_instances(geometry_set); @@ -93,7 +91,7 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params) BKE_mesh_calc_normals(mesh_out); MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); - mesh_component.replace_mesh_but_keep_vertex_group_names(mesh_out); + mesh_component.replace(mesh_out); BKE_subdiv_free(subdiv); @@ -102,12 +100,12 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params) } // namespace blender::nodes -void register_node_type_geo_subdivide() +void register_node_type_geo_mesh_subdivide() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_SUBDIVIDE, "Subdivide", NODE_CLASS_GEOMETRY, 0); - node_type_socket_templates(&ntype, geo_node_subdivide_in, geo_node_subdivide_out); - ntype.geometry_node_execute = blender::nodes::geo_node_subdivide_exec; + geo_node_type_base(&ntype, GEO_NODE_MESH_SUBDIVIDE, "Mesh Subdivide", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_mesh_subdivide_in, geo_node_mesh_subdivide_out); + ntype.geometry_node_execute = blender::nodes::geo_node_mesh_subdivide_exec; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 772bd8a1080..d456c72744f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -83,8 +83,7 @@ static float3 normal_to_euler_rotation(const float3 normal) static Span<MLoopTri> get_mesh_looptris(const Mesh &mesh) { - /* This only updates a cache and can be considered to be logically const. */ - const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(const_cast<Mesh *>(&mesh)); + const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(&mesh); const int looptris_len = BKE_mesh_runtime_looptri_len(&mesh); return {looptris, looptris_len}; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc index bfd6027e0fc..0c1d8645411 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc @@ -95,7 +95,7 @@ static void raycast_to_mesh(const Mesh *mesh, BLI_assert(ray_origins.size() == r_hit_distances.size() || r_hit_distances.is_empty()); BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(mesh), BVHTREE_FROM_LOOPTRI, 4); + BKE_bvhtree_from_mesh_get(&tree_data, mesh, BVHTREE_FROM_LOOPTRI, 4); if (tree_data.tree != nullptr) { for (const int i : ray_origins.index_range()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index 20ffcdb516d..f0f032ed8f4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -96,7 +96,7 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params) BKE_mesh_calc_normals(mesh_out); MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); - mesh_component.replace_mesh_but_keep_vertex_group_names(mesh_out); + mesh_component.replace(mesh_out); // BKE_subdiv_stats_print(&subdiv->stats); BKE_subdiv_free(subdiv); diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc new file mode 100644 index 00000000000..f0b91f49f52 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc @@ -0,0 +1,31 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_viewer_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +void register_node_type_geo_viewer() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, 0); + node_type_socket_templates(&ntype, geo_node_viewer_in, nullptr); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc new file mode 100644 index 00000000000..3024cc51cad --- /dev/null +++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc @@ -0,0 +1,361 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "NOD_geometry_nodes_eval_log.hh" + +#include "BKE_geometry_set_instances.hh" + +#include "DNA_modifier_types.h" +#include "DNA_space_types.h" + +namespace blender::nodes::geometry_nodes_eval_log { + +using fn::CPPType; + +ModifierLog::ModifierLog(GeoLogger &logger) +{ + root_tree_logs_ = allocator_.construct<TreeLog>(); + + LogByTreeContext log_by_tree_context; + + /* Combine all the local loggers that have been used by separate threads. */ + for (LocalGeoLogger &local_logger : logger) { + /* Take ownership of the allocator. */ + logger_allocators_.append(std::move(local_logger.allocator_)); + + for (ValueOfSockets &value_of_sockets : local_logger.values_) { + ValueLog *value_log = value_of_sockets.value.get(); + + /* Take centralized ownership of the logged value. It might be referenced by multiple + * sockets. */ + logged_values_.append(std::move(value_of_sockets.value)); + + for (const DSocket &socket : value_of_sockets.sockets) { + SocketLog &socket_log = this->lookup_or_add_socket_log(log_by_tree_context, socket); + socket_log.value_ = value_log; + } + } + + for (NodeWithWarning &node_with_warning : local_logger.node_warnings_) { + NodeLog &node_log = this->lookup_or_add_node_log(log_by_tree_context, + node_with_warning.node); + node_log.warnings_.append(node_with_warning.warning); + } + } +} + +TreeLog &ModifierLog::lookup_or_add_tree_log(LogByTreeContext &log_by_tree_context, + const DTreeContext &tree_context) +{ + TreeLog *tree_log = log_by_tree_context.lookup_default(&tree_context, nullptr); + if (tree_log != nullptr) { + return *tree_log; + } + + const DTreeContext *parent_context = tree_context.parent_context(); + if (parent_context == nullptr) { + return *root_tree_logs_.get(); + } + TreeLog &parent_log = this->lookup_or_add_tree_log(log_by_tree_context, *parent_context); + destruct_ptr<TreeLog> owned_tree_log = allocator_.construct<TreeLog>(); + tree_log = owned_tree_log.get(); + log_by_tree_context.add_new(&tree_context, tree_log); + parent_log.child_logs_.add_new(tree_context.parent_node()->name(), std::move(owned_tree_log)); + return *tree_log; +} + +NodeLog &ModifierLog::lookup_or_add_node_log(LogByTreeContext &log_by_tree_context, DNode node) +{ + TreeLog &tree_log = this->lookup_or_add_tree_log(log_by_tree_context, *node.context()); + NodeLog &node_log = *tree_log.node_logs_.lookup_or_add_cb(node->name(), [&]() { + destruct_ptr<NodeLog> node_log = allocator_.construct<NodeLog>(); + node_log->input_logs_.resize(node->inputs().size()); + node_log->output_logs_.resize(node->outputs().size()); + return node_log; + }); + return node_log; +} + +SocketLog &ModifierLog::lookup_or_add_socket_log(LogByTreeContext &log_by_tree_context, + DSocket socket) +{ + NodeLog &node_log = this->lookup_or_add_node_log(log_by_tree_context, socket.node()); + MutableSpan<SocketLog> socket_logs = socket->is_input() ? node_log.input_logs_ : + node_log.output_logs_; + SocketLog &socket_log = socket_logs[socket->index()]; + return socket_log; +} + +const NodeLog *TreeLog::lookup_node_log(StringRef node_name) const +{ + const destruct_ptr<NodeLog> *node_log = node_logs_.lookup_ptr_as(node_name); + if (node_log == nullptr) { + return nullptr; + } + return node_log->get(); +} + +const NodeLog *TreeLog::lookup_node_log(const bNode &node) const +{ + return this->lookup_node_log(node.name); +} + +const TreeLog *TreeLog::lookup_child_log(StringRef node_name) const +{ + const destruct_ptr<TreeLog> *tree_log = child_logs_.lookup_ptr_as(node_name); + if (tree_log == nullptr) { + return nullptr; + } + return tree_log->get(); +} + +const SocketLog *NodeLog::lookup_socket_log(eNodeSocketInOut in_out, int index) const +{ + BLI_assert(index >= 0); + Span<SocketLog> socket_logs = (in_out == SOCK_IN) ? input_logs_ : output_logs_; + if (index >= socket_logs.size()) { + return nullptr; + } + return &socket_logs[index]; +} + +const SocketLog *NodeLog::lookup_socket_log(const bNode &node, const bNodeSocket &socket) const +{ + ListBase sockets = socket.in_out == SOCK_IN ? node.inputs : node.outputs; + int index = BLI_findindex(&sockets, &socket); + return this->lookup_socket_log((eNodeSocketInOut)socket.in_out, index); +} + +GeometryValueLog::GeometryValueLog(const GeometrySet &geometry_set, bool log_full_geometry) +{ + bke::geometry_set_instances_attribute_foreach( + geometry_set, + [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) { + this->attributes_.append({attribute_name, meta_data.domain, meta_data.data_type}); + return true; + }, + 8); + for (const GeometryComponent *component : geometry_set.get_components_for_read()) { + component_types_.append(component->type()); + switch (component->type()) { + case GEO_COMPONENT_TYPE_MESH: { + const MeshComponent &mesh_component = *(const MeshComponent *)component; + MeshInfo &info = this->mesh_info.emplace(); + info.tot_verts = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT); + info.tot_edges = mesh_component.attribute_domain_size(ATTR_DOMAIN_EDGE); + info.tot_faces = mesh_component.attribute_domain_size(ATTR_DOMAIN_FACE); + break; + } + case GEO_COMPONENT_TYPE_CURVE: { + const CurveComponent &curve_component = *(const CurveComponent *)component; + CurveInfo &info = this->curve_info.emplace(); + info.tot_splines = curve_component.attribute_domain_size(ATTR_DOMAIN_CURVE); + break; + } + case GEO_COMPONENT_TYPE_POINT_CLOUD: { + const PointCloudComponent &pointcloud_component = *(const PointCloudComponent *)component; + PointCloudInfo &info = this->pointcloud_info.emplace(); + info.tot_points = pointcloud_component.attribute_domain_size(ATTR_DOMAIN_POINT); + break; + } + case GEO_COMPONENT_TYPE_INSTANCES: { + const InstancesComponent &instances_component = *(const InstancesComponent *)component; + InstancesInfo &info = this->instances_info.emplace(); + info.tot_instances = instances_component.instances_amount(); + break; + } + case GEO_COMPONENT_TYPE_VOLUME: { + break; + } + } + } + if (log_full_geometry) { + full_geometry_ = std::make_unique<GeometrySet>(geometry_set); + full_geometry_->ensure_owns_direct_data(); + } +} + +Vector<const GeometryAttributeInfo *> NodeLog::lookup_available_attributes() const +{ + Vector<const GeometryAttributeInfo *> attributes; + Set<StringRef> names; + for (const SocketLog &socket_log : input_logs_) { + const ValueLog *value_log = socket_log.value(); + if (const GeometryValueLog *geo_value_log = dynamic_cast<const GeometryValueLog *>( + value_log)) { + for (const GeometryAttributeInfo &attribute : geo_value_log->attributes()) { + if (names.add(attribute.name)) { + attributes.append(&attribute); + } + } + } + } + return attributes; +} + +const ModifierLog *ModifierLog::find_root_by_node_editor_context(const SpaceNode &snode) +{ + if (snode.id == nullptr) { + return nullptr; + } + if (GS(snode.id->name) != ID_OB) { + return nullptr; + } + Object *object = (Object *)snode.id; + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Nodes) { + NodesModifierData *nmd = (NodesModifierData *)md; + if (nmd->node_group == snode.nodetree) { + return (ModifierLog *)nmd->runtime_eval_log; + } + } + } + return nullptr; +} + +const TreeLog *ModifierLog::find_tree_by_node_editor_context(const SpaceNode &snode) +{ + const ModifierLog *eval_log = ModifierLog::find_root_by_node_editor_context(snode); + if (eval_log == nullptr) { + return nullptr; + } + Vector<bNodeTreePath *> tree_path_vec = snode.treepath; + if (tree_path_vec.is_empty()) { + return nullptr; + } + TreeLog *current = eval_log->root_tree_logs_.get(); + for (bNodeTreePath *path : tree_path_vec.as_span().drop_front(1)) { + destruct_ptr<TreeLog> *tree_log = current->child_logs_.lookup_ptr_as(path->node_name); + if (tree_log == nullptr) { + return nullptr; + } + current = tree_log->get(); + } + return current; +} + +const NodeLog *ModifierLog::find_node_by_node_editor_context(const SpaceNode &snode, + const bNode &node) +{ + const TreeLog *tree_log = ModifierLog::find_tree_by_node_editor_context(snode); + if (tree_log == nullptr) { + return nullptr; + } + return tree_log->lookup_node_log(node); +} + +const SocketLog *ModifierLog::find_socket_by_node_editor_context(const SpaceNode &snode, + const bNode &node, + const bNodeSocket &socket) +{ + const NodeLog *node_log = ModifierLog::find_node_by_node_editor_context(snode, node); + if (node_log == nullptr) { + return nullptr; + } + return node_log->lookup_socket_log(node, socket); +} + +const NodeLog *ModifierLog::find_node_by_spreadsheet_editor_context( + const SpaceSpreadsheet &sspreadsheet) +{ + Vector<SpreadsheetContext *> context_path = sspreadsheet.context_path; + if (context_path.size() <= 2) { + return nullptr; + } + if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { + return nullptr; + } + if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) { + return nullptr; + } + for (SpreadsheetContext *context : context_path.as_span().drop_front(2)) { + if (context->type != SPREADSHEET_CONTEXT_NODE) { + return nullptr; + } + } + Span<SpreadsheetContextNode *> node_contexts = + context_path.as_span().drop_front(2).cast<SpreadsheetContextNode *>(); + + Object *object = ((SpreadsheetContextObject *)context_path[0])->object; + StringRefNull modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name; + if (object == nullptr) { + return nullptr; + } + + const ModifierLog *eval_log = nullptr; + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Nodes) { + if (md->name == modifier_name) { + NodesModifierData *nmd = (NodesModifierData *)md; + eval_log = (const ModifierLog *)nmd->runtime_eval_log; + break; + } + } + } + if (eval_log == nullptr) { + return nullptr; + } + + const TreeLog *tree_log = &eval_log->root_tree(); + for (SpreadsheetContextNode *context : node_contexts.drop_back(1)) { + tree_log = tree_log->lookup_child_log(context->node_name); + if (tree_log == nullptr) { + return nullptr; + } + } + const NodeLog *node_log = tree_log->lookup_node_log(node_contexts.last()->node_name); + return node_log; +} + +void LocalGeoLogger::log_value_for_sockets(Span<DSocket> sockets, GPointer value) +{ + const CPPType &type = *value.type(); + Span<DSocket> copied_sockets = allocator_->construct_array_copy(sockets); + if (type.is<GeometrySet>()) { + bool log_full_geometry = false; + for (const DSocket &socket : sockets) { + if (main_logger_->log_full_geometry_sockets_.contains(socket)) { + log_full_geometry = true; + break; + } + } + + const GeometrySet &geometry_set = *value.get<GeometrySet>(); + destruct_ptr<GeometryValueLog> value_log = allocator_->construct<GeometryValueLog>( + geometry_set, log_full_geometry); + values_.append({copied_sockets, std::move(value_log)}); + } + else { + void *buffer = allocator_->allocate(type.size(), type.alignment()); + type.copy_construct(value.get(), buffer); + destruct_ptr<GenericValueLog> value_log = allocator_->construct<GenericValueLog>( + GMutablePointer{type, buffer}); + values_.append({copied_sockets, std::move(value_log)}); + } +} + +void LocalGeoLogger::log_multi_value_socket(DSocket socket, Span<GPointer> values) +{ + /* Doesn't have to be logged currently. */ + UNUSED_VARS(socket, values); +} + +void LocalGeoLogger::log_node_warning(DNode node, NodeWarningType type, std::string message) +{ + node_warnings_.append({node, {type, std::move(message)}}); +} + +} // namespace blender::nodes::geometry_nodes_eval_log diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 7fc9f664df0..b8c89d1db37 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -127,7 +127,7 @@ static bNodeSocket *group_verify_socket( bNodeSocket *sock; for (sock = verify_lb->first; sock; sock = sock->next) { - if (sock->typeinfo == iosock->typeinfo && STREQ(sock->identifier, iosock->identifier)) { + if (STREQ(sock->identifier, iosock->identifier)) { break; } } @@ -137,6 +137,13 @@ static bNodeSocket *group_verify_socket( const int mask = SOCK_HIDE_VALUE; sock->flag = (sock->flag & ~mask) | (iosock->flag & mask); + /* Update socket type if necessary */ + if (sock->typeinfo != iosock->typeinfo) { + nodeModifySocketType(ntree, gnode, sock, iosock->idname); + /* Flag the tree to make sure link validity is updated after type changes. */ + ntree->update |= NTREE_UPDATE_LINKS; + } + if (iosock->typeinfo->interface_verify_socket) { iosock->typeinfo->interface_verify_socket(ntree, iosock, gnode, sock, "interface"); } @@ -259,7 +266,7 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node) static void node_reroute_init(bNodeTree *ntree, bNode *node) { - /* Note: Cannot use socket templates for this, since it would reset the socket type + /* NOTE: Cannot use socket templates for this, since it would reset the socket type * on each file read via the template verification procedure. */ nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "Input", "Input"); diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index 8b61758a673..1e39aa5214d 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -16,8 +16,6 @@ #include "DNA_modifier_types.h" -#include "BKE_node_ui_storage.hh" - #include "DEG_depsgraph_query.h" #include "NOD_geometry_exec.hh" @@ -26,21 +24,17 @@ #include "node_geometry_util.hh" +using blender::nodes::geometry_nodes_eval_log::LocalGeoLogger; + namespace blender::nodes { void GeoNodeExecParams::error_message_add(const NodeWarningType type, std::string message) const { - bNodeTree *btree_cow = provider_->dnode->btree(); - BLI_assert(btree_cow != nullptr); - if (btree_cow == nullptr) { + if (provider_->logger == nullptr) { return; } - bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow); - - const NodeTreeEvaluationContext context(*provider_->self_object, *provider_->modifier); - - BKE_nodetree_error_message_add( - *btree_original, context, *provider_->dnode->bnode(), type, std::move(message)); + LocalGeoLogger &local_logger = provider_->logger->local(); + local_logger.log_node_warning(provider_->dnode, type, std::move(message)); } const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name) const diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index c0a8382a661..e2568fd8f85 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -131,7 +131,7 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, } if (sock) { if (sock->type != stemp->type) { - nodeModifySocketType(ntree, node, sock, stemp->type, stemp->subtype); + nodeModifySocketTypeStatic(ntree, node, sock, stemp->type, stemp->subtype); } sock->flag |= stemp->flag; } @@ -563,12 +563,14 @@ static bNodeSocketType *make_standard_socket_type(int type, int subtype) { const char *socket_idname = nodeStaticSocketType(type, subtype); const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype); + const char *socket_label = nodeStaticSocketLabel(type, subtype); bNodeSocketType *stype; StructRNA *srna; stype = (bNodeSocketType *)MEM_callocN(sizeof(bNodeSocketType), "node socket C type"); stype->free_self = (void (*)(bNodeSocketType * stype)) MEM_freeN; BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname)); + BLI_strncpy(stype->label, socket_label, sizeof(stype->label)); /* set the RNA type * uses the exact same identifier as the socket type idname */ diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc index bed4d60382d..9ce9d6fc273 100644 --- a/source/blender/nodes/intern/node_tree_ref.cc +++ b/source/blender/nodes/intern/node_tree_ref.cc @@ -461,7 +461,7 @@ bool NodeTreeRef::has_undefined_nodes_or_sockets() const return true; } } - return true; + return false; } std::string NodeTreeRef::to_dot() const diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index e23e2ac3b9d..7367f73d171 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -184,10 +184,11 @@ static bool shader_validate_link(bNodeTree *UNUSED(ntree), bNodeLink *link) return true; } -static bool shader_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool shader_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER); + return nodeIsStaticSocketType(socket_type) && + ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER); } bNodeTreeType *ntreeType_Shader; @@ -790,7 +791,7 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod */ nodeAddLink(ntree, displacement_node, displacement_socket, bump_node, bump_input_socket); - /* Tag as part of the new displacmeent tree. */ + /* Tag as part of the new displacement tree. */ dot_node->tmp_flag = -2; geo_node->tmp_flag = -2; bump_node->tmp_flag = -2; diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c index 7a05fc95eec..50eb5bf32c9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c @@ -37,7 +37,7 @@ static bNodeSocketTemplate sh_node_hue_sat_out[] = { {-1, ""}, }; -/* note: it would be possible to use CMP version for both nodes */ +/* NOTE: it would be possible to use CMP version for both nodes. */ static void do_hue_sat_fac( bNode *UNUSED(node), float *out, float hue, float sat, float val, const float in[4], float fac) { diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 2ae722e3cd8..f771b4934b2 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -152,10 +152,11 @@ static void update(bNodeTree *ntree) } } -static bool texture_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool texture_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); + return nodeIsStaticSocketType(socket_type) && + ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); } bNodeTreeType *ntreeType_Texture; diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 90f54c50a6d..84d804f8bdf 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -20,8 +20,8 @@ #pragma once -struct AnimationEvalContext; struct ARegionType; +struct AnimationEvalContext; struct ChannelDriver; /* DNA_anim_types.h */ struct ID; /* DNA_ID.h */ struct ListBase; /* DNA_listBase.h */ diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index d198c6ca559..24887b24eb6 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -44,10 +44,10 @@ BLI_STATIC_ASSERT(sizeof(PyC_FlagSet) == sizeof(BMO_FlagSet), "size mismatch"); static int bpy_bm_op_as_py_error(BMesh *bm) { - if (BMO_error_occurred(bm)) { - /* note: we could have multiple errors */ + if (BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL)) { + /* NOTE: we could have multiple errors. */ const char *errmsg; - if (BMO_error_get(bm, &errmsg, NULL)) { + if (BMO_error_get(bm, &errmsg, NULL, NULL)) { PyErr_Format(PyExc_RuntimeError, "bmesh operator: %.200s", errmsg); BMO_error_clear(bm); return -1; @@ -243,7 +243,7 @@ static int bpy_slot_from_py(BMesh *bm, break; } case BMO_OP_SLOT_MAT: { - /* XXX - BMesh operator design is crappy here, operator slot should define matrix size, + /* XXX: BMesh operator design is crappy here, operator slot should define matrix size, * not the caller! */ MatrixObject *pymat; if (!Matrix_ParseAny(value, &pymat)) { @@ -583,7 +583,7 @@ static int bpy_slot_from_py(BMesh *bm, break; } default: - /* TODO --- many others */ + /* TODO: many others. */ PyErr_Format(PyExc_NotImplementedError, "%.200s: keyword \"%.200s\" type %d not working yet!", opname, @@ -608,7 +608,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) /* keep switch in same order as above */ switch (slot->slot_type) { case BMO_OP_SLOT_BOOL: - item = PyBool_FromLong((BMO_SLOT_AS_BOOL(slot))); + item = PyBool_FromLong(BMO_SLOT_AS_BOOL(slot)); break; case BMO_OP_SLOT_INT: item = PyLong_FromLong(BMO_SLOT_AS_INT(slot)); @@ -776,8 +776,8 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) return NULL; } - /* TODO - error check this!, though we do the error check on attribute access */ - /* TODO - make flags optional */ + /* TODO: error check this!, though we do the error check on attribute access. */ + /* TODO: make flags optional. */ BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, self->opname); if (kw && PyDict_Size(kw) > 0) { diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 9334e9893b0..612446e6d19 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -553,7 +553,7 @@ static PyObject *bpy_bmloop_is_convex_get(BPy_BMLoop *self) /* ElemSeq * ^^^^^^^ */ -/* note: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly */ +/* NOTE: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly. */ PyDoc_STRVAR(bpy_bmelemseq_layers_vert_doc, "custom-data layers (read-only).\n\n:type: :class:`BMLayerAccessVert`"); PyDoc_STRVAR(bpy_bmelemseq_layers_edge_doc, @@ -2588,7 +2588,7 @@ PyDoc_STRVAR( * If a portable alternative to qsort_r becomes available, remove this static * var hack! * - * Note: the functions below assumes the keys array has been allocated and it + * NOTE: the functions below assumes the keys array has been allocated and it * has enough elements to complete the task. */ diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index ed307ce59a0..043c5322735 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -114,7 +114,7 @@ typedef struct BPy_BMElemSeq { /* we hold a reference to this. * check in case the owner becomes invalid on access */ - /* TODO - make this a GC'd object!, will function OK without this though */ + /* TODO: make this a GC'd object!, will function OK without this though. */ BPy_BMElem *py_ele; /* iterator type */ diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index d9a82f52be0..8f4e07c30d3 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -500,7 +500,7 @@ static PySequenceMethods bpy_bmdeformvert_as_sequence = { NULL, /* sq_concat */ NULL, /* sq_repeat */ - /* Note: if this is set #PySequence_Check() returns True, + /* NOTE: if this is set #PySequence_Check() returns True, * but in this case we don't want to be treated as a seq. */ NULL, /* sq_item */ diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index c1e28182c53..1c3334f1adc 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -189,7 +189,7 @@ static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *ar bm = py_vert->bm; - return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v))); + return PyBool_FromLong(BM_vert_dissolve(bm, py_vert->v)); } PyDoc_STRVAR(bpy_bm_utils_vert_splice_doc, diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index c6afb694413..bfdc763e4df 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -1547,7 +1547,7 @@ static PySequenceMethods BPy_IDGroup_Seq = { NULL, /* binaryfunc sq_concat */ NULL, /* ssizeargfunc sq_repeat */ NULL, - /* ssizeargfunc sq_item */ /* TODO - setting this will allow PySequence_Check to return True */ + /* ssizeargfunc sq_item */ /* TODO: setting this will allow PySequence_Check to return True. */ NULL, /* intintargfunc ***was_sq_slice*** */ NULL, /* intobjargproc sq_ass_item */ NULL, /* ssizeobjargproc ***was_sq_ass_slice*** */ diff --git a/source/blender/python/generic/imbuf_py_api.c b/source/blender/python/generic/imbuf_py_api.c index 57e148b56c8..08ddef992a3 100644 --- a/source/blender/python/generic/imbuf_py_api.c +++ b/source/blender/python/generic/imbuf_py_api.c @@ -443,7 +443,7 @@ static PyObject *M_imbuf_new(PyObject *UNUSED(self), PyObject *args, PyObject *k return NULL; } - /* TODO, make options */ + /* TODO: make options. */ const uchar planes = 4; const uint flags = IB_rect; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 127380feec1..a27ef30c849 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -367,7 +367,7 @@ void PyC_LineSpit(void) const char *filename; int lineno; - /* Note, allow calling from outside python (RNA) */ + /* NOTE: allow calling from outside python (RNA). */ if (!PyC_IsInterpreterActive()) { fprintf(stderr, "python line lookup failed, interpreter inactive\n"); return; @@ -381,7 +381,7 @@ void PyC_LineSpit(void) void PyC_StackSpit(void) { - /* Note, allow calling from outside python (RNA) */ + /* NOTE: allow calling from outside python (RNA). */ if (!PyC_IsInterpreterActive()) { fprintf(stderr, "python line lookup failed, interpreter inactive\n"); return; @@ -826,13 +826,13 @@ PyObject *PyC_UnicodeFromByte(const char *str) /***************************************************************************** * Description: This function creates a new Python dictionary object. - * note: dict is owned by sys.modules["__main__"] module, reference is borrowed - * note: important we use the dict from __main__, this is what python expects + * NOTE: dict is owned by sys.modules["__main__"] module, reference is borrowed + * NOTE: important we use the dict from __main__, this is what python expects * for 'pickle' to work as well as strings like this... * >> foo = 10 * >> print(__import__("__main__").foo) * - * note: this overwrites __main__ which gives problems with nested calls. + * NOTE: this overwrites __main__ which gives problems with nested calls. * be sure to run PyC_MainModule_Backup & PyC_MainModule_Restore if there is * any chance that python is in the call stack. ****************************************************************************/ @@ -846,7 +846,7 @@ PyObject *PyC_DefaultNameSpace(const char *filename) PyModule_AddStringConstant(mod_main, "__name__", "__main__"); if (filename) { /* __file__ mainly for nice UI'ness - * note: this won't map to a real file when executing text-blocks and buttons. */ + * NOTE: this won't map to a real file when executing text-blocks and buttons. */ PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromByte(filename)); } PyModule_AddObject(mod_main, "__builtins__", builtins); diff --git a/source/blender/python/gpu/gpu_py_uniformbuffer.c b/source/blender/python/gpu/gpu_py_uniformbuffer.c index edcec486398..cfef20e2e4d 100644 --- a/source/blender/python/gpu/gpu_py_uniformbuffer.c +++ b/source/blender/python/gpu/gpu_py_uniformbuffer.c @@ -104,7 +104,7 @@ static PyObject *pygpu_uniformbuffer__tp_new(PyTypeObject *UNUSED(self), } PyDoc_STRVAR(pygpu_uniformbuffer_update_doc, - ".. method::update(data)\n" + ".. method:: update(data)\n" "\n" " Update the data of the uniform buffer object.\n"); static PyObject *pygpu_uniformbuffer_update(BPyGPUUniformBuf *self, PyObject *obj) diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index bc05c51414f..d66643c5d61 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -225,7 +225,7 @@ PyObject *BPY_app_handlers_struct(void) #endif if (PyType_Ready(&BPyPersistent_Type) < 0) { - BLI_assert(!"error initializing 'bpy.app.handlers.persistent'"); + BLI_assert_msg(0, "error initializing 'bpy.app.handlers.persistent'"); } PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc); @@ -283,7 +283,7 @@ void BPY_app_handlers_reset(const short do_all) for (i = PyList_GET_SIZE(ls) - 1; i >= 0; i--) { - if ((PyFunction_Check((item = PyList_GET_ITEM(ls, i)))) && + if (PyFunction_Check((item = PyList_GET_ITEM(ls, i))) && (dict_ptr = _PyObject_GetDictPtr(item)) && (*dict_ptr) && (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) { /* keep */ @@ -347,7 +347,7 @@ void bpy_app_generic_callback(struct Main *UNUSED(main), } /* Iterate the list and run the callbacks - * note: don't store the list size since the scripts may remove themselves */ + * NOTE: don't store the list size since the scripts may remove themselves. */ for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) { func = PyList_GET_ITEM(cb_list, pos); PyObject *args = choose_arguments(func, args_all, args_single); diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index 478ae61aecd..7437598582f 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -101,7 +101,7 @@ static bool _ghashutil_keycmp(const void *a, const void *b) const GHashKey *A = a; const GHashKey *B = b; - /* Note: comparing msgid first, most of the time it will be enough! */ + /* NOTE: comparing msgid first, most of the time it will be enough! */ if (BLI_ghashutil_strcmp(A->msgid, B->msgid) == false) { return BLI_ghashutil_strcmp(A->msgctxt, B->msgctxt); } @@ -497,7 +497,7 @@ static PyObject *app_translations_locale_get(PyObject *UNUSED(self), void *UNUSE return PyUnicode_FromString(BLT_lang_get()); } -/* Note: defining as getter, as (even if quite unlikely), this *may* change during runtime... */ +/* NOTE: defining as getter, as (even if quite unlikely), this *may* change during runtime... */ PyDoc_STRVAR(app_translations_locales_doc, "All locales currently known by Blender (i.e. available as translations)."); static PyObject *app_translations_locales_get(PyObject *UNUSED(self), void *UNUSED(userdata)) diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index a7b99f211c2..7effa25e6e8 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -175,7 +175,7 @@ int bpy_pydriver_create_dict(void) return 0; } -/* note, this function should do nothing most runs, only when changing frame */ +/* NOTE: this function should do nothing most runs, only when changing frame. */ /* not thread safe but neither is python */ static struct { float evaltime; @@ -266,7 +266,7 @@ static void pydriver_error(ChannelDriver *driver) "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression); - // BPy_errors_to_report(NULL); /* TODO - reports */ + // BPy_errors_to_report(NULL); /* TODO: reports. */ PyErr_Print(); PyErr_Clear(); } @@ -433,12 +433,12 @@ static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars, * This evaluates Python driver expressions, `driver_orig->expression` * is a Python expression that should evaluate to a float number, which is returned. * - * (old)note: PyGILState_Ensure() isn't always called because python can call + * (old) NOTE: PyGILState_Ensure() isn't always called because python can call * the bake operator which intern starts a thread which calls scene update * which does a driver update. to avoid a deadlock check #PyC_IsInterpreterActive() * if #PyGILState_Ensure() is needed, see T27683. * - * (new)note: checking if python is running is not thread-safe T28114 + * (new) NOTE: checking if python is running is not thread-safe T28114 * now release the GIL on python operator execution instead, using * #PyEval_SaveThread() / #PyEval_RestoreThread() so we don't lock up blender. * @@ -613,7 +613,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, fprintf( stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name); - // BPy_errors_to_report(NULL); /* TODO - reports */ + // BPy_errors_to_report(NULL); /* TODO: reports. */ PyErr_Print(); PyErr_Clear(); } diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c index 686a4d88266..34d2ba16e69 100644 --- a/source/blender/python/intern/bpy_gizmo_wrap.c +++ b/source/blender/python/intern/bpy_gizmo_wrap.c @@ -49,7 +49,7 @@ static bool bpy_gizmotype_target_property_def(wmGizmoType *gzt, PyObject *item) { - /* Note: names based on 'rna_rna.c' */ + /* NOTE: names based on `rna_rna.c`. */ PyObject *empty_tuple = PyTuple_New(0); struct { diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 832af9e8460..f91ba4d362c 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -154,7 +154,7 @@ void bpy_context_clear(bContext *UNUSED(C), const PyGILState_STATE *gilstate) fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n"); } else if (py_call_level == 0) { - /* XXX - Calling classes currently won't store the context :\, + /* XXX: Calling classes currently won't store the context :\, * can't set NULL because of this. but this is very flakey still. */ #if 0 BPY_context_set(NULL); @@ -763,7 +763,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * } #ifdef WITH_PYTHON_MODULE -/* TODO, reloading the module isn't functional at the moment. */ +/* TODO: reloading the module isn't functional at the moment. */ static void bpy_module_free(void *mod); @@ -825,7 +825,7 @@ static void dealloc_obj_dealloc(PyObject *self) { bpy_module_delay_init(((dealloc_obj *)self)->mod); - /* Note, for subclassed PyObjects we can't just call PyObject_DEL() directly or it will crash */ + /* NOTE: for subclassed PyObjects we can't just call PyObject_DEL() directly or it will crash. */ dealloc_obj_Type.tp_free(self); } diff --git a/source/blender/python/intern/bpy_interface_atexit.c b/source/blender/python/intern/bpy_interface_atexit.c index 03d51b2fd59..f92a48eb597 100644 --- a/source/blender/python/intern/bpy_interface_atexit.c +++ b/source/blender/python/intern/bpy_interface_atexit.c @@ -46,9 +46,8 @@ static PyObject *func_bpy_atregister = NULL; /* borrowed reference, `atexit` hol static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg) { - /* note - no error checking, if any of these fail we'll get a crash - * this is intended, but if its problematic it could be changed - * - campbell */ + /* NOTE(campbell): no error checking, if any of these fail we'll get a crash + * this is intended, but if its problematic it could be changed. */ PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0); PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name); diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index 28a97c3fa3b..d9a357c5e2e 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -66,6 +66,8 @@ typedef struct { char relpath[FILE_MAX]; char abspath[FILE_MAX]; /* absolute path */ BlendHandle *blo_handle; + /* Referenced by `blo_handle`, so stored here to keep alive for long enough. */ + BlendFileReadReport bf_reports; int flag; PyObject *dict; /* Borrowed reference to the `bmain`, taken from the RNA instance of #RNA_BlendDataLibraries. @@ -259,7 +261,8 @@ static PyObject *bpy_lib_enter(BPy_Library *self) BKE_reports_init(&reports, RPT_STORE); BlendFileReadReport bf_reports = {.reports = &reports}; - self->blo_handle = BLO_blendhandle_from_file(self->abspath, &bf_reports); + self->bf_reports = bf_reports; + self->blo_handle = BLO_blendhandle_from_file(self->abspath, &self->bf_reports); if (self->blo_handle == NULL) { if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) { diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c index 4e6d2aacb49..04220cf3105 100644 --- a/source/blender/python/intern/bpy_msgbus.c +++ b/source/blender/python/intern/bpy_msgbus.c @@ -90,12 +90,12 @@ static int py_msgbus_rna_key_from_py(PyObject *py_sub, msg_key_params->prop = data_prop->prop; } else if (BPy_StructRNA_Check(py_sub)) { - /* note, this isn't typically used since we don't edit structs directly. */ + /* NOTE: this isn't typically used since we don't edit structs directly. */ BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub; PYRNA_STRUCT_CHECK_INT(data_srna); msg_key_params->ptr = data_srna->ptr; } - /* TODO - property / type, not instance. */ + /* TODO: property / type, not instance. */ else if (PyType_Check(py_sub)) { StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix); if (data_type == NULL) { @@ -264,7 +264,7 @@ static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args return NULL; } - /* Note: we may want to have a way to pass this in. */ + /* NOTE: we may want to have a way to pass this in. */ bContext *C = BPY_context_get(); struct wmMsgBus *mbus = CTX_wm_message_bus(C); wmMsgParams_RNA msg_key_params = {{0}}; @@ -339,7 +339,7 @@ static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, return NULL; } - /* Note: we may want to have a way to pass this in. */ + /* NOTE: we may want to have a way to pass this in. */ bContext *C = BPY_context_get(); struct wmMsgBus *mbus = CTX_wm_message_bus(C); wmMsgParams_RNA msg_key_params = {{0}}; diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 055dd624ea8..9ee9f2e477f 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -82,8 +82,8 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) int context = WM_OP_EXEC_DEFAULT; - /* XXX Todo, work out a better solution for passing on context, - * could make a tuple from self and pack the name and Context into it... */ + /* XXX TODO: work out a better solution for passing on context, + * could make a tuple from self and pack the name and Context into it. */ bContext *C = BPY_context_get(); if (C == NULL) { @@ -169,8 +169,8 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) int context = WM_OP_EXEC_DEFAULT; int is_undo = false; - /* XXX Todo, work out a better solution for passing on context, - * could make a tuple from self and pack the name and Context into it... */ + /* XXX TODO: work out a better solution for passing on context, + * could make a tuple from self and pack the name and Context into it. */ bContext *C = BPY_context_get(); if (C == NULL) { @@ -276,7 +276,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) #ifdef BPY_RELEASE_GIL /* release GIL, since a thread could be started from an operator * that updates a driver */ - /* note: I have not seen any examples of code that does this + /* NOTE: I have not seen any examples of code that does this * so it may not be officially supported but seems to work ok. */ { PyThreadState *ts = PyEval_SaveThread(); diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 0d451a8dd7f..f332d547965 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -1779,12 +1779,12 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, item = seq_fast_items[i]; - if ((PyTuple_CheckExact(item)) && (item_size = PyTuple_GET_SIZE(item)) && + if (PyTuple_CheckExact(item) && (item_size = PyTuple_GET_SIZE(item)) && (item_size >= 3 && item_size <= 5) && (tmp.identifier = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && (tmp.name = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && (tmp.description = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && - /* TODO, number isn't ensured to be unique from the script author */ + /* TODO: number isn't ensured to be unique from the script author. */ (item_size != 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value)) && (item_size != 5 || ((py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.icon) || (tmp_icon = PyUnicode_AsUTF8(PyTuple_GET_ITEM(item, 3)))) && @@ -3509,7 +3509,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) if (def) { /* Only support getting integer default values here. */ if (!py_long_as_int(def, &defvalue)) { - /* note, using type error here is odd but python does this for invalid arguments */ + /* NOTE: using type error here is odd but python does this for invalid arguments. */ PyErr_SetString( PyExc_TypeError, "EnumProperty(...): 'default' can only be an integer when 'items' is a function"); @@ -3557,7 +3557,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) RNA_def_property_duplicate_pointers(srna, prop); if (is_itemf == false) { - /* note: this must be postponed until after #RNA_def_property_duplicate_pointers + /* NOTE: this must be postponed until after #RNA_def_property_duplicate_pointers * otherwise if this is a generator it may free the strings before we copy them */ Py_DECREF(items_fast); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index a3c5d4e9d66..e6f3e509469 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -734,12 +734,12 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) const short order = pyrna_rotation_euler_order_get( ptr, EULER_ORDER_XYZ, &prop_eul_order); - ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA. */ + ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO: get order from RNA. */ RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); } else { /* Order will be updated from callback on use. */ - /* TODO, get order from RNA. */ + /* TODO: get order from RNA. */ PyObject *eul_cb = Euler_CreatePyObject_cb( ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); Py_DECREF(ret); /* The euler owns 'ret' now. */ @@ -817,7 +817,7 @@ int pyrna_enum_value_from_id(const EnumPropertyItem *item, return 0; } -/* note on __cmp__: +/* NOTE(campbell): Regarding comparison `__cmp__`: * checking the 'ptr->data' matches works in almost all cases, * however there are a few RNA properties that are fake sub-structs and * share the pointer with the parent, in those cases this happens 'a.b == a' @@ -825,8 +825,7 @@ int pyrna_enum_value_from_id(const EnumPropertyItem *item, * * So compare the 'ptr->type' as well to avoid this problem. * It's highly unlikely this would happen that 'ptr->data' and 'ptr->prop' would match, - * but _not_ 'ptr->type' but include this check for completeness. - * - campbell */ + * but _not_ 'ptr->type' but include this check for completeness. */ static int pyrna_struct_compare(BPy_StructRNA *a, BPy_StructRNA *b) { @@ -1196,7 +1195,7 @@ static void pyrna_struct_dealloc(BPy_StructRNA *self) } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ - /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */ + /* NOTE: for subclassed PyObjects calling PyObject_DEL() directly crashes. */ Py_TYPE(self)->tp_free(self); } @@ -1225,7 +1224,7 @@ static void pyrna_prop_dealloc(BPy_PropertyRNA *self) PyObject_ClearWeakRefs((PyObject *)self); } #endif - /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */ + /* NOTE: for subclassed PyObjects calling PyObject_DEL() directly crashes. */ Py_TYPE(self)->tp_free(self); } @@ -1236,7 +1235,7 @@ static void pyrna_prop_array_dealloc(BPy_PropertyRNA *self) PyObject_ClearWeakRefs((PyObject *)self); } #endif - /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */ + /* NOTE: for subclassed PyObjects calling PyObject_DEL() directly crashes. */ Py_TYPE(self)->tp_free(self); } @@ -1879,7 +1878,7 @@ static int pyrna_py_to_prop( #ifdef USE_STRING_COERCE PyObject *value_coerce = NULL; if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - /* TODO, get size. */ + /* TODO: get size. */ param = PyC_UnicodeAsByte(value, &value_coerce); } else { @@ -2640,7 +2639,7 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, } /** - * TODO - dimensions + * TODO: dimensions * \note Could also use pyrna_prop_array_to_py_index(self, count) in a loop, but it's much slower * since at the moment it reads (and even allocates) the entire array for each index. */ @@ -2729,7 +2728,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, break; } default: - BLI_assert(!"Invalid array type"); + BLI_assert_msg(0, "Invalid array type"); PyErr_SetString(PyExc_TypeError, "not an array type"); Py_DECREF(tuple); @@ -2853,7 +2852,7 @@ static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *val return -1; } -/* note: currently this is a copy of 'pyrna_prop_collection_subscript' with +/* NOTE: currently this is a copy of 'pyrna_prop_collection_subscript' with * large blocks commented, we may support slice/key indices later */ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject *key, @@ -2884,7 +2883,7 @@ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, return pyrna_prop_collection_ass_subscript_int(self, i, value); } -#if 0 /* TODO, fake slice assignment. */ +#if 0 /* TODO: fake slice assignment. */ else if (PySlice_Check(key)) { PySliceObject *key_slice = (PySliceObject *)key; Py_ssize_t step = 1; @@ -2967,7 +2966,7 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject return NULL; } if (key_slice->start == Py_None && key_slice->stop == Py_None) { - /* Note: no significant advantage with optimizing [:] slice as with collections, + /* NOTE: no significant advantage with optimizing [:] slice as with collections, * but include here for consistency with collection slice func */ const Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self); return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); @@ -4113,7 +4112,7 @@ static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args) } } else { - /* TODO, panels, menus etc. */ + /* TODO: panels, menus etc. */ PyErr_Format( PyExc_ValueError, "Class type \"%.200s\" not supported", RNA_struct_identifier(srna_base)); return NULL; @@ -4254,6 +4253,56 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self) return ret; } +PyDoc_STRVAR(pyrna_struct_id_properties_ensure_doc, + ".. method:: id_properties_ensure()\n" + " :return: the parent group for an RNA struct's custom IDProperties.\n" + " :rtype: :class:`bpy.types.IDPropertyGroup`\n"); +static PyObject *pyrna_struct_id_properties_ensure(BPy_StructRNA *self) +{ + PYRNA_STRUCT_CHECK_OBJ(self); + + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties"); + return NULL; + } + + IDProperty *idprops = RNA_struct_idprops(&self->ptr, true); + + /* This is a paranoid check that theoretically might not be necessary. + * It allows the possibility that some structs can't ensure IDProperties. */ + if (idprops == NULL) { + return Py_None; + } + + BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type); + group->owner_id = self->ptr.owner_id; + group->prop = idprops; + group->parent = NULL; + return (PyObject *)group; +} + +PyDoc_STRVAR(pyrna_struct_id_properties_clear_doc, + ".. method:: id_properties_clear()\n" + " :return: Remove the parent group for an RNA struct's custom IDProperties.\n"); +static PyObject *pyrna_struct_id_properties_clear(BPy_StructRNA *self) +{ + PYRNA_STRUCT_CHECK_OBJ(self); + + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties"); + return NULL; + } + + IDProperty **idprops = RNA_struct_idprops_p(&self->ptr); + + if (*idprops) { + IDP_FreeProperty(*idprops); + *idprops = NULL; + } + + Py_RETURN_NONE; +} + /* ---------------getattr-------------------------------------------- */ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) { @@ -4326,7 +4375,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) } default: /* Should never happen. */ - BLI_assert(!"Invalid context type"); + BLI_assert_msg(0, "Invalid context type"); PyErr_Format(PyExc_AttributeError, "bpy_struct: Context type invalid %d, can't get \"%.200s\" from context", @@ -5183,7 +5232,7 @@ static int foreach_parse_args(BPy_PropertyRNA *self, return -1; } - /* TODO - buffer may not be a sequence! array.array() is though. */ + /* TODO: buffer may not be a sequence! array.array() is though. */ *r_tot = PySequence_Size(*r_seq); if (*r_tot > 0) { @@ -5340,7 +5389,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) break; case PROP_RAW_UNSET: /* Should never happen. */ - BLI_assert(!"Invalid array type - set"); + BLI_assert_msg(0, "Invalid array type - set"); break; } @@ -5357,7 +5406,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) Py_buffer buf; PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); - /* Check if the buffer matches, TODO - signed/unsigned types. */ + /* Check if the buffer matches, TODO: signed/unsigned types. */ buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); @@ -5404,7 +5453,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) break; default: /* PROP_RAW_UNSET */ /* Should never happen. */ - BLI_assert(!"Invalid array type - get"); + BLI_assert_msg(0, "Invalid array type - get"); item = Py_None; Py_INCREF(item); break; @@ -5744,6 +5793,14 @@ static struct PyMethodDef pyrna_struct_methods[] = { METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_doc}, {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, + {"id_properties_ensure", + (PyCFunction)pyrna_struct_id_properties_ensure, + METH_NOARGS, + pyrna_struct_id_properties_ensure_doc}, + {"id_properties_clear", + (PyCFunction)pyrna_struct_id_properties_clear, + METH_NOARGS, + pyrna_struct_id_properties_clear_doc}, /* experimental */ /* unused for now */ @@ -5817,8 +5874,10 @@ static struct PyMethodDef pyrna_prop_collection_idprop_methods[] = { {NULL, NULL, 0, NULL}, }; -/* only needed for subtyping, so a new class gets a valid BPy_StructRNA - * todo - also accept useful args */ +/** + * only needed for sub-typing, so a new class gets a valid #BPy_StructRNA + * TODO: also accept useful args. + */ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { if (PyTuple_GET_SIZE(args) == 1) { @@ -5865,8 +5924,10 @@ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject * return NULL; } -/* only needed for subtyping, so a new class gets a valid BPy_StructRNA - * todo - also accept useful args */ +/** + * Only needed for sub-typing, so a new class gets a valid #BPy_StructRNA + * TODO: also accept useful args. + */ static PyObject *pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { BPy_PropertyRNA *base; @@ -6025,7 +6086,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat RNA_id_pointer_create(*(void **)data, &newptr); } else { - /* note: this is taken from the function's ID pointer + /* NOTE: this is taken from the function's ID pointer * and will break if a function returns a pointer from * another ID block, watch this! - it should at least be * easy to debug since they are all ID's */ @@ -6088,7 +6149,7 @@ static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_look static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject *kw) { - /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here. */ + /* NOTE: both BPy_StructRNA and BPy_PropertyRNA can be used here. */ PointerRNA *self_ptr = &self->ptr; FunctionRNA *self_func = self->func; @@ -6436,11 +6497,11 @@ static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *UNUSED(closure) } /* Subclasses of pyrna_struct_Type which support idprop definitions use this as a metaclass. */ -/* note: tp_base member is set to &PyType_Type on init */ +/* NOTE: tp_base member is set to &PyType_Type on init. */ PyTypeObject pyrna_struct_meta_idprop_Type = { PyVarObject_HEAD_INIT(NULL, 0) "bpy_struct_meta_idprop", /* tp_name */ - /* NOTE! would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's */ + /* NOTE: would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's. */ sizeof(PyHeapTypeObject), /* tp_basicsize */ 0, /* tp_itemsize */ @@ -7216,7 +7277,7 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna) RNA_pointer_create(NULL, &RNA_Struct, srna, &ptr); item = pyrna_struct_CreatePyObject(&ptr); - /* Note, must set the class not the __dict__ else the internal slots are not updated correctly. + /* NOTE: must set the class not the __dict__ else the internal slots are not updated correctly. */ PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item); Py_DECREF(item); @@ -7433,7 +7494,9 @@ static PyObject *pyrna_srna_Subtype(StructRNA *srna) return newclass; } -/* Use for subtyping so we know which srna is used for a PointerRNA. */ +/** + * Use for sub-typing so we know which SRNA is used for a #PointerRNA. + */ static StructRNA *srna_from_ptr(PointerRNA *ptr) { if (ptr->type == &RNA_Struct) { @@ -7454,7 +7517,7 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr) { BPy_StructRNA *pyrna = NULL; - /* Note: don't rely on this to return None since NULL data with a valid type can often crash. */ + /* NOTE: don't rely on this to return None since NULL data with a valid type can often crash. */ if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data. */ Py_RETURN_NONE; } @@ -8367,7 +8430,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun return bpy_class_validate_recursive(dummyptr, dummyptr->type, py_data, have_function); } -/* TODO - multiple return values like with RNA functions. */ +/* TODO: multiple return values like with RNA functions. */ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) { PyObject *args; @@ -8772,7 +8835,7 @@ void pyrna_free_types(void) void *py_ptr = RNA_struct_py_type_get(srna); if (py_ptr) { -#if 0 /* XXX - should be able to do this, but makes Python crash on exit. */ +#if 0 /* XXX: should be able to do this, but makes Python crash on exit. */ bpy_class_free(py_ptr); #endif RNA_struct_py_type_set(srna, NULL); diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index b359e93315e..9745f39b6b8 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -240,7 +240,7 @@ static int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *pyoptions = NULL; const char *path; - /* note, parse_str MUST start with 's|ifsO!' */ + /* NOTE: `parse_str` MUST start with `s|ifsO!`. */ if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index aafc787b6fc..abbc332d89d 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -548,7 +548,7 @@ static int py_to_array(PyObject *seq, } if (totitem) { - /* note: this code is confusing */ + /* NOTE: this code is confusing. */ if (param_data && RNA_property_flag(prop) & PROP_DYNAMIC) { /* not freeing allocated mem, RNA_parameter_list_free() will do this */ ParameterDynAlloc *param_alloc = (ParameterDynAlloc *)param_data; @@ -990,7 +990,7 @@ PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop) return pyrna_prop_CreatePyObject(ptr, prop); } -/* TODO, multi-dimensional arrays */ +/* TODO: multi-dimensional arrays. */ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) { const int len = RNA_property_array_length(ptr, prop); diff --git a/source/blender/python/intern/bpy_rna_gizmo.c b/source/blender/python/intern/bpy_rna_gizmo.c index 1f27e4bcca8..869019692df 100644 --- a/source/blender/python/intern/bpy_rna_gizmo.c +++ b/source/blender/python/intern/bpy_rna_gizmo.c @@ -246,7 +246,7 @@ static PyObject *bpy_gizmo_target_set_handler(PyObject *UNUSED(self), PyObject * .py_fn_slots = {NULL}, }; - /* Note: this is a counter-part to functions: + /* NOTE: this is a counter-part to functions: * 'Gizmo.target_set_prop & target_set_operator' * (see: rna_wm_gizmo_api.c). conventions should match. */ static const char *const _keywords[] = {"self", "target", "get", "set", "range", NULL}; @@ -537,7 +537,7 @@ bool BPY_rna_gizmo_module(PyObject *mod_par) PyObject *func_inst = PyInstanceMethod_New(func); char name_prefix[128]; PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_gizmo_%s", m->ml_name); - /* TODO, return a type that binds nearly to a method. */ + /* TODO: return a type that binds nearly to a method. */ PyModule_AddObject(mod_par, name_prefix, func_inst); } diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c index ac061c3dd60..66044311321 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.c +++ b/source/blender/python/intern/bpy_rna_id_collection.c @@ -130,7 +130,7 @@ static int foreach_libblock_id_user_map_callback(LibraryIDLinkCallbackData *cb_d } PyDoc_STRVAR(bpy_user_map_doc, - ".. method:: user_map([subset=(id1, id2, ...)], key_types={..}, value_types={..})\n" + ".. method:: user_map(subset, key_types, value_types)\n" "\n" " Returns a mapping of all ID data-blocks in current ``bpy.data`` to a set of all " "datablocks using them.\n" @@ -277,7 +277,7 @@ error: } PyDoc_STRVAR(bpy_batch_remove_doc, - ".. method:: batch_remove(ids=(id1, id2, ...))\n" + ".. method:: batch_remove(ids)\n" "\n" " Remove (delete) several IDs at once.\n" "\n" diff --git a/source/blender/python/intern/bpy_utils_previews.c b/source/blender/python/intern/bpy_utils_previews.c index 7a826d99a3d..6a46d2a1a96 100644 --- a/source/blender/python/intern/bpy_utils_previews.c +++ b/source/blender/python/intern/bpy_utils_previews.c @@ -59,7 +59,6 @@ PyDoc_STRVAR( " :type name: string\n" " :return: The Preview matching given name, or a new empty one.\n" " :rtype: :class:`bpy.types.ImagePreview`\n" - " :rtype: :class:`bpy.types.ImagePreview`\n" /* This is only true when accessed via 'bpy.utils.previews.ImagePreviewCollection.load', * however this is the public API, allow this minor difference to the internal version here. */ " :raises KeyError: if ``name`` already exists."); diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index 8a7f782de3c..7546f2ef730 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -68,7 +68,7 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* -----------------------------METHODS---------------------------- */ -/* note: BaseMath_ReadCallback must be called beforehand */ +/* NOTE: BaseMath_ReadCallback must be called beforehand. */ static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits) { PyObject *ret; @@ -570,7 +570,7 @@ static PyObject *Color_mul(PyObject *v1, PyObject *v2) } } else { - BLI_assert(!"internal error"); + BLI_assert_msg(0, "internal error"); } PyErr_Format(PyExc_TypeError, diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 4e1b31b6371..595d03b533b 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -110,7 +110,7 @@ short euler_order_from_string(const char *str, const char *error_prefix) return -1; } -/* note: BaseMath_ReadCallback must be called beforehand */ +/* NOTE: BaseMath_ReadCallback must be called beforehand. */ static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits) { PyObject *ret; diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 3dde0177648..8b8130f3cc2 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -263,7 +263,7 @@ Mathutils_Callback mathutils_matrix_col_cb = { /* ---------------------------------------------------------------------------- * matrix row callbacks * this is so you can do matrix.translation = val - * note, this is _exactly like matrix.col except the 4th component is always omitted */ + * NOTE: this is _exactly like matrix.col except the 4th component is always omitted. */ uchar mathutils_matrix_translation_cb_index = -1; @@ -1938,7 +1938,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) return NULL; } - /* TODO, different sized matrix */ + /* TODO: different sized matrix. */ if (self->num_col == 4 && self->num_row == 4) { #ifdef MATH_STANDALONE blend_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac); @@ -2998,7 +2998,7 @@ static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNU return -1; } - if ((mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation")) == -1) { + if (mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation") == -1) { return -1; } @@ -3614,7 +3614,7 @@ static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item, } return Matrix_ass_item_col(matrix_user, i, value); } - /* TODO, slice */ + /* TODO: slice. */ PyErr_Format( PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name); diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 88aa1f146e2..77a30dcd447 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -42,7 +42,7 @@ static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args); /* -----------------------------METHODS------------------------------ */ -/* note: BaseMath_ReadCallback must be called beforehand */ +/* NOTE: BaseMath_ReadCallback must be called beforehand. */ static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits) { PyObject *ret; diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index a9cb125f715..c2223b023ad 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -149,7 +149,7 @@ static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args) } PyDoc_STRVAR(C_Vector_Range_doc, - ".. classmethod:: Range(start=0, stop, step=1)\n" + ".. classmethod:: Range(start, stop, step=1)\n" "\n" " Create a filled with a range of values.\n" "\n" @@ -628,7 +628,7 @@ PyDoc_STRVAR(Vector_to_tuple_doc, " :type precision: int\n" " :return: the values of the vector rounded by *precision*\n" " :rtype: tuple\n"); -/* note: BaseMath_ReadCallback must be called beforehand */ +/* NOTE: BaseMath_ReadCallback must be called beforehand. */ static PyObject *Vector_to_tuple_ex(VectorObject *self, int ndigits) { PyObject *ret; @@ -2553,7 +2553,7 @@ static PyGetSetDef Vector_getseters[] = { NULL}, {"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL}, - /* autogenerated swizzle attrs, see Python script above */ + /* Auto-generated swizzle attributes, see Python script above. */ {"xx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(0, 0)}, {"xxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 0)}, {"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 0)}, @@ -3019,8 +3019,7 @@ static struct PyMethodDef Vector_methods[] = { }; /** - * Note: - * #Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing + * NOTE: #Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing * but this means for eg that (vec * mat) and (mat * vec) * both get sent to Vector_mul and it needs to sort out the order */ diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c index 80919e014d5..588d3753eab 100644 --- a/source/blender/python/mathutils/mathutils_bvhtree.c +++ b/source/blender/python/mathutils/mathutils_bvhtree.c @@ -1109,7 +1109,7 @@ PyDoc_STRVAR(C_BVHTree_FromObject_doc, " :type cage: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC); static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs) { - /* note, options here match 'bpy_bmesh_from_object' */ + /* NOTE: options here match #bpy_bmesh_from_object. */ const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", NULL}; PyObject *py_ob, *py_depsgraph; diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 3b1a6524ed9..88b3bddddf6 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -1102,7 +1102,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a return NULL; } - /* note, this could be refactored into plain C easy - py bits are noted */ + /* NOTE: this could be refactored into plain C easy - py bits are noted. */ struct PointsInPlanes_UserData user_data = { .py_verts = PyList_New(0), diff --git a/source/blender/render/RE_texture.h b/source/blender/render/RE_texture.h index b394cfeee75..39d773777ab 100644 --- a/source/blender/render/RE_texture.h +++ b/source/blender/render/RE_texture.h @@ -79,7 +79,7 @@ void RE_point_density_fix_linking(void); /* texture_procedural.c */ /* Texture evaluation result. - * Note; tr tg tb ta has to remain in this order for array access. */ + * NOTE: tr tg tb ta has to remain in this order for array access. */ typedef struct TexResult { float tin, tr, tg, tb, ta; int talpha; diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c index 340a35eac15..d5653f87c2b 100644 --- a/source/blender/render/intern/bake.c +++ b/source/blender/render/intern/bake.c @@ -340,10 +340,10 @@ static bool cast_ray_highpoly(BVHTreeFromMesh *treeData, float co_high[3], dir_high[3]; hits[i].index = -1; - /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */ + /* TODO: we should use FLT_MAX here, but sweep-sphere code isn't prepared for that. */ hits[i].dist = BVH_RAYCAST_DIST_MAX; - /* transform the ray from the world space to the highpoly space */ + /* Transform the ray from the world space to the `highpoly` space. */ mul_v3_m4v3(co_high, highpoly[i].imat, co); /* rotates */ @@ -550,15 +550,15 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, Mesh **me_highpoly; BVHTreeFromMesh *treeData; - /* Note: all coordinates are in local space */ + /* NOTE: all coordinates are in local space. */ TriTessFace *tris_low = NULL; TriTessFace *tris_cage = NULL; TriTessFace **tris_high; - /* assume all lowpoly tessfaces can be quads */ + /* Assume all low-poly tessfaces can be quads. */ tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array"); - /* assume all highpoly tessfaces are triangles */ + /* Assume all high-poly tessfaces are triangles. */ me_highpoly = MEM_mallocN(sizeof(Mesh *) * tot_highpoly, "Highpoly Derived Meshes"); treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees"); @@ -583,7 +583,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, BKE_mesh_runtime_looptri_ensure(me_highpoly[i]); if (me_highpoly[i]->runtime.looptris.len != 0) { - /* Create a bvh-tree for each highpoly object */ + /* Create a BVH-tree for each `highpoly` object. */ BKE_bvhtree_from_mesh_get(&treeData[i], me_highpoly[i], BVHTREE_FROM_LOOPTRI, 2); if (treeData[i].tree == NULL) { @@ -752,10 +752,10 @@ void RE_bake_pixels_populate(Mesh *me, for (int a = 0; a < 3; a++) { const float *uv = mloopuv[lt->tri[a]].uv; - /* Note, workaround for pixel aligned UVs which are common and can screw up our + /* NOTE(campbell): workaround for pixel aligned UVs which are common and can screw up our * intersection tests where a pixel gets in between 2 faces or the middle of a quad, * camera aligned quads also have this problem but they are less common. - * Add a small offset to the UVs, fixes bug T18685 - Campbell */ + * Add a small offset to the UVs, fixes bug T18685. */ vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f); vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f); } diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c index db2458a636b..657cd1f606b 100644 --- a/source/blender/render/intern/engine.c +++ b/source/blender/render/intern/engine.c @@ -124,7 +124,7 @@ bool RE_engine_is_external(const Render *re) bool RE_engine_is_opengl(RenderEngineType *render_type) { - /* TODO refine? Can we have ogl render engine without ogl render pipeline? */ + /* TODO: refine? Can we have ogl render engine without ogl render pipeline? */ return (render_type->draw_engine != NULL) && DRW_engine_render_support(render_type->draw_engine); } @@ -310,7 +310,7 @@ RenderResult *RE_engine_begin_result( result = render_result_new(re, &disprect, RR_USE_MEM, layername, viewname); - /* todo: make this thread safe */ + /* TODO: make this thread safe. */ /* can be NULL if we CLAMP the width or height to 0 */ if (result) { @@ -679,7 +679,7 @@ static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer) DRW_render_context_enable(engine->re); } - DEG_evaluate_on_framechange(depsgraph, CFRA); + DEG_evaluate_on_framechange(depsgraph, BKE_scene_frame_get(scene)); if (use_gpu_context) { DRW_render_context_disable(engine->re); diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index d3ea27c6bb0..6329901b4ce 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -1464,7 +1464,7 @@ static void do_render_full_pipeline(Render *re) /* in this case external render overrides all */ } else if (RE_seq_render_active(re->scene, &re->r)) { - /* note: do_render_sequencer() frees rect32 when sequencer returns float images */ + /* NOTE: do_render_sequencer() frees rect32 when sequencer returns float images. */ if (!re->test_break(re->tbh)) { do_render_sequencer(re); render_seq = true; @@ -1828,7 +1828,7 @@ void RE_SetReports(Render *re, ReportList *reports) static void render_update_depsgraph(Render *re) { Scene *scene = re->scene; - DEG_evaluate_on_framechange(re->pipeline_depsgraph, CFRA); + DEG_evaluate_on_framechange(re->pipeline_depsgraph, BKE_scene_frame_get(scene)); BKE_scene_update_sound(re->pipeline_depsgraph, re->main); } @@ -2410,7 +2410,7 @@ void RE_RenderAnim(Render *re, * -sergey- */ { - float ctime = BKE_scene_frame_get(scene); + float ctime = BKE_scene_ctime_get(scene); AnimData *adt = BKE_animdata_from_id(&scene->id); const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( re->pipeline_depsgraph, ctime); @@ -2419,7 +2419,7 @@ void RE_RenderAnim(Render *re, render_update_depsgraph(re); - /* only border now, todo: camera lens. (ton) */ + /* Only border now, TODO(ton): camera lens. */ render_init_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0); if (nfra != scene->r.cfra) { @@ -2612,7 +2612,7 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) } } -/* note; repeated win/disprect calc... solve that nicer, also in compo */ +/* NOTE: repeated win/disprect calc... solve that nicer, also in compo. */ /* only the temp file! */ bool RE_ReadRenderResult(Scene *scene, Scene *scenode) diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index 70bd4f92512..53252cdb42f 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -473,15 +473,15 @@ RenderResult *render_result_new( render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA"); } - /* note, this has to be in sync with scene.c */ + /* NOTE: this has to be in sync with `scene.c`. */ rl->layflag = 0x7FFF; /* solid ztra halo strand */ rl->passflag = SCE_PASS_COMBINED; re->active_view_layer = 0; } - /* border render; calculate offset for use in compositor. compo is centralized coords */ - /* XXX obsolete? I now use it for drawing border render offset (ton) */ + /* Border render; calculate offset for use in compositor. compo is centralized coords. */ + /* XXX(ton): obsolete? I now use it for drawing border render offset. */ rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2); rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2); @@ -1016,7 +1016,7 @@ bool RE_WriteRenderResult(ReportList *reports, IMB_exr_write_channels(exrhandle); } else { - /* TODO, get the error from openexr's exception */ + /* TODO: get the error from openexr's exception. */ BKE_reportf( reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno)); } diff --git a/source/blender/render/intern/render_types.h b/source/blender/render/intern/render_types.h index 9f399971049..50b684beba9 100644 --- a/source/blender/render/intern/render_types.h +++ b/source/blender/render/intern/render_types.h @@ -153,7 +153,7 @@ struct Render { void **movie_ctx_arr; char viewname[MAX_NAME]; - /* TODO replace by a whole draw manager. */ + /* TODO: replace by a whole draw manager. */ void *gl_context; void *gpu_context; }; diff --git a/source/blender/render/intern/texture_image.c b/source/blender/render/intern/texture_image.c index 9f6980a5b0a..c4ee16a0ecc 100644 --- a/source/blender/render/intern/texture_image.c +++ b/source/blender/render/intern/texture_image.c @@ -634,11 +634,11 @@ static void boxsample(ImBuf *ibuf, * If variable 'imaprepeat' has been set, the * clipped-away parts are sampled as well. */ - /* note: actually minx etc isn't in the proper range... - * this due to filter size and offset vectors for bump */ - /* note: talpha must be initialized */ - /* note: even when 'imaprepeat' is set, this can only repeat once in any direction. - * the point which min/max is derived from is assumed to be wrapped */ + /* NOTE: actually minx etc isn't in the proper range... + * this due to filter size and offset vectors for bump. */ + /* NOTE: talpha must be initialized. */ + /* NOTE: even when 'imaprepeat' is set, this can only repeat once in any direction. + * the point which min/max is derived from is assumed to be wrapped. */ TexResult texr; rctf *rf, stack[8]; float opp, tot, alphaclip = 1.0; diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index c0ff00d4f59..31d5bf67f28 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -169,7 +169,7 @@ static void pointdensity_cache_psys( ParticleCacheKey *cache; ParticleSimulationData sim = {NULL}; ParticleData *pa = NULL; - float cfra = BKE_scene_frame_get(scene); + float cfra = BKE_scene_ctime_get(scene); int i /*, Childexists*/ /* UNUSED */; int total_particles; int data_used; @@ -347,9 +347,9 @@ static void pointdensity_cache_vertex_weight(PointDensity *pd, if (!mdef) { return; } - mdef_index = BKE_object_defgroup_name_index(ob, pd->vertex_attribute_name); + mdef_index = BKE_id_defgroup_name_index(&mesh->id, pd->vertex_attribute_name); if (mdef_index < 0) { - mdef_index = ob->actdef - 1; + mdef_index = BKE_object_defgroup_active_index_get(ob) - 1; } if (mdef_index < 0) { return; @@ -782,7 +782,7 @@ static void particle_system_minmax(Depsgraph *depsgraph, float max[3]) { const float size[3] = {radius, radius, radius}; - const float cfra = BKE_scene_frame_get(scene); + const float cfra = BKE_scene_ctime_get(scene); ParticleSettings *part = psys->part; ParticleSimulationData sim = {NULL}; ParticleData *pa = NULL; diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt index 9340cfbf03d..e324bc8b407 100644 --- a/source/blender/sequencer/CMakeLists.txt +++ b/source/blender/sequencer/CMakeLists.txt @@ -77,9 +77,9 @@ set(SRC intern/proxy_job.c intern/render.c intern/render.h + intern/sequence_lookup.c intern/sequencer.c intern/sequencer.h - intern/sequence_lookup.c intern/sound.c intern/strip_add.c intern/strip_edit.c diff --git a/source/blender/sequencer/SEQ_clipboard.h b/source/blender/sequencer/SEQ_clipboard.h index 4b2bf69a8ac..ea7f01e6ae3 100644 --- a/source/blender/sequencer/SEQ_clipboard.h +++ b/source/blender/sequencer/SEQ_clipboard.h @@ -29,12 +29,16 @@ extern "C" { struct ListBase; struct Main; +struct Scene; +struct Sequence; extern struct ListBase seqbase_clipboard; extern int seqbase_clipboard_frame; void SEQ_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase); void SEQ_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); void SEQ_clipboard_free(void); +void SEQ_clipboard_active_seq_name_store(struct Scene *scene); +bool SEQ_clipboard_pasted_seq_was_active(struct Sequence *pasted_seq); #ifdef __cplusplus } diff --git a/source/blender/sequencer/SEQ_iterator.h b/source/blender/sequencer/SEQ_iterator.h index eab2277bbe3..e4c9f20f736 100644 --- a/source/blender/sequencer/SEQ_iterator.h +++ b/source/blender/sequencer/SEQ_iterator.h @@ -30,9 +30,9 @@ extern "C" { #include "BLI_ghash.h" struct Editing; -struct Sequence; struct GSet; struct GSetIterator; +struct Sequence; #define SEQ_ITERATOR_FOREACH(var, collection) \ for (SeqIterator iter = {{{NULL}}}; \ @@ -70,7 +70,7 @@ bool SEQ_iterator_ensure(SeqCollection *collection, struct Sequence **r_seq); struct Sequence *SEQ_iterator_yield(SeqIterator *iterator); -SeqCollection *SEQ_collection_create(void); +SeqCollection *SEQ_collection_create(const char *name); uint SEQ_collection_len(const SeqCollection *collection); bool SEQ_collection_append_strip(struct Sequence *seq, SeqCollection *data); bool SEQ_collection_remove_strip(struct Sequence *seq, SeqCollection *data); diff --git a/source/blender/sequencer/SEQ_proxy.h b/source/blender/sequencer/SEQ_proxy.h index b06adef2802..7bfe932ff1c 100644 --- a/source/blender/sequencer/SEQ_proxy.h +++ b/source/blender/sequencer/SEQ_proxy.h @@ -34,8 +34,8 @@ struct ListBase; struct Main; struct Scene; struct SeqIndexBuildContext; -struct Sequence; struct SeqRenderData; +struct Sequence; bool SEQ_proxy_rebuild_context(struct Main *bmain, struct Depsgraph *depsgraph, diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index 706f4064bf3..f4338d13c8f 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -32,8 +32,8 @@ extern "C" { struct Editing; struct Scene; struct Sequence; -struct SequencerToolSettings; struct SequenceLookup; +struct SequencerToolSettings; /* RNA enums, just to be more readable */ enum { diff --git a/source/blender/sequencer/SEQ_time.h b/source/blender/sequencer/SEQ_time.h index 593a8fe7bf2..732e9bb985a 100644 --- a/source/blender/sequencer/SEQ_time.h +++ b/source/blender/sequencer/SEQ_time.h @@ -44,7 +44,6 @@ int SEQ_time_find_next_prev_edit(struct Scene *scene, const bool do_unselected); void SEQ_time_update_sequence(struct Scene *scene, struct Sequence *seq); void SEQ_time_update_sequence_bounds(struct Scene *scene, struct Sequence *seq); -int SEQ_time_cmp_time_startdisp(const void *a, const void *b); bool SEQ_time_strip_intersects_frame(const struct Sequence *seq, const int timeline_frame); void SEQ_time_update_meta_strip_range(struct Scene *scene, struct Sequence *seq_meta); diff --git a/source/blender/sequencer/SEQ_transform.h b/source/blender/sequencer/SEQ_transform.h index 837a2de5742..9ff827333be 100644 --- a/source/blender/sequencer/SEQ_transform.h +++ b/source/blender/sequencer/SEQ_transform.h @@ -29,8 +29,8 @@ extern "C" { struct ListBase; struct Scene; -struct Sequence; struct SeqCollection; +struct Sequence; int SEQ_transform_get_left_handle_frame(struct Sequence *seq); int SEQ_transform_get_right_handle_frame(struct Sequence *seq); diff --git a/source/blender/sequencer/intern/clipboard.c b/source/blender/sequencer/intern/clipboard.c index e3f82dd4bb0..9e702a4e60b 100644 --- a/source/blender/sequencer/intern/clipboard.c +++ b/source/blender/sequencer/intern/clipboard.c @@ -24,6 +24,8 @@ * \ingroup bke */ +#include <string.h> + #include "MEM_guardedalloc.h" #include "DNA_scene_types.h" @@ -31,6 +33,7 @@ #include "DNA_sound_types.h" #include "BLI_listbase.h" +#include "BLI_string.h" #include "BKE_main.h" #include "BKE_movieclip.h" @@ -38,6 +41,7 @@ #include "BKE_sound.h" #include "SEQ_clipboard.h" +#include "SEQ_select.h" #include "sequencer.h" @@ -55,6 +59,7 @@ ListBase seqbase_clipboard; int seqbase_clipboard_frame; +static char seq_clipboard_active_seq_name[SEQ_NAME_MAXSTR]; void seq_clipboard_pointers_free(struct ListBase *seqbase); @@ -177,3 +182,26 @@ void SEQ_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) SEQ_clipboard_pointers_restore(&seq->seqbase, bmain); } } + +void SEQ_clipboard_active_seq_name_store(Scene *scene) +{ + Sequence *active_seq = SEQ_select_active_get(scene); + if (active_seq != NULL) { + STRNCPY(seq_clipboard_active_seq_name, active_seq->name); + } + else { + seq_clipboard_active_seq_name[0] = '\0'; + } +} + +/** + * Check if strip was active when it was copied. User should restrict this check to pasted strips + * before ensuring original name, because strip name comparison is used to check. + * + * \param pasted_seq: Strip that is pasted(duplicated) from clipboard + * \return true if strip was active, false otherwise + */ +bool SEQ_clipboard_pasted_seq_was_active(Sequence *pasted_seq) +{ + return STREQ(pasted_seq->name, seq_clipboard_active_seq_name); +} diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index 1f518a69395..0a8be3b33ae 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -3187,8 +3187,8 @@ void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force) return; } - /* XXX - new in 2.5x. should we use the animation system this way? - * The fcurve is needed because many frames need evaluating at once - campbell */ + /* XXX(campbell): new in 2.5x. should we use the animation system this way? + * The fcurve is needed because many frames need evaluating at once. */ fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL); if (!v->frameMap || v->length != seq->len) { if (v->frameMap) { diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index a6e4b6ea7ed..604c9900355 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -521,7 +521,7 @@ static bool seq_disk_cache_read_header(FILE *file, DiskCacheHeader *header) BLI_fseek(file, 0LL, SEEK_SET); const size_t num_items_read = fread(header, sizeof(*header), 1, file); if (num_items_read < 1) { - BLI_assert(!"unable to read disk cache header"); + BLI_assert_msg(0, "unable to read disk cache header"); perror("unable to read disk cache header"); return false; } diff --git a/source/blender/sequencer/intern/iterator.c b/source/blender/sequencer/intern/iterator.c index 0754d9b38ed..20a2ee3b183 100644 --- a/source/blender/sequencer/intern/iterator.c +++ b/source/blender/sequencer/intern/iterator.c @@ -106,9 +106,9 @@ void SEQ_collection_free(SeqCollection *collection) * * \return empty strip collection. */ -SeqCollection *SEQ_collection_create(void) +SeqCollection *SEQ_collection_create(const char *name) { - SeqCollection *collection = MEM_callocN(sizeof(SeqCollection), "SeqCollection"); + SeqCollection *collection = MEM_callocN(sizeof(SeqCollection), name); collection->set = BLI_gset_new( BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "SeqCollection GSet"); return collection; @@ -136,7 +136,7 @@ SeqCollection *SEQ_query_by_reference(Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection)) { - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); seq_query_func(seq_reference, seqbase, collection); return collection; } @@ -223,7 +223,7 @@ void SEQ_collection_expand(ListBase *seqbase, */ SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase) { - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { if (seq->type == SEQ_TYPE_META) { SEQ_collection_merge(collection, SEQ_query_all_strips_recursive(&seq->seqbase)); @@ -241,7 +241,7 @@ SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase) */ SeqCollection *SEQ_query_all_strips(ListBase *seqbase) { - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { SEQ_collection_append_strip(seq, collection); } @@ -256,7 +256,7 @@ SeqCollection *SEQ_query_all_strips(ListBase *seqbase) */ SeqCollection *SEQ_query_selected_strips(ListBase *seqbase) { - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { if ((seq->flag & SELECT) == 0) { continue; diff --git a/source/blender/sequencer/intern/modifier.c b/source/blender/sequencer/intern/modifier.c index 75c7d599be5..07d09f4ae17 100644 --- a/source/blender/sequencer/intern/modifier.c +++ b/source/blender/sequencer/intern/modifier.c @@ -262,7 +262,7 @@ static StripColorBalance calc_cb(StripColorBalance *cb_) return cb; } -/* note: lift is actually 2-lift */ +/* NOTE: lift is actually 2-lift. */ MINLINE float color_balance_fl( float in, const float lift, const float gain, const float gamma, const float mul) { diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 7360d525ce3..aba84743621 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -308,7 +308,7 @@ static bool must_render_strip(const Sequence *seq, SeqCollection *strips_at_time static SeqCollection *query_strips_at_frame(ListBase *seqbase, const int timeline_frame) { - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { if (SEQ_time_strip_intersects_frame(seq, timeline_frame)) { @@ -370,7 +370,7 @@ int seq_get_shown_sequences(ListBase *seqbase, const int strip_count = BLI_gset_len(collection->set); if (strip_count > MAXSEQ) { - BLI_assert(!"Too many strips, this shouldn't happen"); + BLI_assert_msg(0, "Too many strips, this shouldn't happen"); return 0; } @@ -1260,7 +1260,7 @@ ImBuf *seq_render_mask(const SeqRenderData *context, float frame_index, bool make_float) { - /* TODO - add option to rasterize to alpha imbuf? */ + /* TODO: add option to rasterize to alpha imbuf? */ ImBuf *ibuf = NULL; float *maskbuf; int i; diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 7907b11989c..7dc19cf39a6 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -625,7 +625,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); } -/* XXX - hackish function needed for transforming strips! TODO - have some better solution */ +/* XXX: hackish function needed for transforming strips! TODO: have some better solution. */ void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs) { char str[SEQ_RNAPATH_MAXSTR]; @@ -693,7 +693,7 @@ void SEQ_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) BLI_movelisttolist(&scene->adt->action->curves, &lb); } -/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */ +/* XXX: hackish function needed to remove all fcurves belonging to a sequencer strip. */ static void seq_free_animdata(Scene *scene, Sequence *seq) { char str[SEQ_RNAPATH_MAXSTR]; diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index 142991eeacf..dab5593be37 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -597,12 +597,12 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL return seq; } -/* note: caller should run SEQ_time_update_sequence(scene, seq) after */ +/* NOTE: caller should run SEQ_time_update_sequence(scene, seq) after. */ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range) { char path[FILE_MAX]; int prev_startdisp = 0, prev_enddisp = 0; - /* note: don't rename the strip, will break animation curves */ + /* NOTE: don't rename the strip, will break animation curves. */ if (ELEM(seq->type, SEQ_TYPE_MOVIE, diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index 3e6eb74fcb3..0dc8dfa10d7 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -255,7 +255,7 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene, return false; } - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); SEQ_collection_append_strip(src_seq, collection); SEQ_collection_expand(seqbase, collection, SEQ_query_strip_effect_chain); @@ -396,7 +396,7 @@ Sequence *SEQ_edit_strip_split(Main *bmain, return NULL; } - SeqCollection *collection = SEQ_collection_create(); + SeqCollection *collection = SEQ_collection_create(__func__); SEQ_collection_append_strip(seq, collection); SEQ_collection_expand(seqbase, collection, SEQ_query_strip_effect_chain); @@ -407,6 +407,8 @@ Sequence *SEQ_edit_strip_split(Main *bmain, BLI_addtail(&left_strips, seq); } + SEQ_collection_free(collection); + /* Sort list, so that no strip can depend on next strip in list. * This is important for SEQ_time_update_sequence functionality. */ SEQ_sort(&left_strips); diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c index e5eb0b3f00f..20e2421ea88 100644 --- a/source/blender/sequencer/intern/strip_time.c +++ b/source/blender/sequencer/intern/strip_time.c @@ -257,15 +257,6 @@ void SEQ_time_update_sequence(Scene *scene, Sequence *seq) } } -/** Comparison function suitable to be used with BLI_listbase_sort()... */ -int SEQ_time_cmp_time_startdisp(const void *a, const void *b) -{ - const Sequence *seq_a = a; - const Sequence *seq_b = b; - - return (seq_a->startdisp > seq_b->startdisp); -} - int SEQ_time_find_next_prev_edit(Scene *scene, int timeline_frame, const short side, @@ -471,7 +462,7 @@ void seq_time_gap_info_get(const Scene *scene, /** * Test if strip intersects with timeline frame. - * Note: This checks if strip would be rendered at this frame. For rendering it is assumed, that + * NOTE: This checks if strip would be rendered at this frame. For rendering it is assumed, that * timeline frame has width of 1 frame and therefore ends at timeline_frame + 1 * * \param seq: Sequence to be checked diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c index 20cbe933b2f..b7989349ebe 100644 --- a/source/blender/sequencer/intern/strip_transform.c +++ b/source/blender/sequencer/intern/strip_transform.c @@ -149,7 +149,7 @@ void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag) SEQ_transform_set_left_handle_frame(seq, seq_tx_get_end(seq) - 1); } - /* doesn't work now - TODO */ + /* TODO: This doesn't work at the moment. */ #if 0 if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) { int ofs; @@ -271,7 +271,7 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep, test->machine += channel_delta; SEQ_time_update_sequence( evil_scene, - test); // XXX - I don't think this is needed since were only moving vertically, Campbell. + test); // XXX: I don't think this is needed since were only moving vertically, Campbell. } if ((test->machine < 1) || (test->machine > MAXSEQ)) { diff --git a/source/blender/shader_fx/intern/FX_shader_flip.c b/source/blender/shader_fx/intern/FX_shader_flip.c index b6a36378f7e..048ff3deba1 100644 --- a/source/blender/shader_fx/intern/FX_shader_flip.c +++ b/source/blender/shader_fx/intern/FX_shader_flip.c @@ -65,8 +65,8 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); row = uiLayoutRowWithHeading(layout, true, IFACE_("Axis")); - uiItemR(row, ptr, "flip_horizontal", toggles_flag, NULL, ICON_NONE); - uiItemR(row, ptr, "flip_vertical", toggles_flag, NULL, ICON_NONE); + uiItemR(row, ptr, "use_flip_x", toggles_flag, NULL, ICON_NONE); + uiItemR(row, ptr, "use_flip_y", toggles_flag, NULL, ICON_NONE); shaderfx_panel_end(layout, ptr); } diff --git a/source/blender/simulation/SIM_mass_spring.h b/source/blender/simulation/SIM_mass_spring.h index 43de8b155cf..b3299258209 100644 --- a/source/blender/simulation/SIM_mass_spring.h +++ b/source/blender/simulation/SIM_mass_spring.h @@ -45,6 +45,8 @@ void SIM_mass_spring_solver_free(struct Implicit_Data *id); int SIM_mass_spring_solver_numvert(struct Implicit_Data *id); int SIM_cloth_solver_init(struct Object *ob, struct ClothModifierData *clmd); +void SIM_mass_spring_set_implicit_vertex_mass(struct Implicit_Data *data, int index, float mass); + void SIM_cloth_solver_free(struct ClothModifierData *clmd); int SIM_cloth_solve(struct Depsgraph *depsgraph, struct Object *ob, diff --git a/source/blender/simulation/intern/ConstrainedConjugateGradient.h b/source/blender/simulation/intern/ConstrainedConjugateGradient.h index 11dc3ebe91b..c5a2827a09f 100644 --- a/source/blender/simulation/intern/ConstrainedConjugateGradient.h +++ b/source/blender/simulation/intern/ConstrainedConjugateGradient.h @@ -68,7 +68,7 @@ EIGEN_DONT_INLINE void constrained_conjugate_gradient(const MatrixType &mat, RealScalar rhsNorm2 = (filter * rhs).squaredNorm(); if (rhsNorm2 == 0) { - /* XXX TODO set constrained result here */ + /* XXX TODO: set constrained result here. */ x.setZero(); iters = 0; tol_error = 0; diff --git a/source/blender/simulation/intern/SIM_mass_spring.cpp b/source/blender/simulation/intern/SIM_mass_spring.cpp index cf654ebff07..ca01120eecb 100644 --- a/source/blender/simulation/intern/SIM_mass_spring.cpp +++ b/source/blender/simulation/intern/SIM_mass_spring.cpp @@ -203,7 +203,7 @@ int SIM_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd) cloth->implicit = id = SIM_mass_spring_solver_create(cloth->mvert_num, nondiag); for (i = 0; i < cloth->mvert_num; i++) { - SIM_mass_spring_set_vertex_mass(id, i, verts[i].mass); + SIM_mass_spring_set_implicit_vertex_mass(id, i, verts[i].mass); } for (i = 0; i < cloth->mvert_num; i++) { @@ -213,6 +213,10 @@ int SIM_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd) return 1; } +void SIM_mass_spring_set_implicit_vertex_mass(Implicit_Data *data, int index, float mass){ + SIM_mass_spring_set_vertex_mass(data, index, mass); +} + void SIM_cloth_solver_free(ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; diff --git a/source/blender/simulation/intern/hair_volume.cpp b/source/blender/simulation/intern/hair_volume.cpp index d954d9b5fff..4966fa2510d 100644 --- a/source/blender/simulation/intern/hair_volume.cpp +++ b/source/blender/simulation/intern/hair_volume.cpp @@ -200,7 +200,7 @@ BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, } if (velocity_gradient) { - /* XXX TODO */ + /* XXX TODO: */ zero_m3(velocity_gradient); } } @@ -530,7 +530,7 @@ void SIM_hair_volume_add_segment(HairGrid *grid, const int stride2 = strides[axis2]; /* increment of secondary directions per step in the primary direction - * note: we always go in the positive direction along axis0, so the sign can be inverted + * NOTE: we always go in the positive direction along axis0, so the sign can be inverted */ const float inc1 = dir2[axis1] / dir2[axis0]; const float inc2 = dir2[axis2] / dir2[axis0]; @@ -800,7 +800,7 @@ bool SIM_hair_volume_solve_divergence(HairGrid *grid, vert->density, target_density, target_strength); /* B vector contains the finite difference approximation of the velocity divergence. - * Note: according to the discretized Navier-Stokes equation the rhs vector + * NOTE: according to the discretized Navier-Stokes equation the rhs vector * and resulting pressure gradient should be multiplied by the (inverse) density; * however, this is already included in the weighting of hair velocities on the grid! */ diff --git a/source/blender/simulation/intern/implicit_blender.c b/source/blender/simulation/intern/implicit_blender.c index 4c01fd3aee0..8aa3774a3f2 100644 --- a/source/blender/simulation/intern/implicit_blender.c +++ b/source/blender/simulation/intern/implicit_blender.c @@ -583,7 +583,7 @@ DO_INLINE void del_bfmatrix(fmatrix3x3 *matrix) /* copy big matrix */ DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from) { - /* TODO bounds checking */ + /* TODO: bounds checking. */ memcpy(to, from, sizeof(fmatrix3x3) * (from[0].vcount + from[0].scount)); } @@ -697,7 +697,7 @@ Implicit_Data *SIM_mass_spring_solver_create(int numverts, int numsprings) id->S = create_bfmatrix(numverts, 0); id->Pinv = create_bfmatrix(numverts, numsprings); id->P = create_bfmatrix(numverts, numsprings); - id->bigI = create_bfmatrix(numverts, numsprings); /* TODO 0 springs */ + id->bigI = create_bfmatrix(numverts, numsprings); /* TODO: 0 springs. */ id->M = create_bfmatrix(numverts, numsprings); id->X = create_lfvector(numverts); id->Xnew = create_lfvector(numverts); @@ -2112,7 +2112,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdx(Implicit_Data *data, int q, float dfdx[3][3]) { - const float delta = 0.00001f; /* TODO find a good heuristic for this */ + const float delta = 0.00001f; /* TODO: find a good heuristic for this. */ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3]; float f[3]; int a, b; @@ -2123,7 +2123,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdx(Implicit_Data *data, copy_m3_m3(dvec_neg, dvec_pos); negate_m3(dvec_neg); - /* XXX TODO offset targets to account for position dependency */ + /* XXX TODO: offset targets to account for position dependency. */ for (a = 0; a < 3; a++) { spring_hairbend_forces( @@ -2151,7 +2151,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdv(Implicit_Data *data, int q, float dfdv[3][3]) { - const float delta = 0.00001f; /* TODO find a good heuristic for this */ + const float delta = 0.00001f; /* TODO: find a good heuristic for this. */ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3]; float f[3]; int a, b; @@ -2162,7 +2162,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdv(Implicit_Data *data, copy_m3_m3(dvec_neg, dvec_pos); negate_m3(dvec_neg); - /* XXX TODO offset targets to account for position dependency */ + /* XXX TODO: offset targets to account for position dependency. */ for (a = 0; a < 3; a++) { spring_hairbend_forces( diff --git a/source/blender/simulation/intern/implicit_eigen.cpp b/source/blender/simulation/intern/implicit_eigen.cpp index 8eb227d38ab..aa9d5d1d34d 100644 --- a/source/blender/simulation/intern/implicit_eigen.cpp +++ b/source/blender/simulation/intern/implicit_eigen.cpp @@ -1223,7 +1223,7 @@ BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data, int q, float dfdx[3][3]) { - const float delta = 0.00001f; /* TODO find a good heuristic for this */ + const float delta = 0.00001f; /* TODO: find a good heuristic for this. */ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3]; float f[3]; int a, b; @@ -1234,7 +1234,7 @@ BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data, copy_m3_m3(dvec_neg, dvec_pos); negate_m3(dvec_neg); - /* XXX TODO offset targets to account for position dependency */ + /* XXX TODO: offset targets to account for position dependency. */ for (a = 0; a < 3; a++) { spring_angbend_forces( @@ -1262,7 +1262,7 @@ BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data, int q, float dfdv[3][3]) { - const float delta = 0.00001f; /* TODO find a good heuristic for this */ + const float delta = 0.00001f; /* TODO: find a good heuristic for this. */ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3]; float f[3]; int a, b; @@ -1273,7 +1273,7 @@ BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data, copy_m3_m3(dvec_neg, dvec_pos); negate_m3(dvec_neg); - /* XXX TODO offset targets to account for position dependency */ + /* XXX TODO: offset targets to account for position dependency. */ for (a = 0; a < 3; a++) { spring_angbend_forces( diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 183b22c9791..e513c49c11b 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -181,7 +181,7 @@ if(WITH_INPUT_NDOF) add_definitions(-DWITH_INPUT_NDOF) endif() -if(WIN32) +if(WIN32 OR APPLE) if(WITH_INPUT_IME) add_definitions(-DWITH_INPUT_IME) endif() diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 319683c8d8e..1c994707ca9 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -31,6 +31,7 @@ /* dna-savable wmStructs here */ #include "BLI_compiler_attrs.h" +#include "BLI_sys_types.h" #include "DNA_windowmanager_types.h" #include "WM_keymap.h" @@ -617,9 +618,14 @@ void WM_operator_type_modal_from_exec_for_object_edit_coords(struct wmOperatorTy void WM_uilisttype_init(void); struct uiListType *WM_uilisttype_find(const char *idname, bool quiet); bool WM_uilisttype_add(struct uiListType *ult); -void WM_uilisttype_freelink(struct uiListType *ult); +void WM_uilisttype_remove_ptr(struct Main *bmain, struct uiListType *ult); void WM_uilisttype_free(void); +void WM_uilisttype_to_full_list_id(const struct uiListType *ult, + const char *list_id, + char r_full_list_id[]); +const char *WM_uilisttype_list_id_get(const struct uiListType *ult, struct uiList *list); + /* wm_menu_type.c */ void WM_menutype_init(void); struct MenuType *WM_menutype_find(const char *idname, bool quiet); @@ -961,7 +967,7 @@ bool WM_xr_session_state_controller_pose_rotation_get(const wmXrData *xr, /* wm_xr_actions.c */ /* XR action functions to be called pre-XR session start. - * Note: The "destroy" functions can also be called post-session start. */ + * NOTE: The "destroy" functions can also be called post-session start. */ bool WM_xr_action_set_create(wmXrData *xr, const char *action_set_name); void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name); bool WM_xr_action_create(wmXrData *xr, @@ -1015,7 +1021,7 @@ bool WM_xr_action_state_get(const wmXrData *xr, bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, - const long long *duration, + const int64_t *duration, const float *frequency, const float *amplitude); void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index e83e36d7a9b..2b48a5f6648 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -339,7 +339,7 @@ typedef struct wmNotifier { #define ND_RENDER_OPTIONS (4 << 16) #define ND_NODES (5 << 16) #define ND_SEQUENCER (6 << 16) -/* Note: If an object was added, removed, merged/joined, ..., it is not enough to notify with +/* NOTE: If an object was added, removed, merged/joined, ..., it is not enough to notify with * this. This affects the layer so also send a layer change notifier (e.g. ND_LAYER_CONTENT)! */ #define ND_OB_ACTIVE (7 << 16) /* See comment on ND_OB_ACTIVE. */ @@ -439,6 +439,13 @@ typedef struct wmNotifier { #define ND_SPACE_FILE_PREVIEW (21 << 16) #define ND_SPACE_SPREADSHEET (22 << 16) +/* NC_ASSET */ +/* Denotes that the AssetList is done reading some previews. NOT that the preview generation of + * assets is done. */ +#define ND_ASSET_LIST (1 << 16) +#define ND_ASSET_LIST_PREVIEW (2 << 16) +#define ND_ASSET_LIST_READING (3 << 16) + /* subtype, 256 entries too */ #define NOTE_SUBTYPE 0x0000FF00 @@ -908,7 +915,7 @@ typedef enum wmDragFlags { WM_DRAG_FREE_DATA = 1, } wmDragFlags; -/* note: structs need not exported? */ +/* NOTE: structs need not exported? */ typedef struct wmDragID { struct wmDragID *next, *prev; diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h index 9a993e1f8d7..1fbbec7f949 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h @@ -107,7 +107,7 @@ typedef enum eWM_GizmoFlagGroupTypeFlag { /** Mark gizmo-group as being 3D */ WM_GIZMOGROUPTYPE_3D = (1 << 0), /** Scale gizmos as 3D object that respects zoom (otherwise zoom independent draw size). - * note: currently only for 3D views, 2D support needs adding. */ + * NOTE: currently only for 3D views, 2D support needs adding. */ WM_GIZMOGROUPTYPE_SCALE = (1 << 1), /** Gizmos can be depth culled with scene objects (covered by other geometry - TODO) */ WM_GIZMOGROUPTYPE_DEPTH_3D = (1 << 2), @@ -445,7 +445,7 @@ typedef struct wmGizmoGroupType { /** Only for convenient removal. */ struct wmKeyConfig *keyconf; - /* Note: currently gizmo-group instances don't store properties, + /* NOTE: currently gizmo-group instances don't store properties, * they're kept in the tool properties. */ /** RNA for properties. */ diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index 062731dfb3d..213a3c2e342 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -981,10 +981,10 @@ void WM_gizmomaptype_group_unlink(bContext *C, WM_gizmomaptype_group_free(gzgt_ref); } - /* TODO(campbell): Gizmos may share keymaps, for now don't + /* TODO(campbell): Gizmos may share key-maps, for now don't * remove however we could flag them as temporary/owned by the gizmo. */ #if 0 - /* Note, we may want to keep this keymap for editing */ + /* NOTE: we may want to keep this key-map for editing. */ WM_keymap_remove(gzgt->keyconf, gzgt->keymap); #endif diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c index 6ebeb5a76b6..6a793d52f74 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c @@ -162,7 +162,7 @@ void WM_gizmo_group_type_free_ptr(wmGizmoGroupType *gzgt) gizmogrouptype_free(gzgt); - /* XXX, TODO, update the world! */ + /* XXX, TODO: update the world! */ } bool WM_gizmo_group_type_free(const char *idname) diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 2ffa04bd8ae..6a328679c2e 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -264,7 +264,7 @@ bool WM_gizmomap_minmax(const wmGizmoMap *gzmap, } bool ok = false; - BLI_assert(!"TODO"); + BLI_assert_msg(0, "TODO"); return ok; } @@ -918,7 +918,7 @@ static bool wm_gizmomap_select_all_intern(bContext *C, wmGizmoMap *gzmap) * Select/Deselect all selectable gizmos in \a gzmap. * \return if selection has changed. * - * TODO select all by type + * TODO: select all by type. */ bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action) { diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 6dd3e4186c4..9657f8aa03c 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -168,7 +168,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id) win->eventstate = NULL; win->cursor_keymap_status = NULL; win->tweak = NULL; -#ifdef WIN32 +#if defined(WIN32) || defined(__APPLE__) win->ime_data = NULL; #endif @@ -516,7 +516,7 @@ void WM_check(bContext *C) } /* Case: fileread. */ - /* Note: this runs in background mode to set the screen context cb. */ + /* NOTE: this runs in background mode to set the screen context cb. */ if ((wm->initialized & WM_WINDOW_IS_INIT) == 0) { ED_screens_init(bmain, wm); wm->initialized |= WM_WINDOW_IS_INIT; diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index 11783ae3517..50d3a856cbe 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -124,14 +124,14 @@ static void window_set_custom_cursor( wmWindow *win, const uchar mask[16][2], const uchar bitmap[16][2], int hotx, int hoty) { GHOST_SetCustomCursorShape( - win->ghostwin, (GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask, 16, 16, hotx, hoty, true); + win->ghostwin, (uint8_t *)bitmap, (uint8_t *)mask, 16, 16, hotx, hoty, true); } static void window_set_custom_cursor_ex(wmWindow *win, BCursor *cursor) { GHOST_SetCustomCursorShape(win->ghostwin, - (GHOST_TUns8 *)cursor->bitmap, - (GHOST_TUns8 *)cursor->mask, + (uint8_t *)cursor->bitmap, + (uint8_t *)cursor->mask, 16, 16, cursor->hotx, @@ -163,7 +163,7 @@ void WM_cursor_set(wmWindow *win, int curs) win->cursor = curs; if (curs < 0 || curs >= WM_CURSOR_NUM) { - BLI_assert(!"Invalid cursor number"); + BLI_assert_msg(0, "Invalid cursor number"); return; } @@ -301,7 +301,7 @@ void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2]) static void wm_cursor_warp_relative(wmWindow *win, int x, int y) { - /* note: don't use wmEvent coords because of continuous grab T36409. */ + /* NOTE: don't use wmEvent coords because of continuous grab T36409. */ int cx, cy; wm_cursor_position_get(win, &cx, &cy); WM_cursor_warp(win, cx + x, cy + y); diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index e899cbb22b9..da40040ce56 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -144,7 +144,7 @@ wmDrag *WM_event_start_drag( wmWindowManager *wm = CTX_wm_manager(C); wmDrag *drag = MEM_callocN(sizeof(struct wmDrag), "new drag"); - /* keep track of future multitouch drag too, add a mousepointer id or so */ + /* Keep track of future multi-touch drag too, add a mouse-pointer id or so. */ /* if multiple drags are added, they're drawn as list */ BLI_addtail(&wm->drags, drag); @@ -321,7 +321,7 @@ void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent) return; } if (GS(drag_id->id->name) != GS(id->name)) { - BLI_assert(!"All dragged IDs must have the same type"); + BLI_assert_msg(0, "All dragged IDs must have the same type"); return; } } diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 0922aaaee53..f01e28f8822 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -457,6 +457,7 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_ GPUOffScreen *offscreen = GPU_offscreen_create( region->winx, region->winy, false, false, NULL); if (!offscreen) { + WM_report(RPT_ERROR, "Region could not be drawn!"); return; } diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c index 905b0f7b128..e7603a02cff 100644 --- a/source/blender/windowmanager/intern/wm_event_query.c +++ b/source/blender/windowmanager/intern/wm_event_query.c @@ -484,7 +484,10 @@ int WM_event_absolute_delta_y(const struct wmEvent *event) * \{ */ #ifdef WITH_INPUT_IME -/* most os using ctrl/oskey + space to switch ime, avoid added space */ +/** + * Most OS's use `Ctrl+Space` / `OsKey+Space` to switch IME, + * so don't type in the space character. + */ bool WM_event_is_ime_switch(const struct wmEvent *event) { return event->val == KM_PRESS && event->type == EVT_SPACEKEY && diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index b82b3c1ff5d..5e29a22304c 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -61,6 +61,7 @@ #include "BLT_translation.h" +#include "ED_asset.h" #include "ED_fileselect.h" #include "ED_info.h" #include "ED_screen.h" @@ -129,7 +130,7 @@ wmEvent *wm_event_add_ex(wmWindow *win, BLI_addtail(&win->event_queue, event); } else { - /* Note: strictly speaking this breaks const-correctness, + /* NOTE: strictly speaking this breaks const-correctness, * however we're only changing 'next' member. */ BLI_insertlinkafter(&win->event_queue, (void *)event_to_add_after, event); } @@ -189,7 +190,7 @@ void wm_event_free(wmEvent *event) if (event->customdata) { if (event->customdatafree) { - /* Note: pointer to listbase struct elsewhere. */ + /* NOTE: pointer to listbase struct elsewhere. */ if (event->custom == EVT_DATA_DRAGDROP) { ListBase *lb = event->customdata; WM_drag_free_list(lb); @@ -326,6 +327,7 @@ void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id) } } } + ED_assetlist_storage_id_remap(old_id, new_id); wmWindowManager *wm = bmain->wm.first; if (wm && wm->message_bus) { @@ -627,7 +629,7 @@ void wm_event_do_notifiers(bContext *C) CTX_wm_window_set(C, NULL); } - /* Autorun warning */ + /* Auto-run warning. */ wm_test_autorun_warning(C); } @@ -915,7 +917,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca { if (G.background == 0 && caller_owns_reports == false) { /* popup */ if (op->reports->list.first) { - /* FIXME, temp setting window, see other call to UI_popup_menu_reports for why. */ + /* FIXME: temp setting window, see other call to #UI_popup_menu_reports for why. */ wmWindow *win_prev = CTX_wm_window(C); ScrArea *area_prev = CTX_wm_area(C); ARegion *region_prev = CTX_wm_region(C); @@ -1370,7 +1372,7 @@ static int wm_operator_invoke(bContext *C, CLOG_ERROR(WM_LOG_OPERATORS, "invalid operator call '%s'", op->idname); } - /* Note, if the report is given as an argument then assume the caller will deal with displaying + /* NOTE: if the report is given as an argument then assume the caller will deal with displaying * them currently Python only uses this. */ if (!(retval & OPERATOR_HANDLED) && (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED))) { /* Only show the report if the report list was not given in the function. */ @@ -2379,9 +2381,9 @@ static int wm_handler_fileselect_do(bContext *C, if (handler->op->reports->list.first) { - /* FIXME, temp setting window, this is really bad! + /* FIXME(campbell): temp setting window, this is really bad! * only have because lib linking errors need to be seen by users :( - * it can be removed without breaking anything but then no linking errors - campbell */ + * it can be removed without breaking anything but then no linking errors. */ wmWindow *win_prev = CTX_wm_window(C); ScrArea *area_prev = CTX_wm_area(C); ARegion *region_prev = CTX_wm_region(C); @@ -2393,7 +2395,7 @@ static int wm_handler_fileselect_do(bContext *C, BKE_report_print_level_set(handler->op->reports, RPT_WARNING); UI_popup_menu_reports(C, handler->op->reports); - /* XXX - copied from 'wm_operator_finished()' */ + /* XXX: copied from 'wm_operator_finished()'. */ /* add reports to the global list, otherwise they are not seen */ BLI_movelisttolist(&CTX_wm_reports(C)->list, &handler->op->reports->list); @@ -2796,7 +2798,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers /* Modal handlers can get removed in this loop, we keep the loop this way. * - * Note: check 'handlers->first' because in rare cases the handlers can be cleared + * NOTE: check 'handlers->first' because in rare cases the handlers can be cleared * by the event that's called, for eg: * * Calling a python script which changes the area.type, see T32232. */ @@ -3398,7 +3400,7 @@ void wm_event_do_handlers(bContext *C) wm_tweakevent_test(C, event, action); if ((action & WM_HANDLER_BREAK) == 0) { - /* Note: setting subwin active should be done here, after modal handlers have been done */ + /* NOTE: setting subwin active should be done here, after modal handlers have been done. */ if (event->type == MOUSEMOVE) { /* State variables in screen, cursors. * Also used in wm_draw.c, fails for modal handlers though. */ @@ -4011,7 +4013,7 @@ wmEventHandler_Dropbox *WM_event_add_dropbox_handler(ListBase *handlers, ListBas return handler; } -/* XXX solution works, still better check the real cause (ton) */ +/* XXX(ton): solution works, still better check the real cause. */ void WM_event_remove_area_handler(ListBase *handlers, void *area) { LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, handlers) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 6230b240d11..3633d3c07d3 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -844,7 +844,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) /* first try to append data from exotic file formats... */ /* it throws error box when file doesn't exist and returns -1 */ - /* note; it should set some error message somewhere... (ton) */ + /* NOTE(ton): it should set some error message somewhere. */ const int retval = wm_read_exotic(filepath); /* we didn't succeed, now try to read Blender file */ @@ -929,7 +929,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) } else { BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath); - BLI_assert(!"invalid 'retval'"); + BLI_assert_msg(0, "invalid 'retval'"); } if (success == false) { @@ -1606,7 +1606,7 @@ static bool wm_file_write(bContext *C, return ok; } - /* note: used to replace the file extension (to ensure '.blend'), + /* NOTE: used to replace the file extension (to ensure '.blend'), * no need to now because the operator ensures, * its handy for scripts to save to a predefined name without blender editing it */ @@ -1645,13 +1645,13 @@ static bool wm_file_write(bContext *C, ED_editors_flush_edits(bmain); - /* first time saving */ - /* XXX temp solution to solve bug, real fix coming (ton) */ + /* First time saving. */ + /* XXX(ton): temp solution to solve bug, real fix coming. */ if ((BKE_main_blendfile_path(bmain)[0] == '\0') && (use_save_as_copy == false)) { BLI_strncpy(bmain->name, filepath, sizeof(bmain->name)); } - /* XXX temp solution to solve bug, real fix coming (ton) */ + /* XXX(ton): temp solution to solve bug, real fix coming. */ bmain->recovered = 0; if (BLO_write_file(CTX_data_main(C), diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 94535427dac..9da901d6c4e 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -447,7 +447,7 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) #if 0 /* Allow view navigation??? */ - /* note, this gives issues: + /* NOTE: this gives issues: * 1) other modal ops run on top (box select), * 2) middle-mouse is used now 3) tablet/trackpad? */ else { diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 48ab76317b5..d7ea47fc625 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -109,6 +109,7 @@ #include "ED_anim_api.h" #include "ED_armature.h" +#include "ED_asset.h" #include "ED_gpencil.h" #include "ED_keyframes_edit.h" #include "ED_keyframing.h" @@ -226,7 +227,7 @@ void WM_init(bContext *C, int argc, const char **argv) { if (!G.background) { - wm_ghost_init(C); /* note: it assigns C to ghost! */ + wm_ghost_init(C); /* NOTE: it assigns C to ghost! */ wm_init_cursor_data(); BKE_sound_jack_sync_callback_set(sound_jack_sync_callback); } @@ -327,13 +328,13 @@ void WM_init(bContext *C, int argc, const char **argv) ED_spacemacros_init(); - /* note: there is a bug where python needs initializing before loading the + /* NOTE(campbell): there is a bug where python needs initializing before loading the * startup.blend because it may contain PyDrivers. It also needs to be after * initializing space types and other internal data. * * However can't redo this at the moment. Solution is to load python * before wm_homefile_read() or make py-drivers check if python is running. - * Will try fix when the crash can be repeated. - campbell. */ + * Will try fix when the crash can be repeated. */ #ifdef WITH_PYTHON BPY_python_start(C, argc, argv); @@ -376,7 +377,7 @@ void WM_init(bContext *C, int argc, const char **argv) { Main *bmain = CTX_data_main(C); - /* note, logic here is from wm_file_read_post, + /* NOTE: logic here is from wm_file_read_post, * call functions that depend on Python being initialized. */ /* normally 'wm_homefile_read' will do this, @@ -481,7 +482,7 @@ void WM_exit_ex(bContext *C, const bool do_python) /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ - /* note; same code copied in wm_files.c */ + /* NOTE: same code copied in `wm_files.c`. */ if (C && wm) { if (!G.background) { struct MemFile *undo_memfile = wm->undo_stack ? @@ -552,7 +553,6 @@ void WM_exit_ex(bContext *C, const bool do_python) wm_surfaces_free(); wm_dropbox_free(); WM_menutype_free(); - WM_uilisttype_free(); /* all non-screen and non-space stuff editors did, like editmode */ if (C) { @@ -571,6 +571,7 @@ void WM_exit_ex(bContext *C, const bool do_python) RE_engines_exit(); ED_preview_free_dbase(); /* frees a Main dbase, before BKE_blender_free! */ + ED_assetlist_storage_exit(); if (wm) { /* Before BKE_blender_free! - since the ListBases get freed there. */ @@ -607,6 +608,8 @@ void WM_exit_ex(bContext *C, const bool do_python) wm_gizmomaptypes_free(); wm_gizmogrouptype_free(); wm_gizmotype_free(); + /* Same for UI-list types. */ + WM_uilisttype_free(); BLF_exit(); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 69b3660038d..25bcf1967ea 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -135,7 +135,7 @@ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi) /* matches wm_keymap_item_properties_set but doesn't alloc new ptr */ WM_operator_properties_create_ptr(kmi->ptr, ot); /* 'kmi->ptr->data' NULL'd above, keep using existing properties. - * Note: the operators property types may have changed, + * NOTE: the operators property types may have changed, * we will need a more comprehensive sanitize function to support this properly. */ if (kmi->properties) { @@ -971,7 +971,7 @@ static const wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(const wmKeyMap *km } } else { - BLI_assert(!"called with non modal keymap"); + BLI_assert_msg(0, "called with non modal keymap"); } return NULL; diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index ba236988c1d..898671706d1 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -133,7 +133,7 @@ void WM_operator_properties_filesel(wmOperatorType *ot, } if (action == FILE_SAVE) { - /* note, this is only used to check if we should highlight the filename area red when the + /* NOTE: this is only used to check if we should highlight the filename area red when the * filepath is an existing file. */ prop = RNA_def_boolean(ot->srna, "check_existing", @@ -198,7 +198,7 @@ void WM_operator_properties_filesel(wmOperatorType *ot, ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - /* TODO asset only filter? */ + /* TODO: asset only filter? */ prop = RNA_def_int( ot->srna, diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a2d783afc32..576f15731a0 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -126,8 +126,8 @@ void WM_operator_py_idname(char *to, const char *from) if (sep) { int ofs = (sep - from); - /* note, we use ascii tolower instead of system tolower, because the - * latter depends on the locale, and can lead to idname mismatch */ + /* NOTE: we use ascii `tolower` instead of system `tolower`, because the + * latter depends on the locale, and can lead to `idname` mismatch. */ memcpy(to, from, sizeof(char) * ofs); BLI_str_tolower_ascii(to, ofs); @@ -604,6 +604,12 @@ void WM_operator_properties_create(PointerRNA *ptr, const char *opstring) * used for keymaps and macros */ void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring) { + IDProperty *tmp_properties = NULL; + /* Allow passing NULL for properties, just create the properties here then. */ + if (properties == NULL) { + properties = &tmp_properties; + } + if (*properties == NULL) { IDPropertyTemplate val = {0}; *properties = IDP_New(IDP_GROUP, &val, "wmOpItemProp"); @@ -745,7 +751,7 @@ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_ if (idp_src) { IDProperty *idp_dst = IDP_CopyProperty(idp_src); - /* note - in the future this may need to be done recursively, + /* NOTE: in the future this may need to be done recursively, * but for now RNA doesn't access nested operators */ idp_dst->flag |= IDP_FLAG_GHOST; @@ -1156,7 +1162,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFor RNA_property_string_get(op->ptr, prop, filepath); if (BKE_image_path_ensure_ext_from_imformat(filepath, im_format)) { RNA_property_string_set(op->ptr, prop, filepath); - /* note, we could check for and update 'filename' here, + /* NOTE: we could check for and update 'filename' here, * but so far nothing needs this. */ return true; } @@ -2361,7 +2367,7 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void strdrawlen = BLI_strlen_utf8(str); break; default: - tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* note, this is a dummy value */ + tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* NOTE: this is a dummy value. */ alpha = 0.75; break; } @@ -3202,7 +3208,7 @@ static void redraw_timer_step(bContext *C, int tot = (scene->r.efra - scene->r.sfra) + 1; while (tot--) { - /* todo, ability to escape! */ + /* TODO: ability to escape! */ scene->r.cfra++; if (scene->r.cfra > scene->r.efra) { scene->r.cfra = scene->r.sfra; diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 5300649a0cd..fa21dbcb4bb 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -220,7 +220,7 @@ static void playanim_window_get_size(int *r_width, int *r_height) static void playanim_gl_matrix(void) { /* unified matrix, note it affects offset for drawing */ - /* note! cannot use GPU_matrix_ortho_2d_set here because shader ignores. */ + /* NOTE: cannot use GPU_matrix_ortho_2d_set here because shader ignores. */ GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f); } @@ -1114,7 +1114,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) #ifdef WITH_AUDASPACE { PlayAnimPict *picture = picsbase.first; - /* TODO - store in ps direct? */ + /* TODO: store in ps direct? */ int i = 0; while (picture && picture != ps->picture) { @@ -1151,7 +1151,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) #ifdef WITH_AUDASPACE { PlayAnimPict *picture = picsbase.first; - /* TODO - store in ps direct? */ + /* TODO: store in ps direct? */ int i = 0; while (picture && picture != ps->picture) { i++; @@ -1357,7 +1357,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey) { GHOST_GLSettings glsettings = {0}; - GHOST_TUns32 scr_w, scr_h; + uint32_t scr_w, scr_h; GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h); @@ -1405,7 +1405,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) { struct ImBuf *ibuf = NULL; static char filepath[FILE_MAX]; /* abused to return dropped file path */ - GHOST_TUns32 maxwinx, maxwiny; + uint32_t maxwinx, maxwiny; int i; /* This was done to disambiguate the name for use under c++. */ int start_x = 0, start_y = 0; diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index ae726e73fe7..f5881a00998 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -112,7 +112,7 @@ static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf) const float distance = sqrt(u * u + v * v); /* Pointer offset to the alpha value of pixel. */ - /* Note, the left corner is flipped in the X-axis. */ + /* NOTE: the left corner is flipped in the X-axis. */ const int offset_l = 4 * (size - x - x - 1) + 3; const int offset_r = 4 * (ibuf->x - size) + 3; diff --git a/source/blender/windowmanager/intern/wm_uilist_type.c b/source/blender/windowmanager/intern/wm_uilist_type.c index 45c14c0bbe9..82ba4aa6e6f 100644 --- a/source/blender/windowmanager/intern/wm_uilist_type.c +++ b/source/blender/windowmanager/intern/wm_uilist_type.c @@ -21,16 +21,24 @@ */ #include <stdio.h> +#include <string.h> +#include "BLI_listbase.h" #include "BLI_sys_types.h" +#include "DNA_space_types.h" #include "DNA_windowmanager_types.h" #include "MEM_guardedalloc.h" +#include "UI_interface.h" + #include "BLI_ghash.h" +#include "BLI_listbase.h" +#include "BLI_string.h" #include "BLI_utildefines.h" +#include "BKE_main.h" #include "BKE_screen.h" #include "WM_api.h" @@ -60,8 +68,62 @@ bool WM_uilisttype_add(uiListType *ult) return 1; } -void WM_uilisttype_freelink(uiListType *ult) +static void wm_uilisttype_unlink_from_region(const uiListType *ult, ARegion *region) { + LISTBASE_FOREACH (uiList *, list, ®ion->ui_lists) { + if (list->type == ult) { + /* Don't delete the list, it's not just runtime data but stored in files. Freeing would make + * that data get lost. */ + list->type = NULL; + } + } +} + +static void wm_uilisttype_unlink_from_area(const uiListType *ult, ScrArea *area) +{ + LISTBASE_FOREACH (SpaceLink *, space_link, &area->spacedata) { + ListBase *regionbase = (space_link == area->spacedata.first) ? &area->regionbase : + &space_link->regionbase; + LISTBASE_FOREACH (ARegion *, region, regionbase) { + wm_uilisttype_unlink_from_region(ult, region); + } + } +} + +/** + * For all lists representing \a ult, clear their `uiListType` pointer. Use when a list-type is + * deleted, so that the UI doesn't keep references to it. + * + * This is a common pattern for unregistering (usually .py defined) types at runtime, e.g. see + * #WM_gizmomaptype_group_unlink(). + * Note that unlike in some other cases using this pattern, we don't actually free the lists with + * type \a ult, we just clear the reference to the type. That's because UI-Lists are written to + * files and we don't want them to get lost together with their (user visible) settings. + */ +static void wm_uilisttype_unlink(Main *bmain, const uiListType *ult) +{ + for (wmWindowManager *wm = bmain->wm.first; wm != NULL; wm = wm->id.next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + LISTBASE_FOREACH (ScrArea *, global_area, &win->global_areas.areabase) { + wm_uilisttype_unlink_from_area(ult, global_area); + } + } + } + + for (bScreen *screen = bmain->screens.first; screen != NULL; screen = screen->id.next) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + wm_uilisttype_unlink_from_area(ult, area); + } + + LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { + wm_uilisttype_unlink_from_region(ult, region); + } + } +} + +void WM_uilisttype_remove_ptr(Main *bmain, uiListType *ult) +{ + wm_uilisttype_unlink(bmain, ult); bool ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN); @@ -88,3 +150,34 @@ void WM_uilisttype_free(void) BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN); uilisttypes_hash = NULL; } + +/** + * The "full" list-ID is an internal name used for storing and identifying a list. It is built like + * this: + * "{uiListType.idname}_{list_id}", whereby "list_id" is an optional parameter passed to + * `UILayout.template_list()`. If it is not set, the full list-ID is just "{uiListType.idname}_". + * + * Note that whenever the Python API refers to the list-ID, it's the short, "non-full" one it + * passed to `UILayout.template_list()`. C code can query that through + * #WM_uilisttype_list_id_get(). + */ +void WM_uilisttype_to_full_list_id(const uiListType *ult, + const char *list_id, + char r_full_list_id[/*UI_MAX_NAME_STR*/]) +{ + /* We tag the list id with the list type... */ + BLI_snprintf(r_full_list_id, UI_MAX_NAME_STR, "%s_%s", ult->idname, list_id ? list_id : ""); +} + +/** + * Get the "non-full" list-ID, see #WM_uilisttype_to_full_list_id() for details. + * + * \note Assumes `uiList.list_id` was set using #WM_uilisttype_to_full_list_id()! + */ +const char *WM_uilisttype_list_id_get(const uiListType *ult, uiList *list) +{ + /* Some sanity check for the assumed behavior of #WM_uilisttype_to_full_list_id(). */ + BLI_assert((list->list_id + strlen(ult->idname))[0] == '_'); + /* +1 to skip the '_' */ + return list->list_id + strlen(ult->idname) + 1; +} diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 8f8577e2616..1b08b8dad92 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -462,7 +462,7 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) /* Informs GHOST of unsaved changes, to set window modified visual indicator (macOS) * and to give hint of unsaved changes for a user warning mechanism in case of OS application * terminate request (e.g. OS Shortcut Alt+F4, Command+Q, (...), or session end). */ - GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8)!wm->file_saved); + GHOST_SetWindowModifiedState(win->ghostwin, (bool)!wm->file_saved); } } @@ -1136,14 +1136,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr return 1; } if (!ghostwin) { - /* XXX - should be checked, why are we getting an event here, and */ - /* what is it? */ + /* XXX: should be checked, why are we getting an event here, and what is it? */ puts("<!> event has no window"); return 1; } if (!GHOST_ValidWindow(g_system, ghostwin)) { - /* XXX - should be checked, why are we getting an event here, and */ - /* what is it? */ + /* XXX: should be checked, why are we getting an event here, and what is it? */ puts("<!> event has invalid window"); return 1; } @@ -1724,7 +1722,7 @@ static char *wm_clipboard_text_get_ex(bool selection, int *r_len, bool firstline return NULL; } - char *buf = (char *)GHOST_getClipboard(selection); + char *buf = GHOST_getClipboard(selection); if (!buf) { *r_len = 0; return NULL; @@ -1811,10 +1809,10 @@ void WM_clipboard_text_set(const char *buf, bool selection) } *p2 = '\0'; - GHOST_putClipboard((GHOST_TInt8 *)newbuf, selection); + GHOST_putClipboard(newbuf, selection); MEM_freeN(newbuf); #else - GHOST_putClipboard((GHOST_TInt8 *)buf, selection); + GHOST_putClipboard(buf, selection); #endif } } @@ -2405,6 +2403,10 @@ void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complet { BLI_assert(win); + /* Convert to native OS window coordinates. */ + float fac = GHOST_GetNativePixelSize(win->ghostwin); + x /= fac; + y /= fac; GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete); } diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index ccb6e47e7e3..c21bebe8062 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -352,8 +352,8 @@ enum { /* for event checks */ /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */ /* UNUSED - see wm_eventmatch - BUG T30479. */ -/* #define ISTEXTINPUT(event_type) ((event_type) >= ' ' && (event_type) <= 255) */ -/* note, an alternative could be to check 'event->utf8_buf' */ +// #define ISTEXTINPUT(event_type) ((event_type) >= ' ' && (event_type) <= 255) +/* NOTE: an alternative could be to check `event->utf8_buf`. */ /* test whether the event is a key on the keyboard */ #define ISKEYBOARD(event_type) \ @@ -439,7 +439,7 @@ bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask ma /* Gestures */ /* NOTE: these values are saved in keymap files, do not change them but just add new ones */ enum { - /* value of tweaks and line gestures, note, KM_ANY (-1) works for this case too */ + /* Value of tweaks and line gestures. #KM_ANY (-1) works for this case too. */ EVT_GESTURE_N = 1, EVT_GESTURE_NE = 2, EVT_GESTURE_E = 3, diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actions.c b/source/blender/windowmanager/xr/intern/wm_xr_actions.c index 51ed3dcfd3c..7eabd29baa0 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_actions.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_actions.c @@ -462,7 +462,7 @@ bool WM_xr_action_state_get(const wmXrData *xr, bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, - const long long *duration, + const int64_t *duration, const float *frequency, const float *amplitude) { diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 3f5ca84fbef..c75174dfff0 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -1954,7 +1954,7 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data) /* Make the path absolute because its needed for relative linked blends to be found */ char filename[FILE_MAX]; - /* note, we could skip these, but so far we always tried to load these files */ + /* NOTE: we could skip these, but so far we always tried to load these files. */ if (argv[0][0] == '-') { fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]); } diff --git a/tests/performance/api/__init__.py b/tests/performance/api/__init__.py new file mode 100644 index 00000000000..2dc9283c44a --- /dev/null +++ b/tests/performance/api/__init__.py @@ -0,0 +1,7 @@ +# Apache License, Version 2.0 + +from .environment import TestEnvironment +from .device import TestDevice, TestMachine +from .config import TestEntry, TestQueue, TestConfig +from .test import Test, TestCollection +from .graph import TestGraph diff --git a/tests/performance/api/config.py b/tests/performance/api/config.py new file mode 100644 index 00000000000..68f4df8d487 --- /dev/null +++ b/tests/performance/api/config.py @@ -0,0 +1,259 @@ +# Apache License, Version 2.0 + +import fnmatch +import json +import pathlib +import sys + +from dataclasses import dataclass, field +from typing import Dict, List + +from .test import TestCollection + + +def get_build_hash(args: None) -> str: + import bpy + import sys + build_hash = bpy.app.build_hash.decode('utf-8') + return '' if build_hash == 'Unknown' else build_hash + + +@dataclass +class TestEntry: + """Test to run, a combination of revision, test and device.""" + test: str = '' + category: str = '' + revision: str = '' + git_hash: str = '' + executable: str = '' + date: int = 0 + device_type: str = 'CPU' + device_id: str = 'CPU' + device_name: str = 'Unknown CPU' + status: str = 'queued' + output: Dict = field(default_factory=dict) + benchmark_type: str = 'comparison' + + def to_json(self) -> Dict: + json_dict = {} + for field in self.__dataclass_fields__: + json_dict[field] = getattr(self, field) + return json_dict + + def from_json(self, json_dict): + for field in self.__dataclass_fields__: + setattr(self, field, json_dict[field]) + + +class TestQueue: + """Queue of tests to be run or inspected. Matches JSON file on disk.""" + + def __init__(self, filepath: pathlib.Path): + self.filepath = filepath + self.has_multiple_revisions_to_build = False + self.has_multiple_categories = False + self.entries = [] + + if self.filepath.is_file(): + with open(self.filepath, 'r') as f: + json_entries = json.load(f) + + for json_entry in json_entries: + entry = TestEntry() + entry.from_json(json_entry) + self.entries.append(entry) + + def rows(self, use_revision_columns: bool) -> List: + # Generate rows of entries for printing and running. + entries = sorted(self.entries, key=lambda entry: + (entry.revision, + entry.device_id, + entry.category, + entry.test)) + + if not use_revision_columns: + # One entry per row. + return [[entry] for entry in entries] + else: + # Multiple revisions per row. + rows = {} + + for entry in entries: + key = (entry.device_id, entry.category, entry.test) + if key in rows: + rows[key].append(entry) + else: + rows[key] = [entry] + + return [value for _, value in sorted(rows.items())] + + def find(self, revision: str, test: str, category: str, device_id: str) -> Dict: + for entry in self.entries: + if entry.revision == revision and \ + entry.test == test and \ + entry.category == category and \ + entry.device_id == device_id: + return entry + + return None + + def write(self) -> None: + json_entries = [entry.to_json() for entry in self.entries] + with open(self.filepath, 'w') as f: + json.dump(json_entries, f, indent=2) + + +class TestConfig: + """Test configuration, containing a subset of revisions, tests and devices.""" + + def __init__(self, env, name: str): + # Init configuration from config.py file. + self.name = name + self.base_dir = env.base_dir / name + self.logs_dir = self.base_dir / 'logs' + + config = self._read_config_module() + self.tests = TestCollection(env, + getattr(config, 'tests', ['*']), + getattr(config, 'categories', ['*'])) + self.revisions = getattr(config, 'revisions', {}) + self.builds = getattr(config, 'builds', {}) + self.queue = TestQueue(self.base_dir / 'results.json') + self.benchmark_type = getattr(config, 'benchmark_type', 'comparison') + + self.devices = [] + self._update_devices(env, getattr(config, 'devices', ['CPU'])) + + self._update_queue(env) + + def revision_names(self) -> List: + return sorted(list(self.revisions.keys()) + list(self.builds.keys())) + + def device_name(self, device_id: str) -> str: + for device in self.devices: + if device.id == device_id: + return device.name + + return "Unknown" + + @staticmethod + def write_default_config(env, config_dir: pathlib.Path) -> None: + config_dir.mkdir(parents=True, exist_ok=True) + + default_config = """devices = ['CPU']\n""" + default_config += """tests = ['*']\n""" + default_config += """categories = ['*']\n""" + default_config += """builds = {\n""" + default_config += """ 'master': '/home/user/blender-git/build/bin/blender',""" + default_config += """ '2.93': '/home/user/blender-2.93/blender',""" + default_config += """}\n""" + default_config += """revisions = {\n""" + default_config += """}\n""" + + config_file = config_dir / 'config.py' + with open(config_file, 'w') as f: + f.write(default_config) + + def _read_config_module(self) -> None: + # Import config.py as a module. + import importlib.util + spec = importlib.util.spec_from_file_location("testconfig", self.base_dir / 'config.py') + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + def _update_devices(self, env, device_filters: List) -> None: + # Find devices matching the filters. + need_gpus = device_filters != ['CPU'] + machine = env.get_machine(need_gpus) + + self.devices = [] + for device in machine.devices: + for device_filter in device_filters: + if fnmatch.fnmatch(device.id, device_filter): + self.devices.append(device) + break + + def _update_queue(self, env) -> None: + # Update queue to match configuration, adding and removing entries + # so that there is one entry for each revision, device and test + # combination. + entries = [] + + # Get entries for specified commits, tags and branches. + for revision_name, revision_commit in self.revisions.items(): + git_hash = env.resolve_git_hash(revision_commit) + date = env.git_hash_date(git_hash) + entries += self._get_entries(revision_name, git_hash, '', date) + + # Optimization to avoid rebuilds. + revisions_to_build = set() + for entry in entries: + if entry.status in ('queued', 'outdated'): + revisions_to_build.add(entry.git_hash) + self.queue.has_multiple_revisions_to_build = len(revisions_to_build) > 1 + + # Get entries for revisions based on existing builds. + for revision_name, executable in self.builds.items(): + executable_path = pathlib.Path(executable) + if not executable_path.exists(): + sys.stderr.write(f'Error: build {executable} not found\n') + sys.exit(1) + + env.set_blender_executable(executable_path) + git_hash, _ = env.run_in_blender(get_build_hash, {}) + env.unset_blender_executable() + + mtime = executable_path.stat().st_mtime + entries += self._get_entries(revision_name, git_hash, executable, mtime) + + # Detect number of categories for more compact printing. + categories = set() + for entry in entries: + categories.add(entry.category) + self.queue.has_multiple_categories = len(categories) > 1 + + # Replace actual entries. + self.queue.entries = entries + + def _get_entries(self, + revision_name: str, + git_hash: str, + executable: pathlib.Path, + date: int) -> None: + entries = [] + for test in self.tests.tests: + test_name = test.name() + test_category = test.category() + + for device in self.devices: + entry = self.queue.find(revision_name, test_name, test_category, device.id) + if entry: + # Test if revision hash or executable changed. + if entry.git_hash != git_hash or \ + entry.executable != executable or \ + entry.benchmark_type != self.benchmark_type or \ + entry.date != date: + # Update existing entry. + entry.git_hash = git_hash + entry.executable = executable + entry.benchmark_type = self.benchmark_type + entry.date = date + if entry.status in ('done', 'failed'): + entry.status = 'outdated' + else: + # Add new entry if it did not exist yet. + entry = TestEntry( + revision=revision_name, + git_hash=git_hash, + executable=executable, + date=date, + test=test_name, + category=test_category, + device_type=device.type, + device_id=device.id, + device_name=device.name, + benchmark_type=self.benchmark_type) + entries.append(entry) + + return entries diff --git a/tests/performance/api/device.py b/tests/performance/api/device.py new file mode 100644 index 00000000000..b61ae42be36 --- /dev/null +++ b/tests/performance/api/device.py @@ -0,0 +1,71 @@ +# Apache License, Version 2.0 + +import platform +import subprocess +from typing import List + + +def get_cpu_name() -> str: + # Get full CPU name. + if platform.system() == "Windows": + return platform.processor() + elif platform.system() == "Darwin": + cmd = ['/usr/sbin/sysctl', "-n", "machdep.cpu.brand_string"] + return subprocess.check_output(cmd).strip().decode('utf-8') + else: + with open('/proc/cpuinfo') as f: + for line in f: + if line.startswith('model name'): + return line.split(':')[1].strip() + + return "Unknown CPU" + + +def get_gpu_device(args: None) -> List: + # Get the list of available Cycles GPU devices. + import bpy + import sys + + prefs = bpy.context.preferences + cprefs = prefs.addons['cycles'].preferences + + result = [] + + for device_type, _, _, _ in cprefs.get_device_types(bpy.context): + cprefs.compute_device_type = device_type + devices = cprefs.get_devices_for_type(device_type) + index = 0 + for device in devices: + if device.type == device_type: + result.append({'type': device.type, 'name': device.name, 'index': index}) + index += 1 + break + + return result + + +class TestDevice: + def __init__(self, device_type: str, device_id: str, name: str, operating_system: str): + self.type = device_type + self.id = device_id + self.name = name + self.operating_system = operating_system + + +class TestMachine: + def __init__(self, env, need_gpus: bool): + operating_system = platform.system() + + self.devices = [TestDevice('CPU', 'CPU', get_cpu_name(), operating_system)] + self.has_gpus = need_gpus + + if need_gpus and env.blender_executable: + gpu_devices, _ = env.run_in_blender(get_gpu_device, {}) + for gpu_device in gpu_devices: + device_type = gpu_device['type'] + device_name = gpu_device['name'] + device_id = gpu_device['type'] + "_" + str(gpu_device['index']) + self.devices.append(TestDevice(device_type, device_id, device_name, operating_system)) + + def cpu_device(self) -> TestDevice: + return self.devices[0] diff --git a/tests/performance/api/environment.py b/tests/performance/api/environment.py new file mode 100644 index 00000000000..c9ddd493394 --- /dev/null +++ b/tests/performance/api/environment.py @@ -0,0 +1,244 @@ +# Apache License, Version 2.0 + +import base64 +import glob +import inspect +import multiprocessing +import os +import pathlib +import platform +import pickle +import subprocess +import sys +from typing import Callable, Dict, List + +from .config import TestConfig +from .device import TestMachine + + +class TestEnvironment: + def __init__(self, blender_git_dir: pathlib.Path, base_dir: pathlib.Path): + self.blender_git_dir = blender_git_dir + self.base_dir = base_dir + self.blender_dir = base_dir / 'blender' + self.build_dir = base_dir / 'build' + self.lib_dir = base_dir / 'lib' + self.benchmarks_dir = self.blender_git_dir.parent / 'lib' / 'benchmarks' + self.git_executable = 'git' + self.cmake_executable = 'cmake' + self.cmake_options = ['-DWITH_INTERNATIONAL=OFF', '-DWITH_BUILDINFO=OFF'] + self.unset_blender_executable() + self.log_file = None + self.machine = None + + def get_machine(self, need_gpus: bool=True) -> None: + if not self.machine or (need_gpus and not self.machine.has_gpus): + self.machine = TestMachine(self, need_gpus) + + return self.machine + + def init(self, build) -> None: + if not self.benchmarks_dir.exists(): + sys.stderr.write(f'Error: benchmark files directory not found at {self.benchmarks_dir}') + sys.exit(1) + + # Create benchmarks folder contents. + print(f'Init {self.base_dir}') + self.base_dir.mkdir(parents=True, exist_ok=True) + + if len(self.get_configs(names_only=True)) == 0: + config_dir = self.base_dir / 'default' + print(f'Creating default configuration in {config_dir}') + TestConfig.write_default_config(self, config_dir) + + if build: + if not self.lib_dir.exists(): + print(f'Creating symlink at {self.lib_dir}') + self.lib_dir.symlink_to(self.blender_git_dir.parent / 'lib') + else: + print(f'Exists {self.lib_dir}') + + if not self.blender_dir.exists(): + print(f'Init git worktree in {self.blender_dir}') + self.call([self.git_executable, 'worktree', 'add', '--detach', self.blender_dir, 'HEAD'], self.blender_git_dir) + else: + print(f'Exists {self.blender_dir}') + + if not self.build_dir.exists(): + print(f'Init build in {self.build_dir}') + self.build_dir.mkdir() + # No translation to avoid dealing with submodules + self.call([self.cmake_executable, self.blender_dir, '.'] + self.cmake_options, self.build_dir) + else: + print(f'Exists {self.build_dir}') + + print("Building") + self.build() + + print('Done') + + def checkout(self) -> None: + # Checkout Blender revision + if not self.blender_dir.exists(): + sys.stderr.write('\n\nError: no build set up, run `./benchmark init --build` first\n') + sys.exit(1) + + self.call([self.git_executable, 'clean', '-f', '-d'], self.blender_dir) + self.call([self.git_executable, 'reset', '--hard', 'HEAD'], self.blender_dir) + self.call([self.git_executable, 'checkout', '--detach', git_hash], self.blender_dir) + + self.build() + + def build(self) -> None: + # Build Blender revision + if not self.build_dir.exists(): + sys.stderr.write('\n\nError: no build set up, run `./benchmark init --build` first\n') + sys.exit(1) + + jobs = str(multiprocessing.cpu_count()) + self.call([self.cmake_executable, '.'] + self.cmake_options, self.build_dir) + self.call([self.cmake_executable, '--build', '.', '-j', jobs, '--target', 'install'], self.build_dir) + + def set_blender_executable(self, executable_path: pathlib.Path) -> None: + # Run all Blender commands with this executable. + self.blender_executable = executable_path + + def unset_blender_executable(self) -> None: + if platform.system() == "Windows": + self.blender_executable = self.build_dir / 'bin' / 'blender.exe' + elif platform.system() == "Darwin": + self.blender_executable = self.build_dir / 'bin' / 'Blender.app' / 'Contents' / 'MacOS' / 'Blender' + else: + self.blender_executable = self.build_dir / 'bin' / 'blender' + + if not self.blender_executable.exists(): + self.blender_executable = 'blender' + + def set_log_file(self, filepath: pathlib.Path, clear=True) -> None: + # Log all commands and output to this file. + self.log_file = filepath + + if clear: + self.log_file.unlink(missing_ok=True) + + def unset_log_file(self) -> None: + self.log_file = None + + def call(self, args: List[str], cwd: pathlib.Path, silent=False) -> List[str]: + # Execute command with arguments in specified directory, + # and return combined stdout and stderr output. + + # Open log file for writing + f = None + if self.log_file: + if not self.log_file.exists(): + self.log_file.parent.mkdir(parents=True, exist_ok=True) + f = open(self.log_file, 'a') + f.write('\n' + ' '.join([str(arg) for arg in args]) + '\n\n') + + proc = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + # Read line by line + lines = [] + try: + while proc.poll() is None: + line = proc.stdout.readline() + if line: + line_str = line.decode('utf-8', 'ignore') + lines.append(line_str) + if f: + f.write(line_str) + except KeyboardInterrupt: + # Avoid processes that keep running when interrupting. + proc.terminate() + + if f: + f.close() + + # Print command output on error + if proc.returncode != 0 and not silent: + for line in lines: + print(line.rstrip()) + raise Exception("Error executing command") + + return lines + + def call_blender(self, args: List[str], foreground=False) -> List[str]: + # Execute Blender command with arguments. + common_args = ['--factory-startup', '--enable-autoexec', '--python-exit-code', '1'] + if foreground: + common_args += ['--no-window-focus', '--window-geometry', '0', '0', '1024', '768'] + else: + common_args += ['--background'] + + return self.call([self.blender_executable] + common_args + args, cwd=self.base_dir) + + def run_in_blender(self, + function: Callable[[Dict], Dict], + args: Dict, + blender_args: List=[], + foreground=False) -> Dict: + # Run function in a Blender instance. Arguments and return values are + # passed as a Python object that must be serializable with pickle. + + # Get information to call this function from Blender. + package_path = pathlib.Path(__file__).parent.parent + functionname = function.__name__ + modulename = inspect.getmodule(function).__name__ + + # Serialize arguments in base64, to avoid having to escape it. + args = base64.b64encode(pickle.dumps(args)) + output_prefix = 'TEST_OUTPUT: ' + + expression = (f'import sys, pickle, base64\n' + f'sys.path.append("{package_path}")\n' + f'import {modulename}\n' + f'args = pickle.loads(base64.b64decode({args}))\n' + f'result = {modulename}.{functionname}(args)\n' + f'result = base64.b64encode(pickle.dumps(result))\n' + f'print("{output_prefix}" + result.decode())\n') + + expr_args = blender_args + ['--python-expr', expression] + lines = self.call_blender(expr_args, foreground=foreground) + + # Parse output. + for line in lines: + if line.startswith(output_prefix): + output = line[len(output_prefix):].strip() + result = pickle.loads(base64.b64decode(output)) + return result, lines + + return {}, lines + + def find_blend_files(self, dirpath: pathlib.Path) -> List: + # Find .blend files in subdirectories of the given directory in the + # lib/benchmarks directory. + dirpath = self.benchmarks_dir / dirpath + filepaths = [] + for filename in glob.iglob(str(dirpath / '*.blend'), recursive=True): + filepaths.append(pathlib.Path(filename)) + return filepaths + + def get_configs(self, name: str=None, names_only: bool=False) -> List: + # Get list of configurations in the benchmarks directory. + configs = [] + + if self.base_dir.exists(): + for dirname in os.listdir(self.base_dir): + if not name or dirname == name: + dirpath = self.base_dir / dirname / 'config.py' + if dirpath.exists(): + if names_only: + configs.append(dirname) + else: + configs.append(TestConfig(self, dirname)) + + return configs + + def resolve_git_hash(self, revision): + # Get git hash for a tag or branch. + return self.call([self.git_executable, 'rev-parse', revision], self.blender_git_dir)[0].strip() + + def git_hash_date(self, git_hash): + # Get commit data for a git hash. + return int(self.call([self.git_executable, 'log', '-n1', git_hash, '--format=%at'], self.blender_git_dir)[0].strip()) diff --git a/tests/performance/api/graph.py b/tests/performance/api/graph.py new file mode 100644 index 00000000000..b3c8329ff27 --- /dev/null +++ b/tests/performance/api/graph.py @@ -0,0 +1,114 @@ +# Apache License, Version 2.0 + +from . import TestQueue + +import json +import pathlib +from typing import Dict, List + + +class TestGraph: + def __init__(self, json_filepaths: List[pathlib.Path]): + # Initialize graph from JSON file. Note that this is implemented without + # accessing any benchmark environment or configuration. This ways benchmarks + # run on various machines can be aggregated and the graph generated on another + # machine. + + # Gather entries for each device. + devices = {} + + for json_filepath in json_filepaths: + queue = TestQueue(json_filepath) + + for entry in queue.entries: + if entry.status in ('done', 'outdated'): + device_name = entry.device_name + if device_name in devices.keys(): + devices[device_name].append(entry) + else: + devices[device_name] = [entry] + + data = [] + for device_name, device_entries in devices.items(): + # Gather used categories. + categories = {} + for entry in device_entries: + category = entry.category + if category in categories.keys(): + categories[category].append(entry) + else: + categories[category] = [entry] + + # Generate one graph for every device x category x result key combination. + for category, category_entries in categories.items(): + entries = sorted(category_entries, key=lambda entry: (entry.revision, entry.test)) + + outputs = set() + for entry in entries: + for output in entry.output.keys(): + outputs.add(output) + + chart_type = 'line' if entries[0].benchmark_type == 'time_series' else 'comparison' + + for output in outputs: + chart_name = f"{category} ({output})" + data.append(self.chart(device_name, chart_name, entries, chart_type, output)) + + self.json = json.dumps(data, indent=2) + + def chart(self, device_name: str, chart_name: str, entries: List, chart_type: str, output: str) -> Dict: + # Gather used tests. + tests = {} + for entry in entries: + test = entry.test + if test not in tests.keys(): + tests[test] = len(tests) + + # Gather used revisions. + revisions = {} + revision_dates = {} + for entry in entries: + revision = entry.revision + if revision not in revisions.keys(): + revisions[revision] = len(revisions) + revision_dates[revision] = int(entry.date) + + # Google Charts JSON data layout is like a spreadsheat table, with + # colums, rows and cells. We create one column for revision labels, + # and one column for each test. + cols = [] + if chart_type == 'line': + cols.append({'id': '', 'label': 'Date', 'type': 'date'}) + else: + cols.append({'id': '', 'label': ' ', 'type': 'string'}) + for test, test_index in tests.items(): + cols.append({'id': '', 'label': test, 'type': 'number'}) + + rows = [] + for revision, revision_index in revisions.items(): + if chart_type == 'line': + date = revision_dates[revision] + row = [{'f': None, 'v': 'Date({0})'.format(date * 1000)}] + else: + row = [{'f': None, 'v': revision}] + row += [{}] * len(tests) + rows.append({'c': row}) + + for entry in entries: + test_index = tests[entry.test] + revision_index = revisions[entry.revision] + time = entry.output[output] if output in entry.output else -1.0 + rows[revision_index]['c'][test_index + 1] = {'f': None, 'v': time} + + data = {'cols': cols, 'rows': rows} + return {'device': device_name, 'name': chart_name, 'data': data, 'chart_type': chart_type} + + def write(self, filepath: pathlib.Path) -> None: + # Write HTML page with JSON graph data embedded. + template_dir = pathlib.Path(__file__).parent + with open(template_dir / 'graph.template.html', 'r') as f: + template = f.read() + + contents = template.replace('%JSON_DATA%', self.json) + with open(filepath, "w") as f: + f.write(contents) diff --git a/tests/performance/api/graph.template.html b/tests/performance/api/graph.template.html new file mode 100644 index 00000000000..147f1628c23 --- /dev/null +++ b/tests/performance/api/graph.template.html @@ -0,0 +1,86 @@ +<html> +<head> + <title>Benchmarks</title> + <meta charset="UTF-8"> + <style type="text/css"> + body { margin: 40px auto; + font-family: Arial; + font-size: 14px; + color: #333; + max-width: 900px; } + a { text-decoration: none; color: #06b; } + </style> + <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> + <script> + google.charts.load('current', {'packages':['line', 'bar']}); + google.charts.setOnLoadCallback(draw_charts); + + function transposeDataTable(dt) + { + /* Swap rows and columns. Bar and line charts expect different layouts, + * with this function we can use the same data source for both. */ + var ndt = new google.visualization.DataTable; + ndt.addColumn('string',dt.getColumnLabel(0)); + for(var x=1; x<dt.getNumberOfColumns(); x++) { + ndt.addRow([dt.getColumnLabel(x)]); + } + for(var x=0; x<dt.getNumberOfRows(); x++) { + ndt.addColumn('number', dt.getValue(x,0)); + for(var y=1; y<dt.getNumberOfColumns(); y++) { + ndt.setValue(y-1, x+1, dt.getValue(x,y)); + } + } + return ndt; + } + + function draw_charts() + { + /* Load JSON data. */ + var json_data = %JSON_DATA%; + + /* Clear contents. */ + charts_elem = document.getElementById("charts"); + while(charts_elem.firstChild) + { + charts_elem.removeChild(charts_elem.firstChild); + } + + /* Draw charts for each device. */ + for (var i = 0; i < json_data.length; i++) + { + device = json_data[i]; + + /* Chart drawing options. */ + var options = { + chart: {title: device["name"], subtitle: device['device']}, + pointsVisible: true, + pointSize: 2.5, + height: 500, + }; + + /* Create chart div. */ + elem = document.createElement('div'); + elem.id = device["id"]; + charts_elem.appendChild(elem) + + /* Create chart. */ + var data = new google.visualization.DataTable(device["data"]); + if (device['chart_type'] == 'line') { + var chart = new google.charts.Line(elem); + chart.draw(data, options); + } + else { + var chart = new google.charts.Bar(elem); + chart.draw(transposeDataTable(data), options); + } + } + } + </script> +</head> +<body> + <h1>Benchmarks</h1> + <div id="charts"> + ... + </div> +</body> +</html> diff --git a/tests/performance/api/test.py b/tests/performance/api/test.py new file mode 100644 index 00000000000..7e8193d2c21 --- /dev/null +++ b/tests/performance/api/test.py @@ -0,0 +1,73 @@ +# Apache License, Version 2.0 + +import abc +import fnmatch +from typing import Dict, List + + +class Test: + @abc.abstractmethod + def name(self) -> str: + """ + Name of the test. + """ + + @abc.abstractmethod + def category(self) -> str: + """ + Category of the test. + """ + + def use_device(self) -> bool: + """ + Test uses a specific CPU or GPU device. + """ + return False + + @abc.abstractmethod + def run(self, env, device_id: str) -> Dict: + """ + Execute the test and report results. + """ + + +class TestCollection: + def __init__(self, env, names_filter: List=['*'], categories_filter: List=['*']): + import importlib + import pkgutil + import tests + + self.tests = [] + + # Find and import all Python files in the tests folder, and generate + # the list of tests for each. + for _, modname, _ in pkgutil.iter_modules(tests.__path__, 'tests.'): + module = importlib.import_module(modname) + tests = module.generate(env) + + for test in tests: + test_category = test.category() + found = False + for category_filter in categories_filter: + if fnmatch.fnmatch(test_category, category_filter): + found = True + if not found: + continue + + test_name = test.name() + found = False + for name_filter in names_filter: + if fnmatch.fnmatch(test_name, name_filter): + found = True + if not found: + continue + + self.tests.append(test) + + def find(self, test_name: str, test_category: str): + # Find a test based on name and category. + for test in self.tests: + if test.name() == test_name and test.category() == test_category: + return test + + return None diff --git a/tests/performance/benchmark b/tests/performance/benchmark new file mode 100755 index 00000000000..3b43bd0aa96 --- /dev/null +++ b/tests/performance/benchmark @@ -0,0 +1,299 @@ +#!/usr/bin/env python3 +# Apache License, Version 2.0 + +import api +import argparse +import fnmatch +import pathlib +import shutil +import sys +import time +from typing import List + +def find_blender_git_dir() -> pathlib.Path: + # Find .git directory of the repository we are in. + cwd = pathlib.Path.cwd() + + for path in [cwd] + list(cwd.parents): + if (path / '.git').exists(): + return path + + return None + +def get_tests_base_dir(blender_git_dir: pathlib.Path) -> pathlib.Path: + # Benchmarks dir is next to the Blender source folder. + return blender_git_dir.parent / 'benchmark' + +def use_revision_columns(config: api.TestConfig) -> bool: + return config.benchmark_type == "comparison" and \ + len(config.queue.entries) > 0 and \ + not config.queue.has_multiple_revisions_to_build + +def print_header(config: api.TestConfig) -> None: + # Print header with revision columns headers. + if use_revision_columns(config): + header = "" + if config.queue.has_multiple_categories: + header += f"{'': <15} " + header += f"{'': <40} " + + for revision_name in config.revision_names(): + header += f"{revision_name: <20} " + print(header) + +def print_row(config: api.TestConfig, entries: List, end='\n') -> None: + # Print one or more test entries on a row. + row = "" + + # For time series, print revision first. + if not use_revision_columns(config): + revision = entries[0].revision + git_hash = entries[0].git_hash + + row += f"{revision: <15} " + + if config.queue.has_multiple_categories: + row += f"{entries[0].category: <15} " + row += f"{entries[0].test: <40} " + + for entry in entries: + # Show time or status. + status = entry.status + output = entry.output + result = '' + if status in ('done', 'outdated') and output: + result = '%.4fs' % output['time'] + + if status == 'outdated': + result += " (outdated)" + else: + result = status + + row += f"{result: <20} " + + print(row, end=end, flush=True) + + +def match_entry(entry: api.TestEntry, args: argparse.Namespace): + # Filter tests by name and category. + return fnmatch.fnmatch(entry.test, args.test) or \ + fnmatch.fnmatch(entry.category, args.test) or \ + entry.test.find(args.test) != -1 or \ + entry.category.find(args.test) != -1 + +def run_entry(env: api.TestEnvironment, config: api.TestConfig, row: List, entry: api.TestEntry): + # Check if entry needs to be run. + if entry.status not in ('queued', 'outdated'): + print_row(config, row, end='\r') + return False + + # Run test entry. + revision = entry.revision + git_hash = entry.git_hash + testname = entry.test + testcategory = entry.category + device_type = entry.device_type + device_id = entry.device_id + + test = config.tests.find(testname, testcategory) + if not test: + return False + + # Log all output to dedicated log file. + logname = testcategory + '_' + testname + '_' + revision + if device_id != 'CPU': + logname += '_' + device_id + env.set_log_file(config.logs_dir / (logname + '.log'), clear=True) + + # Build revision, or just set path to existing executable. + entry.status = 'building' + print_row(config, row, end='\r') + if len(entry.executable): + env.set_blender_executable(pathlib.Path(entry.executable)) + else: + env.checkout(git_hash) + env.build(git_hash) + + # Run test and update output and status. + entry.status = 'running' + print_row(config, row, end='\r') + entry.output = test.run(env, device_id) + entry.status = 'done' if entry.output else 'failed' + print_row(config, row, end='\r') + + # Update device name in case the device changed since the entry was created. + entry.device_name = config.device_name(device_id) + + # Restore default logging and Blender executable. + env.unset_log_file() + env.unset_blender_executable() + + return True + +def cmd_init(env: api.TestEnvironment, argv: List): + # Initialize benchmarks folder. + parser = argparse.ArgumentParser() + parser.add_argument('--build', default=False, action='store_true') + args = parser.parse_args(argv) + env.set_log_file(env.base_dir / 'setup.log', clear=False) + env.init(args.build) + env.unset_log_file() + +def cmd_list(env: api.TestEnvironment, argv: List) -> None: + # List devices, tests and configurations. + print('DEVICES') + machine = env.get_machine() + for device in machine.devices: + name = f"{device.name} ({device.operating_system})" + print(f"{device.id: <15} {name}") + print('') + + print('TESTS') + collection = api.TestCollection(env) + for test in collection.tests: + print(f"{test.category(): <15} {test.name(): <50}") + print('') + + print('CONFIGS') + configs = env.get_configs(names_only=True) + for config_name in configs: + print(config_name) + +def cmd_status(env: api.TestEnvironment, argv: List): + # Print status of tests in configurations. + parser = argparse.ArgumentParser() + parser.add_argument('config', nargs='?', default=None) + parser.add_argument('test', nargs='?', default='*') + args = parser.parse_args(argv) + + configs = env.get_configs(args.config) + first = True + for config in configs: + if not args.config: + if first: + first = False + else: + print("") + print(config.name.upper()) + + print_header(config) + for row in config.queue.rows(use_revision_columns(config)): + if match_entry(row[0], args): + print_row(config, row) + +def cmd_reset(env: api.TestEnvironment, argv: List): + # Reset tests to re-run them. + parser = argparse.ArgumentParser() + parser.add_argument('config', nargs='?', default=None) + parser.add_argument('test', nargs='?', default='*') + args = parser.parse_args(argv) + + configs = env.get_configs(args.config) + for config in configs: + print_header(config) + for row in config.queue.rows(use_revision_columns(config)): + if match_entry(row[0], args): + for entry in row: + entry.status = 'queued' + entry.result = {} + print_row(config, row) + + config.queue.write() + +def cmd_run(env: api.TestEnvironment, argv: List): + # Run tests. + parser = argparse.ArgumentParser() + parser.add_argument('config', nargs='?', default=None) + parser.add_argument('test', nargs='?', default='*') + args = parser.parse_args(argv) + + configs = env.get_configs(args.config) + for config in configs: + updated = False + print_header(config) + for row in config.queue.rows(use_revision_columns(config)): + if match_entry(row[0], args): + for entry in row: + if run_entry(env, config, row, entry): + updated = True + # Write queue every time in case running gets interrupted, + # so it can be resumed. + config.queue.write() + print_row(config, row) + + if updated: + # Generate graph if test were run. + json_filepath = config.base_dir / "results.json" + html_filepath = config.base_dir / "results.html" + graph = api.TestGraph([json_filepath]) + graph.write(html_filepath) + + print("\nfile://" + str(html_filepath)) + +def cmd_graph(argv: List): + # Create graph from a given JSON results file. + parser = argparse.ArgumentParser() + parser.add_argument('json_file', nargs='+') + parser.add_argument('-o', '--output', type=str, required=True) + args = parser.parse_args(argv) + + graph = api.TestGraph([pathlib.Path(path) for path in args.json_file]) + graph.write(pathlib.Path(args.output)) + +def main(): + usage = ('benchmark <command> [<args>]\n' + '\n' + 'Commands:\n' + ' init [--build] Init benchmarks directory and default config\n' + ' Optionally with automated revision building setup\n' + ' \n' + ' list List available tests, devices and configurations\n' + ' \n' + ' run [<config>] [<test>] Execute tests for configuration\n' + ' reset [<config>] [<test>] Clear tests results from config, for re-running\n' + ' status [<config>] [<test>] List configurations and their tests\n' + ' \n' + ' graph a.json b.json... -o out.html Create graph from results in JSON files\n') + + parser = argparse.ArgumentParser( + description='Blender performance testing', + usage=usage) + + parser.add_argument('command', nargs='?', default='help') + args = parser.parse_args(sys.argv[1:2]) + + argv = sys.argv[2:] + blender_git_dir = find_blender_git_dir() + if blender_git_dir == None: + sys.stderr.write('Error: no blender git repository found from current working directory\n') + sys.exit(1) + + if args.command == 'graph': + cmd_graph(argv) + sys.exit(0) + + base_dir = get_tests_base_dir(blender_git_dir) + env = api.TestEnvironment(blender_git_dir, base_dir) + if args.command == 'init': + cmd_init(env, argv) + sys.exit(0) + + if not env.base_dir.exists(): + sys.stderr.write('Error: benchmark directory not initialized\n') + sys.exit(1) + + if args.command == 'list': + cmd_list(env, argv) + elif args.command == 'run': + cmd_run(env, argv) + elif args.command == 'reset': + cmd_reset(env, argv) + elif args.command == 'status': + cmd_status(env, argv) + elif args.command == 'help': + parser.print_usage() + else: + sys.stderr.write(f'Unknown command: {args.command}\n') + +if __name__ == '__main__': + main() diff --git a/tests/performance/tests/__init__.py b/tests/performance/tests/__init__.py new file mode 100644 index 00000000000..ac3e613174f --- /dev/null +++ b/tests/performance/tests/__init__.py @@ -0,0 +1 @@ +# Apache License, Version 2.0 diff --git a/tests/performance/tests/animation.py b/tests/performance/tests/animation.py new file mode 100644 index 00000000000..1a92f1a9718 --- /dev/null +++ b/tests/performance/tests/animation.py @@ -0,0 +1,41 @@ +# Apache License, Version 2.0 + +import api +import os + + +def _run(args): + import bpy + import time + + start_time = time.time() + + scene = bpy.context.scene + for i in range(scene.frame_start, scene.frame_end): + scene.frame_set(scene.frame_start) + + elapsed_time = time.time() - start_time + + result = {'time': elapsed_time} + return result + + +class AnimationTest(api.Test): + def __init__(self, filepath): + self.filepath = filepath + + def name(self): + return self.filepath.stem + + def category(self): + return "animation" + + def run(self, env, device_id): + args = {} + result, _ = env.run_in_blender(_run, args) + return result + + +def generate(env): + filepaths = env.find_blend_files('animation') + return [AnimationTest(filepath) for filepath in filepaths] diff --git a/tests/performance/tests/blend_load.py b/tests/performance/tests/blend_load.py new file mode 100644 index 00000000000..5fe498fd3d7 --- /dev/null +++ b/tests/performance/tests/blend_load.py @@ -0,0 +1,42 @@ +# Apache License, Version 2.0 + +import api +import os +import pathlib + + +def _run(filepath): + import bpy + import time + + # Load once to ensure it's cached by OS + bpy.ops.wm.open_mainfile(filepath=filepath) + bpy.ops.wm.read_homefile() + + # Measure loading the second time + start_time = time.time() + bpy.ops.wm.open_mainfile(filepath=filepath) + elapsed_time = time.time() - start_time + + result = {'time': elapsed_time} + return result + + +class BlendLoadTest(api.Test): + def __init__(self, filepath): + self.filepath = filepath + + def name(self): + return self.filepath.stem + + def category(self): + return "blend_load" + + def run(self, env, device_id): + result, _ = env.run_in_blender(_run, str(self.filepath)) + return result + + +def generate(env): + filepaths = env.find_blend_files('*/*') + return [BlendLoadTest(filepath) for filepath in filepaths] diff --git a/tests/performance/tests/cycles.py b/tests/performance/tests/cycles.py new file mode 100644 index 00000000000..bac6b8a7ceb --- /dev/null +++ b/tests/performance/tests/cycles.py @@ -0,0 +1,92 @@ +# Apache License, Version 2.0 + +import api +import os + + +def _run(args): + import bpy + import time + + device_type = args['device_type'] + device_index = args['device_index'] + + scene = bpy.context.scene + scene.render.engine = 'CYCLES' + scene.render.filepath = args['render_filepath'] + scene.render.image_settings.file_format = 'PNG' + scene.cycles.device = 'CPU' if device_type == 'CPU' else 'GPU' + + if scene.cycles.device == 'GPU': + # Enable specified GPU in preferences. + prefs = bpy.context.preferences + cprefs = prefs.addons['cycles'].preferences + cprefs.compute_device_type = device_type + devices = cprefs.get_devices_for_type(device_type) + for device in devices: + device.use = False + + index = 0 + for device in devices: + if device.type == device_type: + if index == device_index: + device.use = True + break + else: + index += 1 + + # Render + bpy.ops.render.render(write_still=True) + + return None + + +class CyclesTest(api.Test): + def __init__(self, filepath): + self.filepath = filepath + + def name(self): + return self.filepath.stem + + def category(self): + return "cycles" + + def use_device(self): + return True + + def run(self, env, device_id): + tokens = device_id.split('_') + device_type = tokens[0] + device_index = int(tokens[1]) if len(tokens) > 1 else 0 + args = {'device_type': device_type, + 'device_index': device_index, + 'render_filepath': str(env.log_file.parent / (env.log_file.stem + '.png'))} + + _, lines = env.run_in_blender(_run, args, ['--debug-cycles', '--verbose', '1', self.filepath]) + + # Parse render time from output + prefix_time = "Render time (without synchronization): " + prefix_memory = "Peak: " + time = None + memory = None + for line in lines: + line = line.strip() + offset = line.find(prefix_time) + if offset != -1: + time = line[offset + len(prefix_time):] + time = float(time) + offset = line.find(prefix_memory) + if offset != -1: + memory = line[offset + len(prefix_memory):] + memory = memory.split()[0].replace(',', '') + memory = float(memory) + + if not (time and memory): + raise Exception("Error parsing render time output") + + return {'time': time, 'peak_memory': memory} + + +def generate(env): + filepaths = env.find_blend_files('cycles-x/*') + return [CyclesTest(filepath) for filepath in filepaths] diff --git a/tests/python/alembic_export_tests.py b/tests/python/alembic_export_tests.py index 9d1738691f0..23a4a376533 100644 --- a/tests/python/alembic_export_tests.py +++ b/tests/python/alembic_export_tests.py @@ -197,7 +197,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest): def test_hierarchical_export(self, tempdir: pathlib.Path): abc = tempdir / 'cubes_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() + "visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('cubes-hierarchy.blend', script) # Now check the resulting Alembic file. @@ -215,7 +215,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest): def test_flat_export(self, tempdir: pathlib.Path): abc = tempdir / 'cubes_flat.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix() + "visible_objects_only=True, flatten=True)" % abc.as_posix() self.run_blender('cubes-hierarchy.blend', script) # Now check the resulting Alembic file. @@ -236,7 +236,7 @@ class DupliGroupExportTest(AbstractAlembicTest): def test_hierarchical_export(self, tempdir: pathlib.Path): abc = tempdir / 'dupligroup_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() + "visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('dupligroup-scene.blend', script) # Now check the resulting Alembic file. @@ -254,7 +254,7 @@ class DupliGroupExportTest(AbstractAlembicTest): def test_flat_export(self, tempdir: pathlib.Path): abc = tempdir / 'dupligroup_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix() + "visible_objects_only=True, flatten=True)" % abc.as_posix() self.run_blender('dupligroup-scene.blend', script) # Now check the resulting Alembic file. @@ -332,7 +332,7 @@ class CurveExportTest(AbstractAlembicTest): def test_export_single_curve(self, tempdir: pathlib.Path): abc = tempdir / 'single-curve.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() + "visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('single-curve.blend', script) # Now check the resulting Alembic file. @@ -353,7 +353,7 @@ class HairParticlesExportTest(AbstractAlembicTest): def _do_test(self, tempdir: pathlib.Path, export_hair: bool, export_particles: bool) -> pathlib.Path: abc = tempdir / 'hair-particles.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_objects_only=True, flatten=False, " \ + "visible_objects_only=True, flatten=False, " \ "export_hair=%r, export_particles=%r, as_background_job=False)" \ % (abc.as_posix(), export_hair, export_particles) self.run_blender('hair-particles.blend', script) @@ -419,7 +419,7 @@ class UVMapExportTest(AbstractAlembicTest): basename = 'T77021-multiple-uvmaps-animated-mesh' abc = tempdir / f'{basename}.abc' script = f"import bpy; bpy.ops.wm.alembic_export(filepath='{abc.as_posix()}', start=1, end=1, " \ - f"renderable_only=True, visible_objects_only=True, flatten=False)" + f"visible_objects_only=True, flatten=False)" self.run_blender(f'{basename}.blend', script) self.maxDiff = 1000 @@ -468,7 +468,7 @@ class LongNamesExportTest(AbstractAlembicTest): def test_export_long_names(self, tempdir: pathlib.Path): abc = tempdir / 'long-names.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=False, visible_objects_only=False, flatten=False)" % abc.as_posix() + "visible_objects_only=False, flatten=False)" % abc.as_posix() self.run_blender('long-names.blend', script) name_parts = [ @@ -565,7 +565,7 @@ class InvisibleObjectExportTest(AbstractAlembicTest): def test_hierarchical_export(self, tempdir: pathlib.Path): abc = tempdir / 'visibility.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=2, " \ - "renderable_only=False, visible_objects_only=False)" % abc.as_posix() + "visible_objects_only=False)" % abc.as_posix() self.run_blender('visibility.blend', script) def test(cube_name: str, expect_visible: bool): diff --git a/tests/python/bl_alembic_io_test.py b/tests/python/bl_alembic_io_test.py index 53a0879f160..c0d0bcdea70 100644 --- a/tests/python/bl_alembic_io_test.py +++ b/tests/python/bl_alembic_io_test.py @@ -300,7 +300,6 @@ class CameraExportImportTest(unittest.TestCase): abc_path = self.tempdir / "camera_transforms.abc" self.assertIn('FINISHED', bpy.ops.wm.alembic_export( filepath=str(abc_path), - renderable_only=False, flatten=flatten, )) diff --git a/tests/python/bl_animation_fcurves.py b/tests/python/bl_animation_fcurves.py index 2ec04749d70..9017c1ee037 100644 --- a/tests/python/bl_animation_fcurves.py +++ b/tests/python/bl_animation_fcurves.py @@ -40,6 +40,7 @@ class AbstractAnimationTest: self.assertTrue(self.testdir.exists(), 'Test dir %s should exist' % self.testdir) + class FCurveEvaluationTest(AbstractAnimationTest, unittest.TestCase): def test_fcurve_versioning_291(self): # See D8752. diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py index 48625a1ecdb..c9c89c01cee 100644 --- a/tests/python/bl_blendfile_library_overrides.py +++ b/tests/python/bl_blendfile_library_overrides.py @@ -69,7 +69,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): assert(len(local_id.override_library.properties) == 1) override_prop = local_id.override_library.properties[0] - assert(override_prop.rna_path == "location"); + assert(override_prop.rna_path == "location") assert(len(override_prop.operations) == 1) override_operation = override_prop.operations[0] assert(override_operation.operation == 'REPLACE') @@ -96,7 +96,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): self.assertIsNone(local_id.data.override_library) assert(len(local_id.override_library.properties) == 1) override_prop = local_id.override_library.properties[0] - assert(override_prop.rna_path == "scale"); + assert(override_prop.rna_path == "scale") assert(len(override_prop.operations) == 1) override_operation = override_prop.operations[0] assert(override_operation.operation == 'NOOP') @@ -116,14 +116,14 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): assert(len(local_id.override_library.properties) == 2) override_prop = local_id.override_library.properties[0] - assert(override_prop.rna_path == "scale"); + assert(override_prop.rna_path == "scale") assert(len(override_prop.operations) == 1) override_operation = override_prop.operations[0] assert(override_operation.operation == 'NOOP') assert(override_operation.subitem_local_index == -1) override_prop = local_id.override_library.properties[1] - assert(override_prop.rna_path == "location"); + assert(override_prop.rna_path == "location") assert(len(override_prop.operations) == 1) override_operation = override_prop.operations[0] assert(override_operation.operation == 'REPLACE') diff --git a/tests/python/bl_constraints.py b/tests/python/bl_constraints.py index 279c896c6af..a2690fa4e11 100644 --- a/tests/python/bl_constraints.py +++ b/tests/python/bl_constraints.py @@ -375,6 +375,70 @@ class CustomSpaceTest(AbstractConstraintTests): ))) +class CopyTransformsTest(AbstractConstraintTests): + layer_collection = 'Copy Transforms' + + def test_mix_mode_object(self): + """Copy Transforms: all mix modes for objects""" + constraint = bpy.data.objects["Copy Transforms.object.owner"].constraints["Copy Transforms"] + + constraint.mix_mode = 'REPLACE' + self.matrix_test('Copy Transforms.object.owner', Matrix(( + (-0.7818737626075745, 0.14389121532440186, 0.4845699667930603, -0.017531070858240128), + (-0.2741589844226837, -0.591389000415802, -1.2397242784500122, -0.08039521425962448), + (0.04909384995698929, -1.0109175443649292, 0.7942137122154236, 0.1584688276052475), + (0.0, 0.0, 0.0, 1.0) + ))) + + constraint.mix_mode = 'BEFORE_FULL' + self.matrix_test('Copy Transforms.object.owner', Matrix(( + (-1.0791258811950684, -0.021011866629123688, 0.3120136260986328, 0.9082338809967041), + (0.2128538191318512, -0.3411901891231537, -1.7376484870910645, -0.39762523770332336), + (-0.03584420680999756, -1.0162957906723022, 0.8004404306411743, -0.9015425443649292), + (0.0, 0.0, 0.0, 1.0) + ))) + + constraint.mix_mode = 'BEFORE' + self.matrix_test('Copy Transforms.object.owner', Matrix(( + (-0.9952367544174194, -0.03077685832977295, 0.05301344022154808, 0.9082338809967041), + (-0.013416174799203873, -0.39984768629074097, -1.8665285110473633, -0.39762523770332336), + (0.03660336509346962, -0.9833710193634033, 0.75728839635849, -0.9015425443649292), + (0.0, 0.0, 0.0, 1.0) + ))) + + constraint.mix_mode = 'BEFORE_SPLIT' + self.matrix_test('Copy Transforms.object.owner', Matrix(( + (-0.9952367544174194, -0.03077685832977295, 0.05301344022154808, -1.0175310373306274), + (-0.013416174799203873, -0.39984768629074097, -1.8665285110473633, 0.9196047782897949), + (0.03660336509346962, -0.9833710193634033, 0.75728839635849, 0.1584688276052475), + (0.0, 0.0, 0.0, 1.0) + ))) + + constraint.mix_mode = 'AFTER_FULL' + self.matrix_test('Copy Transforms.object.owner', Matrix(( + (-0.8939255475997925, -0.2866469621658325, 0.7563635110855103, -0.964445173740387), + (-0.09460853785276413, -0.73727947473526, -1.0267245769500732, 0.9622588753700256), + (0.37042146921157837, -1.1893107891082764, 1.0113294124603271, 0.21314144134521484), + (0.0, 0.0, 0.0, 1.0) + ))) + + constraint.mix_mode = 'AFTER' + self.matrix_test('Copy Transforms.object.owner', Matrix(( + (-0.9033845067024231, -0.2048732340335846, 0.7542480826377869, -0.964445173740387), + (-0.1757974475622177, -0.6721230745315552, -1.5190268754959106, 0.9622588753700256), + (0.38079890608787537, -0.7963172793388367, 1.0880682468414307, 0.21314144134521484), + (0.0, 0.0, 0.0, 1.0) + ))) + + constraint.mix_mode = 'AFTER_SPLIT' + self.matrix_test('Copy Transforms.object.owner', Matrix(( + (-0.9033845067024231, -0.2048732340335846, 0.7542480826377869, -1.0175310373306274), + (-0.1757974475622177, -0.6721230745315552, -1.5190268754959106, 0.9196047782897949), + (0.38079890608787537, -0.7963172793388367, 1.0880682468414307, 0.1584688276052475), + (0.0, 0.0, 0.0, 1.0) + ))) + + def main(): global args import argparse diff --git a/tests/python/bl_pyapi_idprop.py b/tests/python/bl_pyapi_idprop.py index 1e570bf9a7f..38cd9d04a6b 100644 --- a/tests/python/bl_pyapi_idprop.py +++ b/tests/python/bl_pyapi_idprop.py @@ -140,6 +140,7 @@ class TestIdPropertyCreation(TestHelper, unittest.TestCase): with self.assertRaises(TypeError): self.id["a"] = self + class TestIdPropertyGroupView(TestHelper, unittest.TestCase): def test_type(self): diff --git a/tests/python/bl_run_operators_event_simulate.py b/tests/python/bl_run_operators_event_simulate.py index 92315d3e853..1cc621b9684 100644 --- a/tests/python/bl_run_operators_event_simulate.py +++ b/tests/python/bl_run_operators_event_simulate.py @@ -165,6 +165,16 @@ def gen_events_type_text(text): yield dict(type=type, value='RELEASE', **kw_extra) +def repr_action(name, args, kwargs): + return "%s(%s)" % ( + name, + ", ".join( + [repr(value) for value in args] + + [("%s=%r" % (key, value)) for key, value in kwargs.items()] + ) + ) + + # ----------------------------------------------------------------------------- # Simulate Events @@ -505,6 +515,18 @@ def argparse_create(): required=False, ) + parser.add_argument( + "--time-actions", + dest="time_actions", + default=False, + action="store_true", + help=( + "Display the time each action takes\n" + "(useful for measuring delay between key-presses)." + ), + required=False, + ) + # Collect doc-strings from static methods in `actions`. actions_docstring = [] for action_key in ACTION_DIR: @@ -554,7 +576,7 @@ def setup_default_preferences(prefs): # Main Function -def main_event_iter(*, action_list): +def main_event_iter(*, action_list, time_actions): """ Yield all events from action handlers. """ @@ -565,9 +587,18 @@ def main_event_iter(*, action_list): yield dict(type='MOUSEMOVE', value='NOTHING', x=x_init, y=y_init) + if time_actions: + import time + t_prev = time.time() + for (op, args, kwargs) in action_list: yield from handle_action(op, args, kwargs) + if time_actions: + t = time.time() + print("%.4f: %s" % ((t - t_prev), repr_action(op, args, kwargs))) + t_prev = t + def main(): from sys import argv @@ -588,7 +619,7 @@ def main(): bpy.app.use_event_simulate = False run_event_simulate( - event_iter=main_event_iter(action_list=args.actions), + event_iter=main_event_iter(action_list=args.actions, time_actions=args.time_actions), exit_fn=exit_fn, ) diff --git a/tests/python/compositor_render_tests.py b/tests/python/compositor_render_tests.py index 057d4a2e6dd..199e1c13b8e 100644 --- a/tests/python/compositor_render_tests.py +++ b/tests/python/compositor_render_tests.py @@ -16,6 +16,7 @@ try: except ImportError: inside_blender = False + def get_arguments(filepath, output_filepath): return [ "--background", diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py index 36c3f7d9fe5..ca0bc9f18b9 100644 --- a/tests/python/cycles_render_tests.py +++ b/tests/python/cycles_render_tests.py @@ -57,6 +57,7 @@ BLACKLIST_GPU = [ 'transparent_shadow_hair.*.blend', ] + def get_arguments(filepath, output_filepath): dirname = os.path.dirname(filepath) basedir = os.path.dirname(dirname) diff --git a/tests/python/modules/mesh_test.py b/tests/python/modules/mesh_test.py index 1749e798a32..6d921959e6f 100644 --- a/tests/python/modules/mesh_test.py +++ b/tests/python/modules/mesh_test.py @@ -680,7 +680,7 @@ class RunTest: test_name = each_test.test_name if self.verbose: print() - print("Running test {}/{}: {}...".format(test_number+1, len(self.tests), test_name)) + print("Running test {}/{}: {}...".format(test_number + 1, len(self.tests), test_name)) success = self.run_test(test_name) if not success: diff --git a/tests/python/modules/render_report.py b/tests/python/modules/render_report.py index c1ae0b05fcd..560f8e33585 100755 --- a/tests/python/modules/render_report.py +++ b/tests/python/modules/render_report.py @@ -287,7 +287,7 @@ class Report: -moz-background-size:50px 50px; background-size:50px 50px; - -webkit-background-size:50px 51px; /* override value for shitty webkit */ + -webkit-background-size:50px 51px; /* Override value for silly webkit. */ background-position:0 0, 25px 0, 25px -25px, 0px 25px; }} diff --git a/tests/python/operators.py b/tests/python/operators.py index c209b01c20c..4501df82175 100644 --- a/tests/python/operators.py +++ b/tests/python/operators.py @@ -321,7 +321,7 @@ def main(): MeshTest("CubeEdgeUnsubdivide", "testCubeEdgeUnsubdivide", "expectedCubeEdgeUnsubdivide", [OperatorSpecEditMode("unsubdivide", {}, "EDGE", {i for i in range(6)})]), MeshTest("UVSphereUnsubdivide", "testUVSphereUnsubdivide", "expectedUVSphereUnsubdivide", - [OperatorSpecEditMode("unsubdivide", {'iterations': 9}, "FACE", {i for i in range(512)})]), + [OperatorSpecEditMode("unsubdivide", {'iterations': 9}, "FACE", {i for i in range(512)})]), # vert connect path # Tip: It works only if there is an already existing face or more than 2 vertices. |