diff options
1143 files changed, 31906 insertions, 19323 deletions
diff --git a/.clang-format b/.clang-format index f08d62bd7b9..88d06a56417 100644 --- a/.clang-format +++ b/.clang-format @@ -256,6 +256,7 @@ ForEachMacros: - SEQ_BEGIN - SURFACE_QUAD_ITER_BEGIN - foreach + - ED_screen_areas_iter # Use once we bump the minimum version to version 8. # # Without this string literals that in-line 'STRINGIFY' behave strangely (a bug?). diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fb0393dcda..ae9f3992aa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,11 +138,6 @@ get_blender_version() #----------------------------------------------------------------------------- # Options -# First platform specific non-cached vars -if(UNIX AND NOT (APPLE OR HAIKU)) - set(WITH_X11 ON) -endif() - # Blender internal features option(WITH_BLENDER "Build blender (disable to build only the blender player)" ON) mark_as_advanced(WITH_BLENDER) @@ -207,7 +202,15 @@ mark_as_advanced(WITH_GHOST_DEBUG) option(WITH_GHOST_SDL "Enable building Blender against SDL for windowing rather than the native APIs" OFF) mark_as_advanced(WITH_GHOST_SDL) -if(WITH_X11) +if(UNIX AND NOT (APPLE OR HAIKU)) + option(WITH_GHOST_X11 "Enable building Blender against X11 for windowing" ON) + mark_as_advanced(WITH_GHOST_X11) + + option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing (under development)" OFF) + mark_as_advanced(WITH_GHOST_WAYLAND) +endif() + +if(WITH_GHOST_X11) option(WITH_GHOST_XDND "Enable drag'n'drop support on X11 using XDND protocol" ON) endif() @@ -232,7 +235,7 @@ if(UNIX AND NOT APPLE) mark_as_advanced(WITH_OPENMP_STATIC) endif() -if(WITH_X11) +if(WITH_GHOST_X11) option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON) option(WITH_X11_XF86VMODE "Enable X11 video mode switching" ON) option(WITH_X11_XFIXES "Enable X11 XWayland cursor warping workaround" ON) @@ -323,6 +326,10 @@ option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON) option(WITH_NEW_OBJECT_TYPES "Enable new hair and pointcloud objects (use for development only, don't save in files)" OFF) mark_as_advanced(WITH_NEW_OBJECT_TYPES) +# New simulation data block +option(WITH_NEW_SIMULATION_TYPE "Enable simulation data block (use for development only, don't save in files)" OFF) +mark_as_advanced(WITH_NEW_SIMULATION_TYPE) + # Misc if(WIN32) option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON) @@ -429,6 +436,8 @@ endif() option(WITH_GTESTS "Enable GTest unit testing" OFF) option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF) option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF) +set(TEST_PYTHON_EXE "" CACHE PATH "Python executable to run unit tests") +mark_as_advanced(TEST_PYTHON_EXE) # Documentation if(UNIX AND NOT APPLE) @@ -469,6 +478,8 @@ endif() if(CMAKE_COMPILER_IS_GNUCC) option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON) mark_as_advanced(WITH_LINKER_GOLD) + option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF) + mark_as_advanced(WITH_LINKER_LLD) endif() if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") @@ -532,6 +543,15 @@ if(WIN32) option(WITH_WINDOWS_BUNDLE_CRT "Bundle the C runtime for install free distribution." ON) mark_as_advanced(WITH_WINDOWS_BUNDLE_CRT) + option(WITH_WINDOWS_SCCACHE "Use sccache to speed up builds (Ninja builder only)" OFF) + mark_as_advanced(WITH_WINDOWS_SCCACHE) + + option(WITH_WINDOWS_PDB "Generate a pdb file for client side stacktraces" ON) + mark_as_advanced(WITH_WINDOWS_PDB) + + option(WITH_WINDOWS_STRIPPED_PDB "Use a stripped PDB file" On) + mark_as_advanced(WITH_WINDOWS_STRIPPED_PDB) + endif() # The following only works with the Ninja generator in CMake >= 3.0. @@ -678,7 +698,8 @@ if(WITH_INSTALL_PORTABLE) endif() if(WITH_GHOST_SDL OR WITH_HEADLESS) - set(WITH_X11 OFF) + set(WITH_GHOST_WAYLAND OFF) + set(WITH_GHOST_X11 OFF) set(WITH_X11_XINPUT OFF) set(WITH_X11_XF86VMODE OFF) set(WITH_X11_XFIXES OFF) @@ -1718,6 +1739,7 @@ if(FIRST_RUN) info_cfg_option(WITH_ALEMBIC) info_cfg_option(WITH_QUADRIFLOW) info_cfg_option(WITH_USD) + info_cfg_option(WITH_TBB) info_cfg_text("Compiler Options:") info_cfg_option(WITH_BUILDINFO) diff --git a/GNUmakefile b/GNUmakefile index 98bfded4ec7..e3bb3eaff7a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -71,17 +71,6 @@ Testing Targets which are tagged to use the stricter formatting * test_deprecated: Checks for deprecation tags in our code which may need to be removed - * test_style_c: - Checks C/C++ conforms with blenders style guide: - https://wiki.blender.org/wiki/Source/Code_Style - * test_style_c_qtc: - Same as test_style but outputs QtCreator tasks format - * test_style_osl: - Checks OpenShadingLanguage conforms with blenders style guide: - https://wiki.blender.org/wiki/Source/Code_Style - * test_style_osl_qtc: - Checks OpenShadingLanguage conforms with blenders style guide: - https://wiki.blender.org/wiki/Source/Code_Style Static Source Code Checking Not associated with building Blender. @@ -402,45 +391,6 @@ test_cmake: .FORCE test_deprecated: .FORCE $(PYTHON) tests/check_deprecated.py -test_style_c: .FORCE - # run our own checks on C/C++ style - PYTHONIOENCODING=utf_8 $(PYTHON) \ - "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \ - "$(BLENDER_DIR)/source/blender" \ - "$(BLENDER_DIR)/source/creator" \ - --no-length-check - -test_style_c_qtc: .FORCE - # run our own checks on C/C++ style - USE_QTC_TASK=1 \ - PYTHONIOENCODING=utf_8 $(PYTHON) \ - "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \ - "$(BLENDER_DIR)/source/blender" \ - "$(BLENDER_DIR)/source/creator" \ - --no-length-check \ - > \ - "$(BLENDER_DIR)/test_style.tasks" - @echo "written: test_style.tasks" - - -test_style_osl: .FORCE - # run our own checks on C/C++ style - PYTHONIOENCODING=utf_8 $(PYTHON) \ - "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \ - "$(BLENDER_DIR)/intern/cycles/kernel/shaders" \ - "$(BLENDER_DIR)/release/scripts/templates_osl" - - -test_style_osl_qtc: .FORCE - # run our own checks on C/C++ style - USE_QTC_TASK=1 \ - PYTHONIOENCODING=utf_8 $(PYTHON) \ - "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \ - "$(BLENDER_DIR)/intern/cycles/kernel/shaders" \ - "$(BLENDER_DIR)/release/scripts/templates_osl" \ - > \ - "$(BLENDER_DIR)/test_style.tasks" - @echo "written: test_style.tasks" # ----------------------------------------------------------------------------- # Project Files diff --git a/build_files/build_environment/cmake/jpeg.cmake b/build_files/build_environment/cmake/jpeg.cmake index 47f526e3d29..0d611219353 100644 --- a/build_files/build_environment/cmake/jpeg.cmake +++ b/build_files/build_environment/cmake/jpeg.cmake @@ -18,7 +18,7 @@ if(WIN32) # cmake for windows - set(JPEG_EXTRA_ARGS -DNASM=${NASM_PATH} -DWITH_JPEG8=ON -DCMAKE_DEBUG_POSTFIX=d) + set(JPEG_EXTRA_ARGS -DNASM=${NASM_PATH} -DWITH_JPEG8=ON -DCMAKE_DEBUG_POSTFIX=d -DWITH_CRT_DLL=On) ExternalProject_Add(external_jpeg URL ${JPEG_URI} diff --git a/build_files/build_environment/cmake/openimagedenoise.cmake b/build_files/build_environment/cmake/openimagedenoise.cmake index b20bb838ede..1332a38fea6 100644 --- a/build_files/build_environment/cmake/openimagedenoise.cmake +++ b/build_files/build_environment/cmake/openimagedenoise.cmake @@ -21,7 +21,7 @@ set(OIDN_EXTRA_ARGS -DWITH_EXAMPLE=OFF -DWITH_TEST=OFF -DTBB_ROOT=${LIBDIR}/tbb - -DTBB_STATIC_LIB=ON + -DTBB_STATIC_LIB=${TBB_STATIC_LIBRARY} -DOIDN_STATIC_LIB=ON ) diff --git a/build_files/build_environment/cmake/opensubdiv.cmake b/build_files/build_environment/cmake/opensubdiv.cmake index 5c1ebe46a20..9ec849a219b 100644 --- a/build_files/build_environment/cmake/opensubdiv.cmake +++ b/build_files/build_environment/cmake/opensubdiv.cmake @@ -36,7 +36,7 @@ if(WIN32) set(OPENSUBDIV_EXTRA_ARGS ${OPENSUBDIV_EXTRA_ARGS} -DTBB_INCLUDE_DIR=${LIBDIR}/tbb/include - -DTBB_LIBRARIES=${LIBDIR}/tbb/lib/tbb_static.lib + -DTBB_LIBRARIES=${LIBDIR}/tbb/lib/tbb.lib -DCLEW_INCLUDE_DIR=${LIBDIR}/clew/include/CL -DCLEW_LIBRARY=${LIBDIR}/clew/lib/clew${LIBEXT} -DCUEW_INCLUDE_DIR=${LIBDIR}/cuew/include diff --git a/build_files/build_environment/cmake/pthreads.cmake b/build_files/build_environment/cmake/pthreads.cmake index c5c331117fc..7ddf6867e2b 100644 --- a/build_files/build_environment/cmake/pthreads.cmake +++ b/build_files/build_environment/cmake/pthreads.cmake @@ -24,7 +24,7 @@ if(WIN32) set(PTHREAD_CPPFLAGS "/I. /DHAVE_CONFIG_H ") endif() - set(PTHREADS_BUILD cd ${BUILD_DIR}/pthreads/src/external_pthreads/ && cd && nmake VC-static /e CPPFLAGS=${PTHREAD_CPPFLAGS} /e XLIBS=/NODEFAULTLIB:msvcr) + set(PTHREADS_BUILD cd ${BUILD_DIR}/pthreads/src/external_pthreads/ && cd && nmake VC-static /e CPPFLAGS=${PTHREAD_CPPFLAGS}) ExternalProject_Add(external_pthreads URL ${PTHREADS_URI} @@ -32,6 +32,7 @@ if(WIN32) URL_HASH MD5=${PTHREADS_HASH} PREFIX ${BUILD_DIR}/pthreads CONFIGURE_COMMAND echo . + PATCH_COMMAND COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/pthreads/src/external_pthreads < ${PATCH_DIR}/pthreads.diff BUILD_COMMAND ${PTHREADS_BUILD} INSTALL_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/libpthreadVC3${LIBEXT} ${LIBDIR}/pthreads/lib/pthreadVC3${LIBEXT} && diff --git a/build_files/build_environment/cmake/tbb.cmake b/build_files/build_environment/cmake/tbb.cmake index 8bd2f3160d0..1cb852fb5d1 100644 --- a/build_files/build_environment/cmake/tbb.cmake +++ b/build_files/build_environment/cmake/tbb.cmake @@ -20,8 +20,10 @@ if(WIN32) -DTBB_BUILD_SHARED=On -DTBB_BUILD_TBBMALLOC=On -DTBB_BUILD_TBBMALLOC_PROXY=On - -DTBB_BUILD_STATIC=On -) + -DTBB_BUILD_STATIC=Off + ) + set(TBB_LIBRARY tbb) + set(TBB_STATIC_LIBRARY Off) else() set(TBB_EXTRA_ARGS -DTBB_BUILD_SHARED=Off @@ -29,6 +31,8 @@ else() -DTBB_BUILD_TBBMALLOC_PROXY=Off -DTBB_BUILD_STATIC=On ) + set(TBB_LIBRARY tbb_static) + set(TBB_STATIC_LIBRARY On) endif() # CMake script for TBB from https://github.com/wjakob/tbb/blob/master/CMakeLists.txt @@ -46,7 +50,8 @@ ExternalProject_Add(external_tbb if(WIN32) if(BUILD_MODE STREQUAL Release) ExternalProject_Add_Step(external_tbb after_install - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_static.lib ${HARVEST_TARGET}/tbb/lib/tbb.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.lib ${HARVEST_TARGET}/tbb/lib/tbb.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.dll ${HARVEST_TARGET}/tbb/lib/tbb.dll COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.dll ${HARVEST_TARGET}/tbb/lib/tbbmalloc.dll COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy.lib @@ -57,7 +62,12 @@ if(WIN32) endif() if(BUILD_MODE STREQUAL Debug) ExternalProject_Add_Step(external_tbb after_install - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_static.lib ${HARVEST_TARGET}/tbb/lib/tbb_debug.lib + # findtbb.cmake in some deps *NEEDS* to find tbb.lib even if they are not going to use it + # to make that test pass, we place a copy with the right name in the lib folder. + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.lib ${LIBDIR}/tbb/lib/tbb.lib + # Normal collection of build artifacts + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.lib ${HARVEST_TARGET}/tbb/lib/debug/tbb_debug.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.dll ${HARVEST_TARGET}/tbb/lib/debug/tbb_debug.dll COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy_debug.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.dll ${HARVEST_TARGET}/tbb/lib/debug/tbbmalloc.dll COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.dll ${HARVEST_TARGET}/tbb/lib/debug/tbbmalloc_proxy.dll diff --git a/build_files/build_environment/cmake/usd.cmake b/build_files/build_environment/cmake/usd.cmake index c3594390f80..505607535e9 100644 --- a/build_files/build_environment/cmake/usd.cmake +++ b/build_files/build_environment/cmake/usd.cmake @@ -23,8 +23,8 @@ set(USD_EXTRA_ARGS -DBoost_USE_STATIC_RUNTIME=OFF -DBOOST_ROOT=${LIBDIR}/boost -DTBB_INCLUDE_DIRS=${LIBDIR}/tbb/include - -DTBB_LIBRARIES=${LIBDIR}/tbb/lib/${LIBPREFIX}tbb_static${LIBEXT} - -DTbb_TBB_LIBRARY=${LIBDIR}/tbb/lib/${LIBPREFIX}tbb_static${LIBEXT} + -DTBB_LIBRARIES=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT} + -DTbb_TBB_LIBRARY=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT} # This is a preventative measure that avoids possible conflicts when add-ons # try to load another USD library into the same process space. diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 6a247e81148..5f73756ec0b 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -53,15 +53,15 @@ getopt \ --long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,\ with-all,with-opencollada,with-jack,with-embree,with-oidn,\ ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,ver-xr-openxr:,\ -force-all,force-python,force-numpy,force-boost,\ +force-all,force-python,force-numpy,force-boost,force-tbb,\ force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\ force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,force-usd,\ force-xr-openxr,\ -build-all,build-python,build-numpy,build-boost,\ +build-all,build-python,build-numpy,build-boost,build-tbb,\ build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\ build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,build-usd,\ build-xr-openxr,\ -skip-python,skip-numpy,skip-boost,\ +skip-python,skip-numpy,skip-boost,skip-tbb,\ skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\ skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-usd,\ skip-xr-openxr \ @@ -191,6 +191,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --build-boost Force the build of Boost. + --build-tbb + Force the build of TBB. + --build-ocio Force the build of OpenColorIO. @@ -255,6 +258,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --force-boost Force the rebuild of Boost. + --force-tbb + Force the rebuild of TBB. + --force-ocio Force the rebuild of OpenColorIO. @@ -312,6 +318,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --skip-boost Unconditionally skip Boost installation/building. + --skip-tbb + Unconditionally skip TBB installation/building. + --skip-ocio Unconditionally skip OpenColorIO installation/building. @@ -385,6 +394,13 @@ BOOST_FORCE_BUILD=false BOOST_FORCE_REBUILD=false BOOST_SKIP=false +TBB_VERSION="2019" +TBB_VERSION_UPDATE="_U9" # Used for source packages... +TBB_VERSION_MIN="2018" +TBB_FORCE_BUILD=false +TBB_FORCE_REBUILD=false +TBB_SKIP=false + OCIO_VERSION="1.1.0" OCIO_VERSION_MIN="1.0" OCIO_FORCE_BUILD=false @@ -653,6 +669,7 @@ while true; do PYTHON_FORCE_BUILD=true NUMPY_FORCE_BUILD=true BOOST_FORCE_BUILD=true + TBB_FORCE_BUILD=true OCIO_FORCE_BUILD=true OPENEXR_FORCE_BUILD=true OIIO_FORCE_BUILD=true @@ -682,6 +699,9 @@ while true; do --build-boost) BOOST_FORCE_BUILD=true; shift; continue ;; + --build-tbb) + TBB_FORCE_BUILD=true; shift; continue + ;; --build-ocio) OCIO_FORCE_BUILD=true; shift; continue ;; @@ -728,6 +748,7 @@ while true; do PYTHON_FORCE_REBUILD=true NUMPY_FORCE_REBUILD=true BOOST_FORCE_REBUILD=true + TBB_FORCE_REBUILD=true OCIO_FORCE_REBUILD=true OPENEXR_FORCE_REBUILD=true OIIO_FORCE_REBUILD=true @@ -755,6 +776,9 @@ while true; do --force-boost) BOOST_FORCE_REBUILD=true; shift; continue ;; + --force-tbb) + TBB_FORCE_REBUILD=true; shift; continue + ;; --force-ocio) OCIO_FORCE_REBUILD=true; shift; continue ;; @@ -806,6 +830,9 @@ while true; do --skip-boost) BOOST_SKIP=true; shift; continue ;; + --skip-tbb) + TBB_SKIP=true; shift; continue + ;; --skip-ocio) OCIO_SKIP=true; shift; continue ;; @@ -898,9 +925,12 @@ PYTHON_SOURCE=( "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHO NUMPY_SOURCE=( "https://github.com/numpy/numpy/releases/download/v$NUMPY_VERSION/numpy-$NUMPY_VERSION.tar.gz" ) _boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'` -BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" ) +BOOST_SOURCE=( "https://dl.bintray.com/boostorg/release/$BOOST_VERSION/source/boost_$_boost_version_nodots.tar.bz2" ) BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options" +TBB_SOURCE=( "https://github.com/oneapi-src/oneTBB/archive/$TBB_VERSION$TBB_VERSION_UPDATE.tar.gz" ) +TBB_SOURCE_CMAKE=( "https://raw.githubusercontent.com/wjakob/tbb/master/CMakeLists.txt" ) + OCIO_USE_REPO=false OCIO_SOURCE=( "https://github.com/AcademySoftwareFoundation/OpenColorIO/archive/v$OCIO_VERSION.tar.gz") #~ OCIO_SOURCE_REPO=( "https://github.com/imageworks/OpenColorIO.git" ) @@ -1011,6 +1041,7 @@ You may also want to build them yourself (optional ones are [between brackets]): * Python $PYTHON_VERSION_MIN (from $PYTHON_SOURCE). * [NumPy $NUMPY_VERSION_MIN] (from $NUMPY_SOURCE). * Boost $BOOST_VERSION_MIN (from $BOOST_SOURCE, modules: $BOOST_BUILD_MODULES). + * TBB $TBB_VERSION_MIN (from $TBB_SOURCE). * [FFMpeg $FFMPEG_VERSION_MIN (needs libvorbis, libogg, libtheora, libx264, libmp3lame, libxvidcore, libvpx, ...)] (from $FFMPEG_SOURCE). * [OpenColorIO $OCIO_VERSION_MIN] (from $OCIO_SOURCE). * ILMBase $OPENEXR_VERSION_MIN (from $OPENEXR_SOURCE). @@ -1248,8 +1279,10 @@ _update_deps_python() { clean_Python() { clean_Numpy _init_python + if [ -d $_inst ]; then + _update_deps_python + fi _clean - _update_deps_python } compile_Python() { @@ -1332,8 +1365,10 @@ _update_deps_numpy() { clean_Numpy() { _init_numpy + if [ -d $_inst ]; then + _update_deps_numpy + fi _clean - _update_deps_numpy } compile_Numpy() { @@ -1418,8 +1453,10 @@ _update_deps_boost() { clean_Boost() { _init_boost + if [ -d $_inst ]; then + _update_deps_boost + fi _clean - _update_deps_boost } compile_Boost() { @@ -1485,6 +1522,128 @@ compile_Boost() { } # ---------------------------------------------------------------------------- +# Build TBB + +_init_tbb() { + _src=$SRC/TBB-$TBB_VERSION + _git=false + _inst=$INST/tbb-$TBB_VERSION + _inst_shortcut=$INST/tbb +} + +_update_deps_tbb() { + OSD_FORCE_REBUILD=true + OPENVDB_FORCE_REBUILD=true + USD_FORCE_REBUILD=true + OIDN_FORCE_REBUILD=true + if [ "$_is_building" = true ]; then + OSD_FORCE_BUILD=true + OPENVDB_FORCE_BUILD=true + USD_FORCE_BUILD=true + OIDN_FORCE_BUILD=true + fi +} + +clean_TBB() { + _init_tbb + if [ -d $_inst ]; then + _update_deps_tbb + fi + _clean +} + +compile_TBB() { + if [ "$NO_BUILD" = true ]; then + WARNING "--no-build enabled, TBB will not be compiled!" + return + fi + + # To be changed each time we make edits that would modify the compiled result! + tbb_magic=0 + _init_tbb + + # Clean install if needed! + magic_compile_check tbb-$TBB_VERSION $tbb_magic + if [ $? -eq 1 -o "$TBB_FORCE_REBUILD" = true ]; then + clean_TBB + fi + + if [ ! -d $_inst ]; then + INFO "Building TBB-$TBB_VERSION$TBB_VERSION_UPDATE" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_tbb + + prepare_opt + + if [ ! -d $_src ]; then + INFO "Downloading TBB-$TBB_VERSION$TBB_VERSION_UPDATE" + mkdir -p $SRC + + download TBB_SOURCE[@] $_src.tar.gz + INFO "Unpacking TBB-$TBB_VERSION$TBB_VERSION_UPDATE" + tar -C $SRC --transform "s,(.*/?)oneTBB[^/]*(.*),\1TBB-$TBB_VERSION\2,x" \ + -xf $_src.tar.gz + + INFO + + # Super-hack: Add some cmake builder to tbb... since they don't even have an install target by default, sic. + download TBB_SOURCE_CMAKE[@] $_src/CMakeLists.txt + cp $_src/build/vs2013/version_string.ver $_src/build/version_string.ver.in + fi + + cd $_src + + # Always refresh the whole build! + if [ -d cmake_build ]; then + rm -rf cmake_build + fi + mkdir cmake_build + cd cmake_build + + cmake_d="-D CMAKE_BUILD_TYPE=Release" + cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" + cmake_d="$cmake_d -D TBB_BUILD_SHARED=ON" + cmake_d="$cmake_d -D TBB_BUILD_STATIC=OFF" + cmake_d="$cmake_d -D TBB_BUILD_TBBMALLOC=ON" + cmake_d="$cmake_d -D TBB_BUILD_TBBMALLOC_PROXY=OFF" + cmake_d="$cmake_d -D TBB_BUILD_TESTS=OFF" + + if file /bin/cp | grep -q '32-bit'; then + cflags="-fPIC -m32 -march=i686" + else + cflags="-fPIC" + fi + + cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" .. + + make -j$THREADS && make install + + make clean + + if [ -d $_inst ]; then + _create_inst_shortcut + else + ERROR "TBB-$TBB_VERSION$TBB_VERSION_UPDATE failed to compile, exiting" + exit 1 + fi + + magic_compile_set tbb-$TBB_VERSION $tbb_magic + + cd $CWD + INFO "Done compiling TBB-$TBB_VERSION$TBB_VERSION_UPDATE!" + _is_building=false + else + INFO "Own TBB-$TBB_VERSION$TBB_VERSION_UPDATE is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-tbb option." + fi + + run_ldconfig "tbb" +} + +# ---------------------------------------------------------------------------- # Build OCIO _init_ocio() { @@ -1504,8 +1663,10 @@ _update_deps_ocio() { clean_OCIO() { _init_ocio + if [ -d $_inst ]; then + _update_deps_ocio + fi _clean - _update_deps_ocio } compile_OCIO() { @@ -1617,7 +1778,7 @@ compile_OCIO() { _init_openexr() { _src=$SRC/OpenEXR-$OPENEXR_VERSION _git=false - _inst=$_openexr_inst + _inst=$INST/openexr-$OPENEXR_VERSION _inst_shortcut=$INST/openexr } @@ -1632,8 +1793,10 @@ _update_deps_openexr() { clean_OPENEXR() { _init_openexr + if [ -d $_inst ]; then + _update_deps_openexr + fi _clean - _update_deps_openexr } compile_OPENEXR() { @@ -1651,7 +1814,6 @@ compile_OPENEXR() { clean_OPENEXR fi - _openexr_inst=$INST/openexr-$OPENEXR_VERSION PRINT "" _init_openexr @@ -1697,7 +1859,7 @@ compile_OPENEXR() { mkdir build cd build - cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_openexr_inst" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" cmake_d="$cmake_d -D CMAKE_INSTALL_DOCDIR=/dev/null" # Hack, there is no option to disable that currently... cmake_d="$cmake_d -D BUILD_SHARED_LIBS=ON" cmake_d="$cmake_d -D BUILD_TESTING=OFF" @@ -1759,8 +1921,10 @@ _update_deps_oiio() { clean_OIIO() { _init_oiio + if [ -d $_inst ]; then + _update_deps_oiio + fi _clean - _update_deps_oiio } compile_OIIO() { @@ -1912,8 +2076,10 @@ _update_deps_llvm() { clean_LLVM() { _init_llvm + if [ -d $_inst ]; then + _update_deps_llvm + fi _clean - _update_deps_llvm } compile_LLVM() { @@ -2019,8 +2185,10 @@ _update_deps_osl() { clean_OSL() { _init_osl + if [ -d $_inst ]; then + _update_deps_osl + fi _clean - _update_deps_osl } compile_OSL() { @@ -2162,8 +2330,10 @@ _update_deps_osd() { clean_OSD() { _init_osd + if [ -d $_inst ]; then + _update_deps_osd + fi _clean - _update_deps_osd } compile_OSD() { @@ -2222,6 +2392,9 @@ compile_OSD() { mkdir build cd build + if [ -d $INST/tbb ]; then + cmake_d="$cmake_d $cmake_d -D TBB_LOCATION=$INST/tbb" + fi cmake_d="-D CMAKE_BUILD_TYPE=Release" cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" # ptex is only needed when nicholas bishop is ready @@ -2274,8 +2447,10 @@ _update_deps_blosc() { clean_BLOSC() { _init_blosc + if [ -d $_inst ]; then + _update_deps_blosc + fi _clean - _update_deps_blosc } compile_BLOSC() { @@ -2369,8 +2544,10 @@ _update_deps_openvdb() { clean_OPENVDB() { _init_openvdb + if [ -d $_inst ]; then + _update_deps_openvdb + fi _clean - _update_deps_openvdb } compile_OPENVDB() { @@ -2429,6 +2606,9 @@ compile_OPENVDB() { if [ -d $INST/boost ]; then make_d="$make_d BOOST_INCL_DIR=$INST/boost/include BOOST_LIB_DIR=$INST/boost/lib" fi + if [ -d $INST/tbb ]; then + make_d="$make_d TBB_ROOT=$INST/tbb TBB_USE_STATIC_LIBS=OFF" + fi if [ "$_with_built_openexr" = true ]; then make_d="$make_d ILMBASE_INCL_DIR=$INST/openexr/include ILMBASE_LIB_DIR=$INST/openexr/lib" @@ -2482,8 +2662,10 @@ _update_deps_alembic() { clean_ALEMBIC() { _init_alembic + if [ -d $_inst ]; then + _update_deps_alembic + fi _clean - _update_deps_alembic } compile_ALEMBIC() { @@ -2585,8 +2767,10 @@ _update_deps_usd() { clean_USD() { _init_usd + if [ -d $_inst ]; then + _update_deps_usd + fi _clean - _update_deps_usd } compile_USD() { @@ -2630,6 +2814,10 @@ compile_USD() { if [ -d $INST/boost ]; then cmake_d="$cmake_d $cmake_d -D BOOST_ROOT=$INST/boost" fi + + if [ -d $INST/tbb ]; then + cmake_d="$cmake_d $cmake_d -D TBB_ROOT_DIR=$INST/tbb" + fi cmake_d="$cmake_d -DPXR_SET_INTERNAL_NAMESPACE=usdBlender" cmake_d="$cmake_d -DPXR_ENABLE_PYTHON_SUPPORT=OFF" cmake_d="$cmake_d -DPXR_BUILD_IMAGING=OFF" @@ -2678,8 +2866,10 @@ _update_deps_collada() { clean_OpenCOLLADA() { _init_opencollada + if [ -d $_inst ]; then + _update_deps_collada + fi _clean - _update_deps_collada } compile_OpenCOLLADA() { @@ -2782,8 +2972,10 @@ _update_deps_embree() { clean_Embree() { _init_embree + if [ -d $_inst ]; then + _update_deps_embree + fi _clean - _update_deps_embree } compile_Embree() { @@ -2889,8 +3081,10 @@ _update_deps_oidn() { clean_oidn() { _init_oidn + if [ -d $_inst ]; then + _update_deps_oidn + fi _clean - _update_deps_oidn } compile_OIDN() { @@ -2952,6 +3146,10 @@ compile_OIDN() { cmake_d="$cmake_d -D WITH_TEST=OFF" cmake_d="$cmake_d -D OIDN_STATIC_LIB=ON" + if [ -d $INST/tbb ]; then + make_d="$make_d TBB_ROOT=$INST/tbb" + fi + cmake $cmake_d ../ make -j$THREADS && make install @@ -2992,8 +3190,10 @@ _update_deps_ffmpeg() { clean_FFmpeg() { _init_ffmpeg + if [ -d $_inst ]; then + _update_deps_ffmpeg + fi _clean - _update_deps_ffmpeg } compile_FFmpeg() { @@ -3119,8 +3319,10 @@ _update_deps_xr_openxr_sdk() { clean_XR_OpenXR_SDK() { _init_xr_openxr_sdk + if [ -d $_inst ]; then + _update_deps_xr_openxr_sdk + fi _clean - _update_deps_xr_openxr_sdk } compile_XR_OpenXR_SDK() { @@ -3134,7 +3336,7 @@ compile_XR_OpenXR_SDK() { _init_xr_openxr_sdk # Clean install if needed! - magic_compile_check xr-openxr-$OPENXR_VERSION $xr_openxr_magic + magic_compile_check xr-openxr-$XR_OPENXR_VERSION $xr_openxr_magic if [ $? -eq 1 -o "$XR_OPENXR_FORCE_REBUILD" = true ]; then clean_XR_OpenXR_SDK fi @@ -3311,7 +3513,7 @@ install_DEB() { THEORA_DEV="libtheora-dev" _packages="gawk cmake cmake-curses-gui build-essential libjpeg-dev libpng-dev libtiff-dev \ - git libfreetype6-dev libx11-dev flex bison libtbb-dev libxxf86vm-dev \ + git libfreetype6-dev libx11-dev flex bison libxxf86vm-dev \ libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \ libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \ libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \ @@ -3521,6 +3723,23 @@ install_DEB() { PRINT "" + if [ "$TBB_SKIP" = true ]; then + WARNING "Skipping TBB installation, as requested..." + elif [ "$TBB_FORCE_BUILD" = true ]; then + INFO "Forced TBB building, as requested..." + compile_TBB + else + check_package_version_ge_DEB libtbb-dev $TBB_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB libtbb-dev + clean_TBB + else + compile_TBB + fi + fi + + + PRINT "" if [ "$OCIO_SKIP" = true ]; then WARNING "Skipping OpenColorIO installation, as requested..." elif [ "$OCIO_FORCE_BUILD" = true ]; then @@ -3956,7 +4175,7 @@ install_RPM() { THEORA_USE=true if [ "$RPM" = "FEDORA" -o "$RPM" = "RHEL" ]; then - _packages="$_packages freetype-devel tbb-devel" + _packages="$_packages freetype-devel" if [ "$WITH_JACK" = true ]; then _packages="$_packages jack-audio-connection-kit-devel" @@ -3998,17 +4217,6 @@ install_RPM() { install_packages_RPM $_packages PRINT "" - # Install TBB on openSUSE, from temporary repo - check_package_RPM tbb-devel - if [ $? -eq 0 ]; then - install_packages_RPM tbb-devel - else - $SUDO zypper ar -f http://download.opensuse.org/repositories/devel:/libraries:/c_c++/openSUSE_$_suse_rel/devel:libraries:c_c++.repo - $SUDO zypper -n --gpg-auto-import-keys install tbb-devel - $SUDO zypper rr devel_libraries_c_c++ - fi - - PRINT "" X264_DEV="libx264-devel" check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN if [ $? -eq 0 ]; then @@ -4144,6 +4352,23 @@ install_RPM() { PRINT "" + if [ "$TBB_SKIP" = true ]; then + WARNING "Skipping TBB installation, as requested..." + elif [ "$TBB_FORCE_BUILD" = true ]; then + INFO "Forced TBB building, as requested..." + compile_TBB + else + check_package_version_ge_RPM tbb-devel $TBB_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM tbb-devel + clean_TBB + else + compile_TBB + fi + fi + + + PRINT "" if [ "$OCIO_SKIP" = true ]; then WARNING "Skipping OpenColorIO installation, as requested..." elif [ "$OCIO_FORCE_BUILD" = true ]; then @@ -4499,7 +4724,7 @@ install_ARCH() { _packages="$BASE_DEVEL git cmake \ libxi libxcursor libxrandr libxinerama glew libpng libtiff wget openal \ - $OPENJPEG_DEV $VORBIS_DEV $OGG_DEV $THEORA_DEV yasm sdl fftw intel-tbb \ + $OPENJPEG_DEV $VORBIS_DEV $OGG_DEV $THEORA_DEV yasm sdl fftw \ libxml2 yaml-cpp tinyxml python-requests jemalloc" OPENJPEG_USE=true @@ -4639,6 +4864,23 @@ install_ARCH() { PRINT "" + if [ "$TBB_SKIP" = true ]; then + WARNING "Skipping TBB installation, as requested..." + elif [ "$TBB_FORCE_BUILD" = true ]; then + INFO "Forced TBB building, as requested..." + compile_TBB + else + check_package_version_ge_ARCH intel-tbb $TBB_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_ARCH intel-tbb + clean_TBB + else + compile_TBB + fi + fi + + + PRINT "" if [ "$OCIO_SKIP" = true ]; then WARNING "Skipping OpenColorIO installation, as requested..." elif [ "$OCIO_FORCE_BUILD" = true ]; then @@ -4932,15 +5174,10 @@ install_OTHER() { fi PRINT "" - _do_compile_python=false if [ "$PYTHON_SKIP" = true ]; then WARNING "Skipping Python/NumPy installation, as requested..." elif [ "$PYTHON_FORCE_BUILD" = true ]; then INFO "Forced Python/NumPy building, as requested..." - _do_compile_python=true - fi - - if [ "$_do_compile_python" = true ]; then compile_Python PRINT "" if [ "$NUMPY_SKIP" = true ]; then @@ -4961,6 +5198,15 @@ install_OTHER() { PRINT "" + if [ "$TBB_SKIP" = true ]; then + WARNING "Skipping TBB installation, as requested..." + elif [ "$TBB_FORCE_BUILD" = true ]; then + INFO "Forced TBB building, as requested..." + compile_TBB + fi + + + PRINT "" if [ "$OCIO_SKIP" = true ]; then WARNING "Skipping OpenColorIO installation, as requested..." elif [ "$OCIO_FORCE_BUILD" = true ]; then @@ -4989,16 +5235,10 @@ install_OTHER() { PRINT "" have_llvm=false - _do_compile_llvm=false if [ "$LLVM_SKIP" = true ]; then WARNING "Skipping LLVM installation, as requested (this also implies skipping OSL!)..." elif [ "$LLVM_FORCE_BUILD" = true ]; then INFO "Forced LLVM building, as requested..." - _do_compile_llvm=true - fi - - if [ "$_do_compile_llvm" = true ]; then - PRINT "" compile_LLVM have_llvm=true LLVM_VERSION_FOUND=$LLVM_VERSION @@ -5006,15 +5246,10 @@ install_OTHER() { PRINT "" - _do_compile_osl=false if [ "$OSL_SKIP" = true ]; then WARNING "Skipping OpenShadingLanguage installation, as requested..." elif [ "$OSL_FORCE_BUILD" = true ]; then INFO "Forced OpenShadingLanguage building, as requested..." - _do_compile_osl=true - fi - - if [ "$_do_compile_osl" = true ]; then if [ "$have_llvm" = true ]; then PRINT "" compile_OSL @@ -5025,66 +5260,40 @@ install_OTHER() { PRINT "" - _do_compile_osd=false if [ "$OSD_SKIP" = true ]; then WARNING "Skipping OpenSubdiv installation, as requested..." elif [ "$OSD_FORCE_BUILD" = true ]; then INFO "Forced OpenSubdiv building, as requested..." - _do_compile_osd=true - fi - - if [ "$_do_compile_osd" = true ]; then - PRINT "" compile_OSD fi if [ "$WITH_OPENCOLLADA" = true ]; then - _do_compile_collada=false PRINT "" if [ "$OPENCOLLADA_SKIP" = true ]; then WARNING "Skipping OpenCOLLADA installation, as requested..." elif [ "$OPENCOLLADA_FORCE_BUILD" = true ]; then INFO "Forced OpenCollada building, as requested..." - _do_compile_collada=true - fi - - if [ "$_do_compile_collada" = true ]; then - PRINT "" compile_OpenCOLLADA fi fi if [ "$WITH_EMBREE" = true ]; then - _do_compile_embree=false PRINT "" if [ "$EMBREE_SKIP" = true ]; then WARNING "Skipping Embree installation, as requested..." elif [ "$EMBREE_FORCE_BUILD" = true ]; then INFO "Forced Embree building, as requested..." - _do_compile_embree=true - fi - - if [ "$_do_compile_embree" = true ]; then - PRINT "" compile_Embree fi fi if [ "$WITH_OIDN" = true ]; then - _do_compile_oidn=false PRINT "" if [ "$OIDN_SKIP" = true ]; then WARNING "Skipping OpenImgeDenoise installation, as requested..." elif [ "$OIDN_FORCE_BUILD" = true ]; then INFO "Forced OpenImageDenoise building, as requested..." - _do_compile_oidn=true - else - # No package currently! - _do_compile_oidn=true - fi - - if [ "$_do_compile_oidn" = true ]; then compile_OIDN fi fi @@ -5103,9 +5312,6 @@ install_OTHER() { elif [ "$XR_OPENXR_FORCE_BUILD" = true ]; then INFO "Forced OpenXR-SDK building, as requested..." compile_XR_OpenXR_SDK - else - # No package currently! - compile_XR_OpenXR_SDK fi } @@ -5191,7 +5397,7 @@ print_info() { PRINT "" PRINT "If you're using CMake add this to your configuration flags:" - _buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost*" + _buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost* -U *TBB*" _buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*" _buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*" @@ -5216,6 +5422,12 @@ print_info() { _buildargs="$_buildargs $_1 $_2" fi + if [ -d $INST/tbb ]; then + _1="-D TBB_ROOT_DIR=$INST/tbb" + PRINT " $_1" + _buildargs="$_buildargs $_1" + fi + if [ "$OCIO_SKIP" = false ]; then _1="-D WITH_OPENCOLORIO=ON" PRINT " $_1" diff --git a/build_files/build_environment/patches/cmakelists_tbb.txt b/build_files/build_environment/patches/cmakelists_tbb.txt index da9fd938943..7edf3aa2785 100644 --- a/build_files/build_environment/patches/cmakelists_tbb.txt +++ b/build_files/build_environment/patches/cmakelists_tbb.txt @@ -109,6 +109,9 @@ if (WIN32) MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/${ARCH_PREFIX}-tbbmalloc-export.def COMMENT "Preprocessing tbbmalloc.def" ) + list(APPEND tbb_src ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/tbb_resource.rc) + list(APPEND tbbmalloc_src ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/tbbmalloc.rc) + list(APPEND tbbmalloc_proxy_src ${CMAKE_CURRENT_SOURCE_DIR}/src/tbbmalloc/tbbmalloc.rc) else() add_custom_command(OUTPUT tbb.def COMMAND ${CMAKE_CXX_COMPILER} -xc++ -E ${CMAKE_CURRENT_SOURCE_DIR}/src/tbb/${ARCH_PREFIX}-tbb-export.def -I ${CMAKE_CURRENT_SOURCE_DIR}/include -o tbb.def @@ -145,8 +148,12 @@ if (TBB_BUILD_SHARED) set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "-Wl,-version-script,${CMAKE_CURRENT_BINARY_DIR}/tbb.def") elseif(WIN32) set_property(TARGET tbb APPEND PROPERTY LINK_FLAGS "/DEF:${CMAKE_CURRENT_BINARY_DIR}/tbb.def") + endif() install(TARGETS tbb DESTINATION lib) + if(WIN32) + set_target_properties(tbb PROPERTIES OUTPUT_NAME "tbb$<$<CONFIG:Debug>:_debug>") + endif() endif() if(CMAKE_COMPILER_IS_GNUCC) @@ -196,7 +203,7 @@ if(TBB_BUILD_TBBMALLOC_PROXY) add_library(tbbmalloc_proxy SHARED ${tbbmalloc_proxy_src}) set_property(TARGET tbbmalloc_proxy APPEND PROPERTY COMPILE_DEFINITIONS "__TBBMALLOC_BUILD=1") set_property(TARGET tbbmalloc_proxy APPEND_STRING PROPERTY COMPILE_FLAGS ${DISABLE_RTTI}) - link_libraries(tbbmalloc_proxy tbbmalloc) + target_link_libraries(tbbmalloc_proxy tbbmalloc) install(TARGETS tbbmalloc_proxy DESTINATION lib) endif() endif() diff --git a/build_files/build_environment/patches/openimagedenoise.diff b/build_files/build_environment/patches/openimagedenoise.diff index f83b0776c30..7bfc3aa2eba 100644 --- a/build_files/build_environment/patches/openimagedenoise.diff +++ b/build_files/build_environment/patches/openimagedenoise.diff @@ -18,17 +18,6 @@ diff --git a/mkl-dnn/cmake/TBB.cmake b/mkl-dnn/cmake/TBB.cmake index 0711e699..c14210b6 100644 --- a/mkl-dnn/cmake/TBB.cmake +++ b/mkl-dnn/cmake/TBB.cmake -@@ -90,8 +90,8 @@ if(WIN32) - NO_DEFAULT_PATH - ) - set(TBB_LIB_DIR ${TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER}) -- find_library(TBB_LIBRARY tbb PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) -- find_library(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) -+ find_library(TBB_LIBRARY tbb_static PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) -+ find_library(TBB_LIBRARY_MALLOC tbbmalloc_static PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) - endif() - - else() @@ -138,13 +138,13 @@ else() set(TBB_LIBRARY_MALLOC TBB_LIBRARY_MALLOC-NOTFOUND) if(APPLE) diff --git a/build_files/build_environment/patches/pthreads.diff b/build_files/build_environment/patches/pthreads.diff index bbabfdc8925..4b6c9766e11 100644 --- a/build_files/build_environment/patches/pthreads.diff +++ b/build_files/build_environment/patches/pthreads.diff @@ -1,13 +1,12 @@ ---- pthread.h.orig 2012-05-26 22:16:45 -0600 -+++ pthread.h 2016-04-01 09:20:36 -0600 -@@ -109,6 +109,10 @@ - /* Include everything */ - #endif +diff -Naur orig/Makefile external_pthreads/Makefile +--- orig/Makefile 2018-08-08 04:47:40 -0600 ++++ external_pthreads/Makefile 2020-05-09 11:20:28 -0600 +@@ -185,7 +185,7 @@ + @ $(MAKE) /E /nologo XCFLAGS="/MTd" EHFLAGS="$(VSEFLAGSD) /D__PTW32_STATIC_LIB /D__PTW32_BUILD_INLINED" CLEANUP=__PTW32_CLEANUP_SEH pthreadVSE$(PTW32_VER_DEBUG).inlined_static_stamp -+#if _MSC_VER >= 1900 -+# define HAVE_STRUCT_TIMESPEC 1 -+#endif -+ - #if defined(_UWIN) - # define HAVE_STRUCT_TIMESPEC 1 - # define HAVE_SIGNAL_H 1 + VC-static: +- @ $(MAKE) /E /nologo XCFLAGS="/MT" EHFLAGS="$(VCFLAGS) /D__PTW32_STATIC_LIB /D__PTW32_BUILD_INLINED" CLEANUP=__PTW32_CLEANUP_C pthreadVC$(PTW32_VER).inlined_static_stamp ++ @ $(MAKE) /E /nologo XCFLAGS="/MD" EHFLAGS="$(VCFLAGS) /D__PTW32_STATIC_LIB /D__PTW32_BUILD_INLINED" CLEANUP=__PTW32_CLEANUP_C pthreadVC$(PTW32_VER).inlined_static_stamp + + VC-static-debug: + @ $(MAKE) /E /nologo XCFLAGS="/MTd" EHFLAGS="$(VCFLAGSD) /D__PTW32_STATIC_LIB /D__PTW32_BUILD_INLINED" CLEANUP=__PTW32_CLEANUP_C pthreadVC$(PTW32_VER_DEBUG).inlined_static_stamp diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake index 04e1670aef6..c36b264a300 100644 --- a/build_files/cmake/Modules/GTestTesting.cmake +++ b/build_files/cmake/Modules/GTestTesting.cmake @@ -66,6 +66,9 @@ macro(BLENDER_SRC_GTEST_EX) if(UNIX AND NOT APPLE) target_link_libraries(${TARGET_NAME} bf_intern_libc_compat) endif() + if(WITH_TBB) + target_link_libraries(${TARGET_NAME} ${TBB_LIBRARIES}) + endif() get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(GENERATOR_IS_MULTI_CONFIG) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 6287da55580..d99e46ce76e 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -440,6 +440,14 @@ function(SETUP_LIBDIRS) link_directories(${HDF5_LIBPATH}) endif() + if(WITH_GHOST_WAYLAND) + link_directories( + ${wayland-client_LIBRARY_DIRS} + ${wayland-egl_LIBRARY_DIRS} + ${xkbcommon_LIBRARY_DIRS} + ${wayland-cursor_LIBRARY_DIRS}) + endif() + if(WIN32 AND NOT UNIX) link_directories(${PTHREADS_LIBPATH}) endif() diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index e4102e3437b..6e00a2dec7b 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -505,7 +505,27 @@ if(WITH_SYSTEM_AUDASPACE) endif() endif() -if(WITH_X11) +if(WITH_GHOST_WAYLAND) + find_package(PkgConfig) + pkg_check_modules(wayland-client REQUIRED wayland-client>=1.12) + pkg_check_modules(wayland-egl REQUIRED wayland-egl) + pkg_check_modules(wayland-scanner REQUIRED wayland-scanner) + pkg_check_modules(xkbcommon REQUIRED xkbcommon) + pkg_check_modules(wayland-cursor REQUIRED wayland-cursor) + + set(WITH_GL_EGL ON) + + if(WITH_GHOST_WAYLAND) + list(APPEND PLATFORM_LINKLIBS + ${wayland-client_LIBRARIES} + ${wayland-egl_LIBRARIES} + ${xkbcommon_LIBRARIES} + ${wayland-cursor_LIBRARIES} + ) + endif() +endif() + +if(WITH_GHOST_X11) find_package(X11 REQUIRED) find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH}) @@ -576,6 +596,19 @@ if(CMAKE_COMPILER_IS_GNUCC) unset(LD_VERSION) endif() + if(WITH_LINKER_LLD) + execute_process( + COMMAND ${CMAKE_C_COMPILER} -fuse-ld=lld -Wl,--version + ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) + if("${LD_VERSION}" MATCHES "LLD") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld") + else() + message(STATUS "LLD linker isn't available, using the default system linker.") + endif() + unset(LD_VERSION) + endif() + # CLang is the same as GCC for now. elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 1ecde8635c8..1889c9773fb 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -51,6 +51,10 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang") endif() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \"${CLANG_OPENMP_LIB}\"") endif() + if(WITH_WINDOWS_STRIPPED_PDB) + message(WARNING "stripped pdb not supported with clang, disabling..") + set(WITH_WINDOWS_STRIPPED_PDB Off) + endif() endif() set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS}) @@ -107,12 +111,13 @@ endif() unset(_min_ver) # needed for some MSVC installations -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") -set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") +# 4099 : PDB 'filename' was not found with 'object/library' +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /ignore:4099") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO /ignore:4099") +set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO /ignore:4099") list(APPEND PLATFORM_LINKLIBS - ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 Comctl32 + ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 Comctl32 version advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp Shlwapi ) @@ -134,7 +139,12 @@ add_definitions(-D_ALLOW_KEYWORD_MACROS) # We want to support Windows 7 level ABI add_definitions(-D_WIN32_WINNT=0x601) include(build_files/cmake/platform/platform_win32_bundle_crt.cmake) -remove_cc_flag("/MDd" "/MD") +remove_cc_flag("/MDd" "/MD" "/Zi") + +if(WITH_WINDOWS_PDB) + set(PDB_INFO_OVERRIDE_FLAGS "/Z7") + set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO") +endif() if(MSVC_CLANG) # Clangs version of cl doesn't support all flags set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ") @@ -151,27 +161,42 @@ if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:twoPhase-") endif() +if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND) + message(WARNING "Disabling sccache, sccache is not supported with msbuild") + set(WITH_WINDOWS_SCCACHE Off) +endif() -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /ZI") -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd /ZI") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD") -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD") -set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MD") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD") - +if(WITH_WINDOWS_SCCACHE) + set(CMAKE_C_COMPILER_LAUNCHER sccache) + set(CMAKE_CXX_COMPILER_LAUNCHER sccache) + set(SYMBOL_FORMAT /Z7) +else() + unset(CMAKE_C_COMPILER_LAUNCHER) + unset(CMAKE_CXX_COMPILER_LAUNCHER) + set(SYMBOL_FORMAT /ZI) +endif() + +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd ${SYMBOL_FORMAT}") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd ${SYMBOL_FORMAT}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD ${PDB_INFO_OVERRIDE_FLAGS}") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD ${PDB_INFO_OVERRIDE_FLAGS}") +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD ${PDB_INFO_OVERRIDE_FLAGS}") +set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MD ${PDB_INFO_OVERRIDE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD ${SYMBOL_FORMAT}") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD ${SYMBOL_FORMAT}") +unset(SYMBOL_FORMAT) # JMC is available on msvc 15.8 (1915) and up if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /JMC") endif() -set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ") +set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /SUBSYSTEM:CONSOLE /STACK:2097152 ") set(PLATFORM_LINKFLAGS_RELEASE "/NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib") set(PLATFORM_LINKFLAGS_DEBUG "${PLATFORM_LINKFLAGS_DEBUG} /IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libcmtd.lib") # Ignore meaningless for us linker warnings. set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /ignore:4049 /ignore:4217 /ignore:4221") +set(PLATFORM_LINKFLAGS_RELEASE "${PLATFORM_LINKFLAGS} ${PDB_INFO_OVERRIDE_LINKER_FLAGS}") set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") if(CMAKE_CL_64) @@ -209,7 +234,7 @@ endif() # Mark libdir as system headers with a lower warn level, to resolve some warnings # that we have very little control over -if(MSVC_VERSION GREATER_EQUAL 1914 AND NOT MSVC_CLANG) +if(MSVC_VERSION GREATER_EQUAL 1914 AND NOT MSVC_CLANG AND NOT WITH_WINDOWS_SCCACHE) add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0) endif() @@ -572,7 +597,7 @@ if(WITH_SYSTEM_AUDASPACE) endif() if(WITH_TBB) - set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib) + set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/debug/tbb_debug.lib) set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include) set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR}) if(WITH_TBB_MALLOC_PROXY) diff --git a/build_files/windows/configure_msbuild.cmd b/build_files/windows/configure_msbuild.cmd index 3c1194011cd..4956f1e3ea1 100644 --- a/build_files/windows/configure_msbuild.cmd +++ b/build_files/windows/configure_msbuild.cmd @@ -2,6 +2,11 @@ set BUILD_GENERATOR_POST= set BUILD_PLATFORM_SELECT= set MSBUILD_PLATFORM=x64 +if "%BUILD_WITH_SCCACHE%"=="1" ( + echo sccache is only supported with ninja as the build system. + exit /b 1 +) + if "%WITH_CLANG%"=="1" ( set CLANG_CMAKE_ARGS=-T"llvm" if "%WITH_ASAN%"=="1" ( diff --git a/build_files/windows/configure_ninja.cmd b/build_files/windows/configure_ninja.cmd index 1650e43cda9..20692847bef 100644 --- a/build_files/windows/configure_ninja.cmd +++ b/build_files/windows/configure_ninja.cmd @@ -6,6 +6,13 @@ if %ERRORLEVEL% NEQ 0 ( set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Ninja" %TESTS_CMAKE_ARGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% +if "%BUILD_WITH_SCCACHE%"=="1" ( + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_WINDOWS_SCCACHE=On + if NOT "%verbose%" == "" ( + echo Enabling sccache + ) +) + if "%WITH_CLANG%" == "1" ( set LLVM_DIR= for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd index 4ee05bfde7d..54dc41ece87 100644 --- a/build_files/windows/parse_arguments.cmd +++ b/build_files/windows/parse_arguments.cmd @@ -86,6 +86,8 @@ if NOT "%1" == "" ( set BUILD_UPDATE_ARGS="--no-libraries" ) else if "%1" == "ninja" ( SET BUILD_WITH_NINJA=1 + ) else if "%1" == "sccache" ( + SET BUILD_WITH_SCCACHE=1 ) else if "%1" == "clean" ( set MUST_CLEAN=1 ) else if "%1" == "verbose" ( diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd index 48a61aff44a..262874713eb 100644 --- a/build_files/windows/reset_variables.cmd +++ b/build_files/windows/reset_variables.cmd @@ -30,3 +30,4 @@ set WITH_PYDEBUG= set PYDEBUG_CMAKE_ARGS= set FORMAT= set TEST= +set BUILD_WITH_SCCACHE= diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index ecd60957f2b..1e430823b10 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.83" +PROJECT_NUMBER = "V2.90" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -51,7 +51,7 @@ PROJECT_BRIEF = # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = ../../release/freedesktop/icons/48x48/apps/blender.png +PROJECT_LOGO = ../../release/freedesktop/icons/scalable/apps/blender.svg # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is @@ -1720,7 +1720,7 @@ COMPACT_LATEX = NO # The default value is: a4. # This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # that should be included in the LaTeX output. The package can be specified just diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index e341453fe93..562076c6c43 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -253,7 +253,13 @@ Registering a class with Blender results in the class definition being loaded in where it becomes available alongside existing functionality. Once this class is loaded you can access it from :mod:`bpy.types`, -using the bl_idname rather than the classes original name. +using the ``bl_idname`` rather than the classes original name. + +.. note:: + + There are some exceptions to this for class names which aren't guarantee to be unique. + In this case use: :func:`bpy.types.Struct.bl_rna_get_subclass`. + When loading a class, Blender performs sanity checks making sure all required properties and functions are found, that properties have the correct type, and that functions have the right number of arguments. diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 84a5af8b11e..4780fe389cf 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -492,6 +492,11 @@ if _BPY_PROP_COLLECTION_FAKE: else: _BPY_PROP_COLLECTION_ID = "collection" +if _BPY_STRUCT_FAKE: + bpy_struct = bpy.types.bpy_struct +else: + bpy_struct = None + def escape_rst(text): """ Escape plain text which may contain characters used by RST. @@ -1443,7 +1448,7 @@ def pyrna2sphinx(basepath): if _BPY_STRUCT_FAKE: descr_items = [ - (key, descr) for key, descr in sorted(bpy.types.Struct.__bases__[0].__dict__.items()) + (key, descr) for key, descr in sorted(bpy_struct.__dict__.items()) if not key.startswith("__") ] @@ -1459,9 +1464,6 @@ def pyrna2sphinx(basepath): for identifier, py_prop in base.get_py_properties(): lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier)) - for identifier, py_prop in base.get_py_properties(): - lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier)) - if lines: fw(".. rubric:: Inherited Properties\n\n") @@ -1485,6 +1487,8 @@ def pyrna2sphinx(basepath): lines.append(" * :class:`%s.%s`\n" % (base.identifier, func.identifier)) for identifier, py_func in base.get_py_functions(): lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier)) + for identifier, py_func in base.get_py_c_functions(): + lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier)) if lines: fw(".. rubric:: Inherited Functions\n\n") @@ -1572,7 +1576,7 @@ def pyrna2sphinx(basepath): # write fake classes if _BPY_STRUCT_FAKE: - class_value = bpy.types.Struct.__bases__[0] + class_value = bpy_struct fake_bpy_type( "bpy.types", class_value, _BPY_STRUCT_FAKE, "built-in base class for all classes in bpy.types.", use_subclasses=True, @@ -1712,7 +1716,7 @@ class PatchedPythonDomain(PythonDomain): fw("def setup(app):\n") fw(" app.add_stylesheet('css/theme_overrides.css')\n") - fw(" app.override_domain(PatchedPythonDomain)\n\n") + fw(" app.add_domain(PatchedPythonDomain, override=True)\n\n") file.close() diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index e79aba0e988..235c2fa931a 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -72,7 +72,7 @@ if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV) endif() endif() -if(WITH_X11 AND WITH_GHOST_XDND) +if(WITH_GHOST_X11 AND WITH_GHOST_XDND) add_subdirectory(xdnd) endif() diff --git a/extern/audaspace/bindings/C/AUD_Device.cpp b/extern/audaspace/bindings/C/AUD_Device.cpp index 441f228deac..d4643094bc2 100644 --- a/extern/audaspace/bindings/C/AUD_Device.cpp +++ b/extern/audaspace/bindings/C/AUD_Device.cpp @@ -290,14 +290,14 @@ AUD_API AUD_Device* AUD_Device_getCurrent() return new AUD_Device(device); } -AUD_API void AUD_seekSynchronizer(AUD_Handle* handle, float time) +AUD_API void AUD_seekSynchronizer(AUD_Handle* handle, double time) { auto synchronizer = DeviceManager::getDevice()->getSynchronizer(); if(synchronizer) synchronizer->seek(*reinterpret_cast<std::shared_ptr<IHandle>*>(handle), time); } -AUD_API float AUD_getSynchronizerPosition(AUD_Handle* handle) +AUD_API double AUD_getSynchronizerPosition(AUD_Handle* handle) { auto synchronizer = DeviceManager::getDevice()->getSynchronizer(); if(synchronizer) diff --git a/extern/audaspace/bindings/C/AUD_Device.h b/extern/audaspace/bindings/C/AUD_Device.h index 0dfa21f0660..05e004a17db 100644 --- a/extern/audaspace/bindings/C/AUD_Device.h +++ b/extern/audaspace/bindings/C/AUD_Device.h @@ -221,14 +221,14 @@ extern AUD_API AUD_Device* AUD_Device_getCurrent(); * \param handle Playback handle. * \param time Time in seconds to seek to. */ -extern AUD_API void AUD_seekSynchronizer(AUD_Handle* handle, float time); +extern AUD_API void AUD_seekSynchronizer(AUD_Handle* handle, double time); /** * Returns the current sound scene playback time. * \param handle Playback handle. * \return The playback time in seconds. */ -extern AUD_API float AUD_getSynchronizerPosition(AUD_Handle* handle); +extern AUD_API double AUD_getSynchronizerPosition(AUD_Handle* handle); /** * Starts the playback of jack transport if possible. diff --git a/extern/audaspace/bindings/C/AUD_DynamicMusic.cpp b/extern/audaspace/bindings/C/AUD_DynamicMusic.cpp index bb7a129dde3..62e626cdc6c 100644 --- a/extern/audaspace/bindings/C/AUD_DynamicMusic.cpp +++ b/extern/audaspace/bindings/C/AUD_DynamicMusic.cpp @@ -101,14 +101,14 @@ AUD_API int AUD_DynamicMusic_pause(AUD_DynamicMusic* player) return (*player)->pause(); } -AUD_API int AUD_DynamicMusic_seek(AUD_DynamicMusic* player, float position) +AUD_API int AUD_DynamicMusic_seek(AUD_DynamicMusic* player, double position) { assert(player); return (*player)->seek(position); } -AUD_API float AUD_DynamicMusic_getPosition(AUD_DynamicMusic* player) +AUD_API double AUD_DynamicMusic_getPosition(AUD_DynamicMusic* player) { assert(player); @@ -141,4 +141,4 @@ AUD_API int AUD_DynamicMusic_stop(AUD_DynamicMusic* player) assert(player); return (*player)->stop(); -}
\ No newline at end of file +} diff --git a/extern/audaspace/bindings/C/AUD_DynamicMusic.h b/extern/audaspace/bindings/C/AUD_DynamicMusic.h index c362479591e..b8b78e57b55 100644 --- a/extern/audaspace/bindings/C/AUD_DynamicMusic.h +++ b/extern/audaspace/bindings/C/AUD_DynamicMusic.h @@ -103,14 +103,14 @@ extern AUD_API int AUD_DynamicMusic_pause(AUD_DynamicMusic* player); * \param position The new position from which to play back, in seconds. * \return 0 if the seeking wasn't possible. */ -extern AUD_API int AUD_DynamicMusic_seek(AUD_DynamicMusic* player, float position); +extern AUD_API int AUD_DynamicMusic_seek(AUD_DynamicMusic* player, double position); /** * Retrieves the position of the current scene of a dynamic music player. * \param player The DynamicMusic object. * \return The position of the current playing scene. */ -extern AUD_API float AUD_DynamicMusic_getPosition(AUD_DynamicMusic* player); +extern AUD_API double AUD_DynamicMusic_getPosition(AUD_DynamicMusic* player); /** * Retrieves the volume of the current scene of a dynamic music player. @@ -142,4 +142,4 @@ extern AUD_API int AUD_DynamicMusic_stop(AUD_DynamicMusic* player); #ifdef __cplusplus } -#endif
\ No newline at end of file +#endif diff --git a/extern/audaspace/bindings/C/AUD_Handle.cpp b/extern/audaspace/bindings/C/AUD_Handle.cpp index 265c7bf08d2..88d46d635e3 100644 --- a/extern/audaspace/bindings/C/AUD_Handle.cpp +++ b/extern/audaspace/bindings/C/AUD_Handle.cpp @@ -259,13 +259,13 @@ AUD_API int AUD_Handle_setPitch(AUD_Handle* handle, float value) return (*handle)->setPitch(value); } -AUD_API float AUD_Handle_getPosition(AUD_Handle* handle) +AUD_API double AUD_Handle_getPosition(AUD_Handle* handle) { assert(handle); return (*handle)->getPosition(); } -AUD_API int AUD_Handle_setPosition(AUD_Handle* handle, float value) +AUD_API int AUD_Handle_setPosition(AUD_Handle* handle, double value) { assert(handle); return (*handle)->seek(value); diff --git a/extern/audaspace/bindings/C/AUD_Handle.h b/extern/audaspace/bindings/C/AUD_Handle.h index 27cbd251de5..2182346c451 100644 --- a/extern/audaspace/bindings/C/AUD_Handle.h +++ b/extern/audaspace/bindings/C/AUD_Handle.h @@ -211,14 +211,14 @@ extern AUD_API int AUD_Handle_setPitch(AUD_Handle* handle, float value); * param handle The handle to get the position from. * return The position of the handle. */ -extern AUD_API float AUD_Handle_getPosition(AUD_Handle* handle); +extern AUD_API double AUD_Handle_getPosition(AUD_Handle* handle); /** * Sets the position of a handle. * param handle The handle to set the position from. * param value The new position to set. */ -extern AUD_API int AUD_Handle_setPosition(AUD_Handle* handle, float value); +extern AUD_API int AUD_Handle_setPosition(AUD_Handle* handle, double value); /** * Retrieves the relative of a handle. diff --git a/extern/audaspace/bindings/C/AUD_Sequence.cpp b/extern/audaspace/bindings/C/AUD_Sequence.cpp index d278cb148a1..e3f88629657 100644 --- a/extern/audaspace/bindings/C/AUD_Sequence.cpp +++ b/extern/audaspace/bindings/C/AUD_Sequence.cpp @@ -41,7 +41,7 @@ AUD_API void AUD_Sequence_free(AUD_Sound* sequence) delete sequence; } -AUD_API AUD_SequenceEntry* AUD_Sequence_add(AUD_Sound* sequence, AUD_Sound* sound, float begin, float end, float skip) +AUD_API AUD_SequenceEntry* AUD_Sequence_add(AUD_Sound* sequence, AUD_Sound* sound, double begin, double end, double skip) { if(!sound) return new AUD_SequenceEntry(((Sequence *)sequence->get())->add(AUD_Sound(), begin, end, skip)); @@ -160,7 +160,7 @@ AUD_API void AUD_Sequence_setSpeedOfSound(AUD_Sound* sequence, float value) -AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, float begin, float end, float skip) +AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, double begin, double end, double skip) { (*entry)->move(begin, end, skip); } diff --git a/extern/audaspace/bindings/C/AUD_Sequence.h b/extern/audaspace/bindings/C/AUD_Sequence.h index 668960c7d50..bdf1a61a2de 100644 --- a/extern/audaspace/bindings/C/AUD_Sequence.h +++ b/extern/audaspace/bindings/C/AUD_Sequence.h @@ -55,7 +55,7 @@ extern AUD_API void AUD_Sequence_free(AUD_Sound* sequence); * \param skip How much seconds should be skipped at the beginning. * \return The entry added. */ -extern AUD_API AUD_SequenceEntry* AUD_Sequence_add(AUD_Sound* sequence, AUD_Sound* sound, float begin, float end, float skip); +extern AUD_API AUD_SequenceEntry* AUD_Sequence_add(AUD_Sound* sequence, AUD_Sound* sound, double begin, double end, double skip); /** * Removes an entry from the scene. @@ -167,7 +167,7 @@ extern AUD_API void AUD_Sequence_setSpeedOfSound(AUD_Sound* sequence, float valu * \param end The new end time or a negative value if unknown. * \param skip How many seconds to skip at the beginning. */ -extern AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, float begin, float end, float skip); +extern AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, double begin, double end, double skip); /** * Writes animation data to a sequenced entry. diff --git a/extern/audaspace/bindings/C/AUD_Special.cpp b/extern/audaspace/bindings/C/AUD_Special.cpp index 30148fa1487..c7155276a30 100644 --- a/extern/audaspace/bindings/C/AUD_Special.cpp +++ b/extern/audaspace/bindings/C/AUD_Special.cpp @@ -175,7 +175,7 @@ static void pauseSound(AUD_Handle* handle) (*handle)->pause(); } -AUD_API AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds) +AUD_API AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, double seconds) { auto device = DeviceManager::getDevice(); @@ -336,7 +336,7 @@ AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start } } -AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start) +AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, double start) { try { diff --git a/extern/audaspace/bindings/C/AUD_Special.h b/extern/audaspace/bindings/C/AUD_Special.h index ab79ae915a2..9faf9e4ee74 100644 --- a/extern/audaspace/bindings/C/AUD_Special.h +++ b/extern/audaspace/bindings/C/AUD_Special.h @@ -45,7 +45,7 @@ extern AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float * \param seconds The time in seconds. * \return The silence handle. */ -extern AUD_API AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds); +extern AUD_API AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, double seconds); /** * Reads a sound into a buffer for drawing at a specific sampling rate. @@ -101,7 +101,7 @@ extern AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned in * \param start The start time of the mixdown in the sound scene. * \return The read device for the mixdown. */ -extern AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start); +extern AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, double start); /** * Initializes audio routines (FFMPEG/JACK if it is enabled). diff --git a/extern/audaspace/bindings/doc/device.rst b/extern/audaspace/bindings/doc/device.rst index fd6b334022c..d6f49bd7407 100644 --- a/extern/audaspace/bindings/doc/device.rst +++ b/extern/audaspace/bindings/doc/device.rst @@ -4,4 +4,5 @@ Device .. currentmodule:: aud .. autoclass:: Device :members: + :noindex: diff --git a/extern/audaspace/bindings/doc/handle.rst b/extern/audaspace/bindings/doc/handle.rst index aceedbca3a6..1d118e1ef62 100644 --- a/extern/audaspace/bindings/doc/handle.rst +++ b/extern/audaspace/bindings/doc/handle.rst @@ -4,4 +4,5 @@ Handle .. currentmodule:: aud .. autoclass:: Handle :members: + :noindex: diff --git a/extern/audaspace/bindings/doc/index.rst b/extern/audaspace/bindings/doc/index.rst index b8a26822949..cc6a543067d 100644 --- a/extern/audaspace/bindings/doc/index.rst +++ b/extern/audaspace/bindings/doc/index.rst @@ -7,6 +7,7 @@ Welcome to audaspace's documentation! ===================================== .. automodule:: aud + :no-members: This documentation is valid for both the Python and C bindings of audaspace. If you are looking for installation instructions check the `C++ API documentation <../index.html>`_. As C is not an object oriented language everything is accessible via functions where the first paramter is always the object. For methods these are named as ``AUD_ClassName_method()`` and properties are accessed via ``AUD_ClassName_property_get/set()``. Python users simply ``import aud`` to access the library. @@ -18,7 +19,7 @@ This documentation is valid for both the Python and C bindings of audaspace. If Classes: .. toctree:: - :maxdepth: 2 + :maxdepth: 1 device sound diff --git a/extern/audaspace/bindings/doc/sequence.rst b/extern/audaspace/bindings/doc/sequence.rst index 16fcb00f4dc..51aef1a1d37 100644 --- a/extern/audaspace/bindings/doc/sequence.rst +++ b/extern/audaspace/bindings/doc/sequence.rst @@ -4,4 +4,5 @@ Sequence .. currentmodule:: aud .. autoclass:: Sequence :members: + :noindex: diff --git a/extern/audaspace/bindings/doc/sequence_entry.rst b/extern/audaspace/bindings/doc/sequence_entry.rst index 0a3d83388e9..797b950dcdd 100644 --- a/extern/audaspace/bindings/doc/sequence_entry.rst +++ b/extern/audaspace/bindings/doc/sequence_entry.rst @@ -4,4 +4,5 @@ Sequence Entry .. currentmodule:: aud .. autoclass:: SequenceEntry :members: + :noindex: diff --git a/extern/audaspace/bindings/doc/sound.rst b/extern/audaspace/bindings/doc/sound.rst index 2f14721cf3a..d88c113eead 100644 --- a/extern/audaspace/bindings/doc/sound.rst +++ b/extern/audaspace/bindings/doc/sound.rst @@ -4,4 +4,5 @@ Sound .. currentmodule:: aud .. autoclass:: Sound :members: + :noindex: diff --git a/extern/audaspace/bindings/doc/tutorials.rst b/extern/audaspace/bindings/doc/tutorials.rst index 2a0e7541861..919c9083fc8 100644 --- a/extern/audaspace/bindings/doc/tutorials.rst +++ b/extern/audaspace/bindings/doc/tutorials.rst @@ -40,7 +40,7 @@ and create a :func:`aud.Sound.sine` signal with a frequency of 440 Hz. sine = aud.Sound.sine(440) .. note:: At this point nothing is playing back yet, -:class:`aud.Sound` objects are just descriptions of sounds. + :class:`aud.Sound` objects are just descriptions of sounds. However instead of a sine wave, we would like to have a square wave to produce a more retro gaming sound. We could of course use the diff --git a/extern/audaspace/bindings/python/PyDynamicMusic.cpp b/extern/audaspace/bindings/python/PyDynamicMusic.cpp index cab856359e0..8a7d8265bf4 100644 --- a/extern/audaspace/bindings/python/PyDynamicMusic.cpp +++ b/extern/audaspace/bindings/python/PyDynamicMusic.cpp @@ -228,9 +228,9 @@ PyDoc_STRVAR(M_aud_DynamicMusic_position_doc, static int DynamicMusic_set_position(DynamicMusicP* self, PyObject* args, void* nothing) { - float position; + double position; - if(!PyArg_Parse(args, "f:position", &position)) + if(!PyArg_Parse(args, "d:position", &position)) return -1; try @@ -252,7 +252,7 @@ DynamicMusic_get_position(DynamicMusicP* self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getPosition()); + return Py_BuildValue("d", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getPosition()); } catch(aud::Exception& e) { diff --git a/extern/audaspace/bindings/python/PyHandle.cpp b/extern/audaspace/bindings/python/PyHandle.cpp index 828c1b1afef..4ecf2ffd210 100644 --- a/extern/audaspace/bindings/python/PyHandle.cpp +++ b/extern/audaspace/bindings/python/PyHandle.cpp @@ -696,7 +696,7 @@ Handle_get_position(Handle* self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getPosition()); + return Py_BuildValue("d", (*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getPosition()); } catch(Exception& e) { @@ -708,9 +708,9 @@ Handle_get_position(Handle* self, void* nothing) static int Handle_set_position(Handle* self, PyObject* args, void* nothing) { - float position; + double position; - if(!PyArg_Parse(args, "f:position", &position)) + if(!PyArg_Parse(args, "d:position", &position)) return -1; try diff --git a/extern/audaspace/bindings/python/PySequence.cpp b/extern/audaspace/bindings/python/PySequence.cpp index 2e08059cefb..26f0c9e566f 100644 --- a/extern/audaspace/bindings/python/PySequence.cpp +++ b/extern/audaspace/bindings/python/PySequence.cpp @@ -104,11 +104,11 @@ PyDoc_STRVAR(M_aud_Sequence_add_doc, " :arg sound: The sound this entry should play.\n" " :type sound: :class:`Sound`\n" " :arg begin: The start time.\n" - " :type begin: float\n" + " :type begin: double\n" " :arg end: The end time or a negative value if determined by the sound.\n" - " :type end: float\n" + " :type end: double\n" " :arg skip: How much seconds should be skipped at the beginning.\n" - " :type skip: float\n" + " :type skip: double\n" " :return: The entry added.\n" " :rtype: :class:`SequenceEntry`"); @@ -116,13 +116,13 @@ static PyObject * Sequence_add(Sequence* self, PyObject* args, PyObject* kwds) { PyObject* object; - float begin; - float end = -1.0f; - float skip = 0.0f; + double begin; + double end = -1.0; + double skip = 0.0; static const char* kwlist[] = {"sound", "begin", "end", "skip", nullptr}; - if(!PyArg_ParseTupleAndKeywords(args, kwds, "Of|ff:add", const_cast<char**>(kwlist), &object, &begin, &end, &skip)) + if(!PyArg_ParseTupleAndKeywords(args, kwds, "Od|dd:add", const_cast<char**>(kwlist), &object, &begin, &end, &skip)) return nullptr; Sound* sound = checkSound(object); diff --git a/extern/audaspace/bindings/python/PySequenceEntry.cpp b/extern/audaspace/bindings/python/PySequenceEntry.cpp index a1bf3db21d2..74c038de0b0 100644 --- a/extern/audaspace/bindings/python/PySequenceEntry.cpp +++ b/extern/audaspace/bindings/python/PySequenceEntry.cpp @@ -46,18 +46,18 @@ PyDoc_STRVAR(M_aud_SequenceEntry_move_doc, ".. classmethod:: move()\n\n" " Moves the entry.\n\n" " :arg begin: The new start time.\n" - " :type begin: float\n" + " :type begin: double\n" " :arg end: The new end time or a negative value if unknown.\n" - " :type end: float\n" + " :type end: double\n" " :arg skip: How many seconds to skip at the beginning.\n" - " :type skip: float\n"); + " :type skip: double\n"); static PyObject * SequenceEntry_move(SequenceEntry* self, PyObject* args) { - float begin, end, skip; + double begin, end, skip; - if(!PyArg_ParseTuple(args, "fff:move", &begin, &end, &skip)) + if(!PyArg_ParseTuple(args, "ddd:move", &begin, &end, &skip)) return nullptr; try diff --git a/extern/audaspace/bindings/python/PySound.cpp b/extern/audaspace/bindings/python/PySound.cpp index c37e3f7fa52..62ee3435e82 100644 --- a/extern/audaspace/bindings/python/PySound.cpp +++ b/extern/audaspace/bindings/python/PySound.cpp @@ -1394,7 +1394,7 @@ PyDoc_STRVAR(M_aud_Sound_threshold_doc, " with a amplitude >= threshold to 1, all <= -threshold to -1 and\n" " all between to 0.\n\n" " :arg threshold: Threshold value over which an amplitude counts\n" - " non-zero.\n" + " non-zero.\n\n" ":type threshold: float\n" ":return: The created :class:`Sound` object.\n" ":rtype: :class:`Sound`"); @@ -1434,7 +1434,8 @@ PyDoc_STRVAR(M_aud_Sound_volume_doc, " :type volume: float\n" " :return: The created :class:`Sound` object.\n" " :rtype: :class:`Sound`\n\n" - " .. note:: Should be in the range [0, 1] to avoid clipping.\n\n" + " .. note::\n\n" + " Should be in the range [0, 1] to avoid clipping.\n\n" " .. note::\n\n" " This is a filter function, you might consider using\n" " :attr:`Handle.volume` instead."); @@ -1475,8 +1476,8 @@ PyDoc_STRVAR(M_aud_Sound_join_doc, " :return: The created :class:`Sound` object.\n" " :rtype: :class:`Sound`\n\n" " .. note::\n\n" - " The two factories have to have the same specifications\n" - " (channels and samplerate)."); + " The two factories have to have the same specifications\n" + " (channels and samplerate)."); static PyObject * Sound_join(Sound* self, PyObject* object) diff --git a/extern/audaspace/include/devices/DefaultSynchronizer.h b/extern/audaspace/include/devices/DefaultSynchronizer.h index 31f6c65219c..e818306603c 100644 --- a/extern/audaspace/include/devices/DefaultSynchronizer.h +++ b/extern/audaspace/include/devices/DefaultSynchronizer.h @@ -33,8 +33,8 @@ AUD_NAMESPACE_BEGIN class AUD_API DefaultSynchronizer : public ISynchronizer { public: - virtual void seek(std::shared_ptr<IHandle> handle, float time); - virtual float getPosition(std::shared_ptr<IHandle> handle); + virtual void seek(std::shared_ptr<IHandle> handle, double time); + virtual double getPosition(std::shared_ptr<IHandle> handle); virtual void play(); virtual void stop(); virtual void setSyncCallback(syncFunction function, void* data); diff --git a/extern/audaspace/include/devices/IDeviceFactory.h b/extern/audaspace/include/devices/IDeviceFactory.h index 7023cc058c5..c0769fa8015 100644 --- a/extern/audaspace/include/devices/IDeviceFactory.h +++ b/extern/audaspace/include/devices/IDeviceFactory.h @@ -35,6 +35,9 @@ AUD_NAMESPACE_BEGIN class AUD_API IDeviceFactory { public: + /** + * Destroys the device factory. + */ virtual ~IDeviceFactory() {} /** diff --git a/extern/audaspace/include/devices/IHandle.h b/extern/audaspace/include/devices/IHandle.h index 3f42fc33c3a..a10ef3d71e4 100644 --- a/extern/audaspace/include/devices/IHandle.h +++ b/extern/audaspace/include/devices/IHandle.h @@ -105,14 +105,14 @@ public: * - false if the handle is invalid. * \warning Whether the seek works or not depends on the sound source. */ - virtual bool seek(float position)=0; + virtual bool seek(double position)=0; /** * Retrieves the current playback position of a sound. * \return The playback position in seconds, or 0.0 if the handle is * invalid. */ - virtual float getPosition()=0; + virtual double getPosition()=0; /** * Returns the status of a played back sound. diff --git a/extern/audaspace/include/devices/ISynchronizer.h b/extern/audaspace/include/devices/ISynchronizer.h index 6f14de59565..430230fbcb3 100644 --- a/extern/audaspace/include/devices/ISynchronizer.h +++ b/extern/audaspace/include/devices/ISynchronizer.h @@ -56,14 +56,14 @@ public: * @param handle The handle that should be synchronized/seeked. * @param time The absolute time to synchronize to. */ - virtual void seek(std::shared_ptr<IHandle> handle, float time) = 0; + virtual void seek(std::shared_ptr<IHandle> handle, double time) = 0; /** * Retrieves the position of the synchronizer. * @param handle The handle which is synchronized. * @return The position in seconds. */ - virtual float getPosition(std::shared_ptr<IHandle> handle) = 0; + virtual double getPosition(std::shared_ptr<IHandle> handle) = 0; /** * Starts the synchronizer playback. diff --git a/extern/audaspace/include/devices/NULLDevice.h b/extern/audaspace/include/devices/NULLDevice.h index 76211a799b9..9af78919f88 100644 --- a/extern/audaspace/include/devices/NULLDevice.h +++ b/extern/audaspace/include/devices/NULLDevice.h @@ -53,8 +53,8 @@ private: virtual bool stop(); virtual bool getKeep(); virtual bool setKeep(bool keep); - virtual bool seek(float position); - virtual float getPosition(); + virtual bool seek(double position); + virtual double getPosition(); virtual Status getStatus(); virtual float getVolume(); virtual bool setVolume(float volume); diff --git a/extern/audaspace/include/devices/SoftwareDevice.h b/extern/audaspace/include/devices/SoftwareDevice.h index 8f3846394c6..e92a35e5402 100644 --- a/extern/audaspace/include/devices/SoftwareDevice.h +++ b/extern/audaspace/include/devices/SoftwareDevice.h @@ -180,8 +180,8 @@ protected: virtual bool stop(); virtual bool getKeep(); virtual bool setKeep(bool keep); - virtual bool seek(float position); - virtual float getPosition(); + virtual bool seek(double position); + virtual double getPosition(); virtual Status getStatus(); virtual float getVolume(); virtual bool setVolume(float volume); diff --git a/extern/audaspace/include/file/IFileInput.h b/extern/audaspace/include/file/IFileInput.h index aec929e7639..64074910d13 100644 --- a/extern/audaspace/include/file/IFileInput.h +++ b/extern/audaspace/include/file/IFileInput.h @@ -40,7 +40,10 @@ class Buffer; class AUD_API IFileInput { public: - virtual ~IFileInput() {}; + /** + * Destroys the file input. + */ + virtual ~IFileInput() {} /** * Creates a reader for a file to be read. diff --git a/extern/audaspace/include/fx/Delay.h b/extern/audaspace/include/fx/Delay.h index d6ab93ca351..d8730802c6f 100644 --- a/extern/audaspace/include/fx/Delay.h +++ b/extern/audaspace/include/fx/Delay.h @@ -35,7 +35,7 @@ private: /** * The delay in samples. */ - const float m_delay; + const double m_delay; // delete copy constructor and operator= Delay(const Delay&) = delete; @@ -47,12 +47,12 @@ public: * \param sound The input sound. * \param delay The desired delay in seconds. */ - Delay(std::shared_ptr<ISound> sound, float delay = 0); + Delay(std::shared_ptr<ISound> sound, double delay = 0); /** * Returns the delay in seconds. */ - float getDelay() const; + double getDelay() const; virtual std::shared_ptr<IReader> createReader(); }; diff --git a/extern/audaspace/include/fx/DelayReader.h b/extern/audaspace/include/fx/DelayReader.h index fe37e56d83e..38106082020 100644 --- a/extern/audaspace/include/fx/DelayReader.h +++ b/extern/audaspace/include/fx/DelayReader.h @@ -52,7 +52,7 @@ public: * \param reader The reader to read from. * \param delay The delay in seconds. */ - DelayReader(std::shared_ptr<IReader> reader, float delay); + DelayReader(std::shared_ptr<IReader> reader, double delay); virtual void seek(int position); virtual int getLength() const; diff --git a/extern/audaspace/include/fx/DynamicMusic.h b/extern/audaspace/include/fx/DynamicMusic.h index 5d59f77401a..c2a1c75b47e 100644 --- a/extern/audaspace/include/fx/DynamicMusic.h +++ b/extern/audaspace/include/fx/DynamicMusic.h @@ -55,7 +55,7 @@ private: /** * Length of the crossfade transition in seconds, used when no custom transition has been set. */ - float m_fadeTime; + double m_fadeTime; /** * Handle to the playback of the current scene. @@ -145,13 +145,13 @@ public: * Sets the length of the crossfade transition (default 1 second). * \param seconds The time in seconds. */ - void setFadeTime(float seconds); + void setFadeTime(double seconds); /** * Gets the length of the crossfade transition (default 1 second). * \return The length of the cressfade transition in seconds. */ - float getFadeTime(); + double getFadeTime(); /** * Resumes a paused sound. @@ -177,14 +177,14 @@ public: * - false if the handle is invalid. * \warning Whether the seek works or not depends on the sound source. */ - bool seek(float position); + bool seek(double position); /** * Retrieves the current playback position of a sound. * \return The playback position in seconds, or 0.0 if the handle is * invalid. */ - float getPosition(); + double getPosition(); /** * Retrieves the volume of the scenes. diff --git a/extern/audaspace/include/fx/Fader.h b/extern/audaspace/include/fx/Fader.h index 63280aec292..452d525e8ca 100644 --- a/extern/audaspace/include/fx/Fader.h +++ b/extern/audaspace/include/fx/Fader.h @@ -43,12 +43,12 @@ private: /** * The fading start. */ - const float m_start; + const double m_start; /** * The fading length. */ - const float m_length; + const double m_length; // delete copy constructor and operator= Fader(const Fader&) = delete; @@ -64,7 +64,7 @@ public: */ Fader(std::shared_ptr<ISound> sound, FadeType type = FADE_IN, - float start = 0.0f, float length = 1.0f); + double start = 0, double length = 1); /** * Returns the fading type. @@ -74,12 +74,12 @@ public: /** * Returns the fading start. */ - float getStart() const; + double getStart() const; /** * Returns the fading length. */ - float getLength() const; + double getLength() const; virtual std::shared_ptr<IReader> createReader(); }; diff --git a/extern/audaspace/include/fx/FaderReader.h b/extern/audaspace/include/fx/FaderReader.h index 99ea3d28938..9e5fc6d265f 100644 --- a/extern/audaspace/include/fx/FaderReader.h +++ b/extern/audaspace/include/fx/FaderReader.h @@ -49,12 +49,12 @@ private: /** * The fading start. */ - const float m_start; + const double m_start; /** * The fading length. */ - const float m_length; + const double m_length; // delete copy constructor and operator= FaderReader(const FaderReader&) = delete; @@ -69,7 +69,7 @@ public: * \param length How long fading should last in seconds. */ FaderReader(std::shared_ptr<IReader> reader, FadeType type, - float start,float length); + double start,double length); virtual void read(int& length, bool& eos, sample_t* buffer); }; diff --git a/extern/audaspace/include/fx/Limiter.h b/extern/audaspace/include/fx/Limiter.h index 0b5451b4eed..b3cf598db2e 100644 --- a/extern/audaspace/include/fx/Limiter.h +++ b/extern/audaspace/include/fx/Limiter.h @@ -35,12 +35,12 @@ private: /** * The start time. */ - const float m_start; + const double m_start; /** * The end time. */ - const float m_end; + const double m_end; // delete copy constructor and operator= Limiter(const Limiter&) = delete; @@ -55,17 +55,17 @@ public: * play to the end. */ Limiter(std::shared_ptr<ISound> sound, - float start = 0, float end = -1); + double start = 0, double end = -1); /** * Returns the start time. */ - float getStart() const; + double getStart() const; /** * Returns the end time. */ - float getEnd() const; + double getEnd() const; virtual std::shared_ptr<IReader> createReader(); }; diff --git a/extern/audaspace/include/fx/LimiterReader.h b/extern/audaspace/include/fx/LimiterReader.h index 49a07b5c29e..00ad02e343d 100644 --- a/extern/audaspace/include/fx/LimiterReader.h +++ b/extern/audaspace/include/fx/LimiterReader.h @@ -35,12 +35,12 @@ private: /** * The start sample: inclusive. */ - const float m_start; + const double m_start; /** * The end sample: exlusive. */ - const float m_end; + const double m_end; // delete copy constructor and operator= LimiterReader(const LimiterReader&) = delete; @@ -54,7 +54,7 @@ public: * \param end The desired end time (sample exklusive), a negative value * signals that it should play to the end. */ - LimiterReader(std::shared_ptr<IReader> reader, float start = 0, float end = -1); + LimiterReader(std::shared_ptr<IReader> reader, double start = 0, double end = -1); virtual void seek(int position); virtual int getLength() const; diff --git a/extern/audaspace/include/sequence/Sequence.h b/extern/audaspace/include/sequence/Sequence.h index 7005171e2c8..de14fd9fa38 100644 --- a/extern/audaspace/include/sequence/Sequence.h +++ b/extern/audaspace/include/sequence/Sequence.h @@ -151,7 +151,7 @@ public: * \param skip How much seconds should be skipped at the beginning. * \return The entry added. */ - std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, float begin, float end, float skip); + std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, double begin, double end, double skip); /** * Removes an entry from the scene. diff --git a/extern/audaspace/include/sequence/SequenceData.h b/extern/audaspace/include/sequence/SequenceData.h index b3df0548a4d..c3380e66924 100644 --- a/extern/audaspace/include/sequence/SequenceData.h +++ b/extern/audaspace/include/sequence/SequenceData.h @@ -203,7 +203,7 @@ public: * \param skip How much seconds should be skipped at the beginning. * \return The entry added. */ - std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, float begin, float end, float skip); + std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, double begin, double end, double skip); /** * Removes an entry from the scene. diff --git a/extern/audaspace/include/sequence/SequenceEntry.h b/extern/audaspace/include/sequence/SequenceEntry.h index 98f15faf7ff..b8e9f116ee4 100644 --- a/extern/audaspace/include/sequence/SequenceEntry.h +++ b/extern/audaspace/include/sequence/SequenceEntry.h @@ -55,13 +55,13 @@ private: std::shared_ptr<ISound> m_sound; /// The begin time. - float m_begin; + double m_begin; /// The end time. - float m_end; + double m_end; /// How many seconds are skipped at the beginning. - float m_skip; + double m_skip; /// Whether the entry is muted. bool m_muted; @@ -124,7 +124,7 @@ public: * \param skip How much seconds should be skipped at the beginning. * \param id The ID of the entry. */ - SequenceEntry(std::shared_ptr<ISound> sound, float begin, float end, float skip, int id); + SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id); virtual ~SequenceEntry(); /** @@ -155,7 +155,7 @@ public: * \param end The new end time or a negative value if unknown. * \param skip How many seconds to skip at the beginning. */ - void move(float begin, float end, float skip); + void move(double begin, double end, double skip); /** * Retrieves the muting state of the entry. diff --git a/extern/audaspace/plugins/jack/JackDevice.cpp b/extern/audaspace/plugins/jack/JackDevice.cpp index 1d238f74c3a..32874fd1315 100644 --- a/extern/audaspace/plugins/jack/JackDevice.cpp +++ b/extern/audaspace/plugins/jack/JackDevice.cpp @@ -292,7 +292,7 @@ void JackDevice::stopPlayback() m_nextState = JackTransportStopped; } -void JackDevice::seekPlayback(float time) +void JackDevice::seekPlayback(double time) { if(time >= 0.0f) AUD_jack_transport_locate(m_client, time * m_specs.rate); @@ -304,11 +304,11 @@ void JackDevice::setSyncCallback(ISynchronizer::syncFunction sync, void* data) m_syncFuncData = data; } -float JackDevice::getPlaybackPosition() +double JackDevice::getPlaybackPosition() { jack_position_t position; AUD_jack_transport_query(m_client, &position); - return position.frame / (float) m_specs.rate; + return position.frame / (double) m_specs.rate; } bool JackDevice::doesPlayback() diff --git a/extern/audaspace/plugins/jack/JackDevice.h b/extern/audaspace/plugins/jack/JackDevice.h index 72143eda149..4e6b1f5d12c 100644 --- a/extern/audaspace/plugins/jack/JackDevice.h +++ b/extern/audaspace/plugins/jack/JackDevice.h @@ -174,7 +174,7 @@ public: * Seeks jack transport playback. * \param time The time to seek to. */ - void seekPlayback(float time); + void seekPlayback(double time); /** * Sets the sync callback for jack transport playback. @@ -187,7 +187,7 @@ public: * Retrieves the jack transport playback time. * \return The current time position. */ - float getPlaybackPosition(); + double getPlaybackPosition(); /** * Returns whether jack transport plays back. diff --git a/extern/audaspace/plugins/jack/JackSynchronizer.cpp b/extern/audaspace/plugins/jack/JackSynchronizer.cpp index cd4c448786d..0bcafa19ca5 100644 --- a/extern/audaspace/plugins/jack/JackSynchronizer.cpp +++ b/extern/audaspace/plugins/jack/JackSynchronizer.cpp @@ -25,12 +25,12 @@ JackSynchronizer::JackSynchronizer(JackDevice* device) : { } -void JackSynchronizer::seek(std::shared_ptr<IHandle> handle, float time) +void JackSynchronizer::seek(std::shared_ptr<IHandle> handle, double time) { m_device->seekPlayback(time); } -float JackSynchronizer::getPosition(std::shared_ptr<IHandle> handle) +double JackSynchronizer::getPosition(std::shared_ptr<IHandle> handle) { return m_device->getPlaybackPosition(); } diff --git a/extern/audaspace/plugins/jack/JackSynchronizer.h b/extern/audaspace/plugins/jack/JackSynchronizer.h index 5c7341a7872..8a1f930ebed 100644 --- a/extern/audaspace/plugins/jack/JackSynchronizer.h +++ b/extern/audaspace/plugins/jack/JackSynchronizer.h @@ -48,8 +48,8 @@ public: */ JackSynchronizer(JackDevice* device); - virtual void seek(std::shared_ptr<IHandle> handle, float time); - virtual float getPosition(std::shared_ptr<IHandle> handle); + virtual void seek(std::shared_ptr<IHandle> handle, double time); + virtual double getPosition(std::shared_ptr<IHandle> handle); virtual void play(); virtual void stop(); virtual void setSyncCallback(syncFunction function, void* data); diff --git a/extern/audaspace/plugins/openal/OpenALDevice.cpp b/extern/audaspace/plugins/openal/OpenALDevice.cpp index f41e9c6bef8..536ec4ccb1b 100644 --- a/extern/audaspace/plugins/openal/OpenALDevice.cpp +++ b/extern/audaspace/plugins/openal/OpenALDevice.cpp @@ -269,7 +269,7 @@ bool OpenALDevice::OpenALHandle::setKeep(bool keep) return true; } -bool OpenALDevice::OpenALHandle::seek(float position) +bool OpenALDevice::OpenALHandle::seek(double position) { if(!m_status) return false; @@ -335,7 +335,7 @@ bool OpenALDevice::OpenALHandle::seek(float position) return true; } -float OpenALDevice::OpenALHandle::getPosition() +double OpenALDevice::OpenALHandle::getPosition() { if(!m_status) return false; diff --git a/extern/audaspace/plugins/openal/OpenALDevice.h b/extern/audaspace/plugins/openal/OpenALDevice.h index c2bec443933..b6ba5456d85 100644 --- a/extern/audaspace/plugins/openal/OpenALDevice.h +++ b/extern/audaspace/plugins/openal/OpenALDevice.h @@ -126,8 +126,8 @@ private: virtual bool stop(); virtual bool getKeep(); virtual bool setKeep(bool keep); - virtual bool seek(float position); - virtual float getPosition(); + virtual bool seek(double position); + virtual double getPosition(); virtual Status getStatus(); virtual float getVolume(); virtual bool setVolume(float volume); diff --git a/extern/audaspace/src/devices/DefaultSynchronizer.cpp b/extern/audaspace/src/devices/DefaultSynchronizer.cpp index aa8945dadaa..3ef1f0bfc41 100644 --- a/extern/audaspace/src/devices/DefaultSynchronizer.cpp +++ b/extern/audaspace/src/devices/DefaultSynchronizer.cpp @@ -19,12 +19,12 @@ AUD_NAMESPACE_BEGIN -void DefaultSynchronizer::seek(std::shared_ptr<IHandle> handle, float time) +void DefaultSynchronizer::seek(std::shared_ptr<IHandle> handle, double time) { handle->seek(time); } -float DefaultSynchronizer::getPosition(std::shared_ptr<IHandle> handle) +double DefaultSynchronizer::getPosition(std::shared_ptr<IHandle> handle) { return handle->getPosition(); } diff --git a/extern/audaspace/src/devices/NULLDevice.cpp b/extern/audaspace/src/devices/NULLDevice.cpp index a82537f43b2..c3290465563 100644 --- a/extern/audaspace/src/devices/NULLDevice.cpp +++ b/extern/audaspace/src/devices/NULLDevice.cpp @@ -52,12 +52,12 @@ bool NULLDevice::NULLHandle::setKeep(bool keep) return false; } -bool NULLDevice::NULLHandle::seek(float position) +bool NULLDevice::NULLHandle::seek(double position) { return false; } -float NULLDevice::NULLHandle::getPosition() +double NULLDevice::NULLHandle::getPosition() { return std::numeric_limits<float>::quiet_NaN(); } diff --git a/extern/audaspace/src/devices/SoftwareDevice.cpp b/extern/audaspace/src/devices/SoftwareDevice.cpp index 8c16c75e8e3..7186f8b9442 100644 --- a/extern/audaspace/src/devices/SoftwareDevice.cpp +++ b/extern/audaspace/src/devices/SoftwareDevice.cpp @@ -347,7 +347,7 @@ bool SoftwareDevice::SoftwareHandle::setKeep(bool keep) return true; } -bool SoftwareDevice::SoftwareHandle::seek(float position) +bool SoftwareDevice::SoftwareHandle::seek(double position) { if(!m_status) return false; @@ -366,7 +366,7 @@ bool SoftwareDevice::SoftwareHandle::seek(float position) return true; } -float SoftwareDevice::SoftwareHandle::getPosition() +double SoftwareDevice::SoftwareHandle::getPosition() { if(!m_status) return false; @@ -376,7 +376,7 @@ float SoftwareDevice::SoftwareHandle::getPosition() if(!m_status) return 0.0f; - float position = m_reader->getPosition() / (float)m_device->m_specs.rate; + double position = m_reader->getPosition() / (double)m_device->m_specs.rate; return position; } diff --git a/extern/audaspace/src/fx/Delay.cpp b/extern/audaspace/src/fx/Delay.cpp index e2a82299bc0..3ce16f54636 100644 --- a/extern/audaspace/src/fx/Delay.cpp +++ b/extern/audaspace/src/fx/Delay.cpp @@ -19,13 +19,13 @@ AUD_NAMESPACE_BEGIN -Delay::Delay(std::shared_ptr<ISound> sound, float delay) : +Delay::Delay(std::shared_ptr<ISound> sound, double delay) : Effect(sound), m_delay(delay) { } -float Delay::getDelay() const +double Delay::getDelay() const { return m_delay; } diff --git a/extern/audaspace/src/fx/DelayReader.cpp b/extern/audaspace/src/fx/DelayReader.cpp index 530aed69cba..ec171a76f93 100644 --- a/extern/audaspace/src/fx/DelayReader.cpp +++ b/extern/audaspace/src/fx/DelayReader.cpp @@ -20,7 +20,7 @@ AUD_NAMESPACE_BEGIN -DelayReader::DelayReader(std::shared_ptr<IReader> reader, float delay) : +DelayReader::DelayReader(std::shared_ptr<IReader> reader, double delay) : EffectReader(reader), m_delay(int((SampleRate)delay * reader->getSpecs().rate)), m_remdelay(int((SampleRate)delay * reader->getSpecs().rate)) diff --git a/extern/audaspace/src/fx/DynamicMusic.cpp b/extern/audaspace/src/fx/DynamicMusic.cpp index b8f5c975b3f..ad4a76fee95 100644 --- a/extern/audaspace/src/fx/DynamicMusic.cpp +++ b/extern/audaspace/src/fx/DynamicMusic.cpp @@ -133,14 +133,14 @@ bool DynamicMusic::addTransition(int init, int end, std::shared_ptr<ISound> soun return false; } -void DynamicMusic::setFadeTime(float seconds) +void DynamicMusic::setFadeTime(double seconds) { m_device->lock(); m_fadeTime = seconds; m_device->unlock(); } -float DynamicMusic::getFadeTime() +double DynamicMusic::getFadeTime() { return m_fadeTime; } @@ -169,7 +169,7 @@ bool DynamicMusic::pause() return result || resultTrans; } -bool DynamicMusic::seek(float position) +bool DynamicMusic::seek(double position) { bool result = false; @@ -183,9 +183,9 @@ bool DynamicMusic::seek(float position) return result; } -float DynamicMusic::getPosition() +double DynamicMusic::getPosition() { - float result = 0.0f; + double result = 0.0f; if(m_currentHandle != nullptr) result = m_currentHandle->getPosition(); diff --git a/extern/audaspace/src/fx/Fader.cpp b/extern/audaspace/src/fx/Fader.cpp index 041d8369a01..778720b6059 100644 --- a/extern/audaspace/src/fx/Fader.cpp +++ b/extern/audaspace/src/fx/Fader.cpp @@ -18,7 +18,7 @@ AUD_NAMESPACE_BEGIN -Fader::Fader(std::shared_ptr<ISound> sound, FadeType type, float start, float length) : +Fader::Fader(std::shared_ptr<ISound> sound, FadeType type, double start, double length) : Effect(sound), m_type(type), m_start(start), @@ -31,12 +31,12 @@ FadeType Fader::getType() const return m_type; } -float Fader::getStart() const +double Fader::getStart() const { return m_start; } -float Fader::getLength() const +double Fader::getLength() const { return m_length; } diff --git a/extern/audaspace/src/fx/FaderReader.cpp b/extern/audaspace/src/fx/FaderReader.cpp index b1e23b993f3..10783f9f00c 100644 --- a/extern/audaspace/src/fx/FaderReader.cpp +++ b/extern/audaspace/src/fx/FaderReader.cpp @@ -20,7 +20,7 @@ AUD_NAMESPACE_BEGIN -FaderReader::FaderReader(std::shared_ptr<IReader> reader, FadeType type, float start,float length) : +FaderReader::FaderReader(std::shared_ptr<IReader> reader, FadeType type, double start, double length) : EffectReader(reader), m_type(type), m_start(start), @@ -36,14 +36,14 @@ void FaderReader::read(int& length, bool& eos, sample_t* buffer) m_reader->read(length, eos, buffer); - if((position + length) / (float)specs.rate <= m_start) + if((position + length) / specs.rate <= m_start) { if(m_type != FADE_OUT) { std::memset(buffer, 0, length * samplesize); } } - else if(position / (float)specs.rate >= m_start+m_length) + else if(position / specs.rate >= m_start+m_length) { if(m_type == FADE_OUT) { @@ -58,7 +58,7 @@ void FaderReader::read(int& length, bool& eos, sample_t* buffer) { if(i % specs.channels == 0) { - volume = (((position+i)/(float)specs.rate)-m_start) / m_length; + volume = float((((position + i) / specs.rate) - m_start) / m_length); if(volume > 1.0f) volume = 1.0f; else if(volume < 0.0f) diff --git a/extern/audaspace/src/fx/Limiter.cpp b/extern/audaspace/src/fx/Limiter.cpp index 38a7288e8d7..031283bb322 100644 --- a/extern/audaspace/src/fx/Limiter.cpp +++ b/extern/audaspace/src/fx/Limiter.cpp @@ -20,19 +20,19 @@ AUD_NAMESPACE_BEGIN Limiter::Limiter(std::shared_ptr<ISound> sound, - float start, float end) : + double start, double end) : Effect(sound), m_start(start), m_end(end) { } -float Limiter::getStart() const +double Limiter::getStart() const { return m_start; } -float Limiter::getEnd() const +double Limiter::getEnd() const { return m_end; } diff --git a/extern/audaspace/src/fx/LimiterReader.cpp b/extern/audaspace/src/fx/LimiterReader.cpp index 1d003c29679..28eb47aed2f 100644 --- a/extern/audaspace/src/fx/LimiterReader.cpp +++ b/extern/audaspace/src/fx/LimiterReader.cpp @@ -21,7 +21,7 @@ AUD_NAMESPACE_BEGIN -LimiterReader::LimiterReader(std::shared_ptr<IReader> reader, float start, float end) : +LimiterReader::LimiterReader(std::shared_ptr<IReader> reader, double start, double end) : EffectReader(reader), m_start(start), m_end(end) diff --git a/extern/audaspace/src/respec/ChannelMapperReader.cpp b/extern/audaspace/src/respec/ChannelMapperReader.cpp index 6558d2444f5..f7ddf3dbc73 100644 --- a/extern/audaspace/src/respec/ChannelMapperReader.cpp +++ b/extern/audaspace/src/respec/ChannelMapperReader.cpp @@ -16,9 +16,9 @@ #include "respec/ChannelMapperReader.h" +#include <algorithm> #include <cmath> #include <limits> -#include <algorithm> AUD_NAMESPACE_BEGIN diff --git a/extern/audaspace/src/respec/Mixer.cpp b/extern/audaspace/src/respec/Mixer.cpp index d63f0bab2bb..ad8d885df4e 100644 --- a/extern/audaspace/src/respec/Mixer.cpp +++ b/extern/audaspace/src/respec/Mixer.cpp @@ -66,11 +66,11 @@ void Mixer::setSpecs(Specs specs) void Mixer::clear(int length) { - m_buffer.assureSize(length * m_specs.channels * AUD_SAMPLE_SIZE(m_specs)); + m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs)); m_length = length; - std::memset(m_buffer.getBuffer(), 0, length * m_specs.channels * AUD_SAMPLE_SIZE(m_specs)); + std::memset(m_buffer.getBuffer(), 0, length * AUD_SAMPLE_SIZE(m_specs)); } void Mixer::mix(sample_t* buffer, int start, int length, float volume) diff --git a/extern/audaspace/src/sequence/Sequence.cpp b/extern/audaspace/src/sequence/Sequence.cpp index eaec4d84ae1..ab7e6e77857 100644 --- a/extern/audaspace/src/sequence/Sequence.cpp +++ b/extern/audaspace/src/sequence/Sequence.cpp @@ -90,7 +90,7 @@ AnimateableProperty* Sequence::getAnimProperty(AnimateablePropertyType type) return m_sequence->getAnimProperty(type); } -std::shared_ptr<SequenceEntry> Sequence::add(std::shared_ptr<ISound> sound, float begin, float end, float skip) +std::shared_ptr<SequenceEntry> Sequence::add(std::shared_ptr<ISound> sound, double begin, double end, double skip) { return m_sequence->add(sound, begin, end, skip); } diff --git a/extern/audaspace/src/sequence/SequenceData.cpp b/extern/audaspace/src/sequence/SequenceData.cpp index fb920acc1a8..288f0bd225d 100644 --- a/extern/audaspace/src/sequence/SequenceData.cpp +++ b/extern/audaspace/src/sequence/SequenceData.cpp @@ -149,7 +149,7 @@ AnimateableProperty* SequenceData::getAnimProperty(AnimateablePropertyType type) } } -std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, float begin, float end, float skip) +std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, double begin, double end, double skip) { std::lock_guard<std::recursive_mutex> lock(m_mutex); diff --git a/extern/audaspace/src/sequence/SequenceEntry.cpp b/extern/audaspace/src/sequence/SequenceEntry.cpp index de538199d7d..b63bdd2ffca 100644 --- a/extern/audaspace/src/sequence/SequenceEntry.cpp +++ b/extern/audaspace/src/sequence/SequenceEntry.cpp @@ -22,7 +22,7 @@ AUD_NAMESPACE_BEGIN -SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, float begin, float end, float skip, int id) : +SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id) : m_status(0), m_pos_status(1), m_sound_status(0), @@ -84,7 +84,7 @@ void SequenceEntry::setSound(std::shared_ptr<ISound> sound) } } -void SequenceEntry::move(float begin, float end, float skip) +void SequenceEntry::move(double begin, double end, double skip) { std::lock_guard<std::recursive_mutex> lock(m_mutex); diff --git a/extern/audaspace/src/sequence/SequenceHandle.cpp b/extern/audaspace/src/sequence/SequenceHandle.cpp index 140b1fbd94a..0437b05c85d 100644 --- a/extern/audaspace/src/sequence/SequenceHandle.cpp +++ b/extern/audaspace/src/sequence/SequenceHandle.cpp @@ -57,7 +57,7 @@ void SequenceHandle::start() m_valid = m_handle.get(); } -bool SequenceHandle::updatePosition(float position) +bool SequenceHandle::updatePosition(double position) { std::lock_guard<ILockable> lock(*m_entry); @@ -140,7 +140,7 @@ void SequenceHandle::stop() m_3dhandle = nullptr; } -void SequenceHandle::update(float position, float frame, float fps) +void SequenceHandle::update(double position, float frame, float fps) { if(m_sound_status != m_entry->m_sound_status) { @@ -229,7 +229,7 @@ void SequenceHandle::update(float position, float frame, float fps) m_handle->setVolume(0); } -bool SequenceHandle::seek(float position) +bool SequenceHandle::seek(double position) { if(!m_valid) // sound not valid, aborting @@ -240,7 +240,7 @@ bool SequenceHandle::seek(float position) return false; std::lock_guard<ILockable> lock(*m_entry); - float seekpos = position - m_entry->m_begin; + double seekpos = position - m_entry->m_begin; if(seekpos < 0) seekpos = 0; seekpos += m_entry->m_skip; diff --git a/extern/audaspace/src/sequence/SequenceHandle.h b/extern/audaspace/src/sequence/SequenceHandle.h index 9a77489a8f8..14a94365878 100644 --- a/extern/audaspace/src/sequence/SequenceHandle.h +++ b/extern/audaspace/src/sequence/SequenceHandle.h @@ -71,7 +71,7 @@ private: * \param position Current playback position in seconds. * \return Whether the handle is valid. */ - bool updatePosition(float position); + bool updatePosition(double position); public: /** @@ -104,14 +104,14 @@ public: * \param frame The current frame during playback. * \param fps The animation frames per second. */ - void update(float position, float frame, float fps); + void update(double position, float frame, float fps); /** * Seeks the handle to a specific time position. * \param position The time to seek to. * \return Whether the handle is valid. */ - bool seek(float position); + bool seek(double position); }; AUD_NAMESPACE_END diff --git a/extern/audaspace/src/sequence/SequenceReader.cpp b/extern/audaspace/src/sequence/SequenceReader.cpp index 38647aaeadf..c903e8ef42e 100644 --- a/extern/audaspace/src/sequence/SequenceReader.cpp +++ b/extern/audaspace/src/sequence/SequenceReader.cpp @@ -49,7 +49,7 @@ void SequenceReader::seek(int position) for(auto& handle : m_handles) { - handle->seek(position / m_sequence->m_specs.rate); + handle->seek(position / (double)m_sequence->m_specs.rate); } } @@ -150,13 +150,12 @@ void SequenceReader::read(int& length, bool& eos, sample_t* buffer) Specs specs = m_sequence->m_specs; int pos = 0; - float time = float(m_position) / float(specs.rate); + double time = double(m_position) / double(specs.rate); float volume, frame; int len, cfra; Vector3 v, v2; Quaternion q; - while(pos < length) { frame = time * m_sequence->m_fps; @@ -187,7 +186,7 @@ void SequenceReader::read(int& length, bool& eos, sample_t* buffer) m_device.read(reinterpret_cast<data_t*>(buffer + specs.channels * pos), len); pos += len; - time += float(len) / float(specs.rate); + time += double(len) / double(specs.rate); } m_position += length; diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h index 791dd001bbe..e5cd4a3d6ce 100644 --- a/extern/mantaflow/preprocessed/gitinfo.h +++ b/extern/mantaflow/preprocessed/gitinfo.h @@ -1,3 +1,3 @@ -#define MANTA_GIT_VERSION "commit 21303fab2eda588ec22988bf9e5762d2001c131f" +#define MANTA_GIT_VERSION "commit b4a2742bd743e2913fba94dd35846042e2650212" diff --git a/extern/mantaflow/preprocessed/plugin/extforces.cpp b/extern/mantaflow/preprocessed/plugin/extforces.cpp index 36221fbbc10..798bb3daeee 100644 --- a/extern/mantaflow/preprocessed/plugin/extforces.cpp +++ b/extern/mantaflow/preprocessed/plugin/extforces.cpp @@ -244,13 +244,15 @@ struct KnApplyForce : public KernelBase { bool additive; }; -//! add gravity forces to all fluid cells, automatically adapts to different grid sizes +//! add gravity forces to all fluid cells, optionally adapts to different grid sizes automatically void addGravity(const FlagGrid &flags, MACGrid &vel, Vec3 gravity, - const Grid<Real> *exclude = NULL) + const Grid<Real> *exclude = NULL, + bool scale = true) { - Vec3 f = gravity * flags.getParent()->getDt() / flags.getDx(); + float gridScale = (scale) ? flags.getDx() : 1; + Vec3 f = gravity * flags.getParent()->getDt() / gridScale; KnApplyForce(flags, vel, f, exclude, true); } static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds) @@ -267,8 +269,9 @@ static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds) MACGrid &vel = *_args.getPtr<MACGrid>("vel", 1, &_lock); Vec3 gravity = _args.get<Vec3>("gravity", 2, &_lock); const Grid<Real> *exclude = _args.getPtrOpt<Grid<Real>>("exclude", 3, NULL, &_lock); + bool scale = _args.getOpt<bool>("scale", 4, true, &_lock); _retval = getPyNone(); - addGravity(flags, vel, gravity, exclude); + addGravity(flags, vel, gravity, exclude, scale); _args.check(); } pbFinalizePlugin(parent, "addGravity", !noTiming); @@ -287,14 +290,13 @@ void PbRegister_addGravity() } } -//! add gravity forces to all fluid cells , but dont account for changing cell size +//! Deprecated: use addGravity(scale=false) instead void addGravityNoScale(const FlagGrid &flags, MACGrid &vel, const Vec3 &gravity, const Grid<Real> *exclude = NULL) { - const Vec3 f = gravity * flags.getParent()->getDt(); - KnApplyForce(flags, vel, f, exclude, true); + addGravity(flags, vel, gravity, exclude, false); } static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds) { @@ -412,14 +414,17 @@ struct KnAddBuoyancy : public KernelBase { Vec3 strength; }; -//! add Buoyancy force based on fctor (e.g. smoke density) +//! add Buoyancy force based on factor (e.g. smoke density), optionally adapts to different grid +//! sizes automatically void addBuoyancy(const FlagGrid &flags, const Grid<Real> &density, MACGrid &vel, Vec3 gravity, - Real coefficient = 1.) + Real coefficient = 1., + bool scale = true) { - Vec3 f = -gravity * flags.getParent()->getDt() / flags.getParent()->getDx() * coefficient; + float gridScale = (scale) ? flags.getDx() : 1; + Vec3 f = -gravity * flags.getParent()->getDt() / gridScale * coefficient; KnAddBuoyancy(flags, density, vel, f); } static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds) @@ -437,8 +442,9 @@ static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds) MACGrid &vel = *_args.getPtr<MACGrid>("vel", 2, &_lock); Vec3 gravity = _args.get<Vec3>("gravity", 3, &_lock); Real coefficient = _args.getOpt<Real>("coefficient", 4, 1., &_lock); + bool scale = _args.getOpt<bool>("scale", 5, true, &_lock); _retval = getPyNone(); - addBuoyancy(flags, density, vel, gravity, coefficient); + addBuoyancy(flags, density, vel, gravity, coefficient, scale); _args.check(); } pbFinalizePlugin(parent, "addBuoyancy", !noTiming); diff --git a/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp b/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp index a8913a218c1..5e24b6f28db 100644 --- a/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp +++ b/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp @@ -982,9 +982,14 @@ void flipSampleSecondaryParticles(const std::string mode, const Real c_b, const Real k_ta, const Real k_wc, - const Real dt, + const Real dt = 0, const int itype = FlagGrid::TypeFluid) { + + float timestep = dt; + if (dt <= 0) + timestep = flags.getParent()->getDt(); + if (mode == "single") { knFlipSampleSecondaryParticles(flags, v, @@ -1001,7 +1006,7 @@ void flipSampleSecondaryParticles(const std::string mode, c_b, k_ta, k_wc, - dt, + timestep, itype); } else if (mode == "multiple") { @@ -1020,7 +1025,7 @@ void flipSampleSecondaryParticles(const std::string mode, c_b, k_ta, k_wc, - dt, + timestep, itype); } else { @@ -1053,7 +1058,7 @@ static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds) const Real c_b = _args.get<Real>("c_b", 13, &_lock); const Real k_ta = _args.get<Real>("k_ta", 14, &_lock); const Real k_wc = _args.get<Real>("k_wc", 15, &_lock); - const Real dt = _args.get<Real>("dt", 16, &_lock); + const Real dt = _args.getOpt<Real>("dt", 16, 0, &_lock); const int itype = _args.getOpt<int>("itype", 17, FlagGrid::TypeFluid, &_lock); _retval = getPyNone(); flipSampleSecondaryParticles(mode, @@ -1691,13 +1696,20 @@ void flipUpdateSecondaryParticles(const std::string mode, const Real k_d, const Real c_s, const Real c_b, - const Real dt, + const Real dt = 0, + bool scale = true, const int exclude = ParticleBase::PTRACER, const int antitunneling = 0, const int itype = FlagGrid::TypeFluid) { - Vec3 g = gravity / flags.getDx(); + float gridScale = (scale) ? flags.getParent()->getDx() : 1; + Vec3 g = gravity / gridScale; + + float timestep = dt; + if (dt <= 0) + timestep = flags.getParent()->getDt(); + if (mode == "linear") { knFlipUpdateSecondaryParticlesLinear(pts_sec, v_sec, @@ -1711,7 +1723,7 @@ void flipUpdateSecondaryParticles(const std::string mode, k_d, c_s, c_b, - dt, + timestep, exclude, antitunneling); } @@ -1729,7 +1741,7 @@ void flipUpdateSecondaryParticles(const std::string mode, k_d, c_s, c_b, - dt, + timestep, exclude, antitunneling, itype); @@ -1764,10 +1776,11 @@ static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds) const Real k_d = _args.get<Real>("k_d", 11, &_lock); const Real c_s = _args.get<Real>("c_s", 12, &_lock); const Real c_b = _args.get<Real>("c_b", 13, &_lock); - const Real dt = _args.get<Real>("dt", 14, &_lock); - const int exclude = _args.getOpt<int>("exclude", 15, ParticleBase::PTRACER, &_lock); - const int antitunneling = _args.getOpt<int>("antitunneling", 16, 0, &_lock); - const int itype = _args.getOpt<int>("itype", 17, FlagGrid::TypeFluid, &_lock); + const Real dt = _args.getOpt<Real>("dt", 14, 0, &_lock); + bool scale = _args.getOpt<bool>("scale", 15, true, &_lock); + const int exclude = _args.getOpt<int>("exclude", 16, ParticleBase::PTRACER, &_lock); + const int antitunneling = _args.getOpt<int>("antitunneling", 17, 0, &_lock); + const int itype = _args.getOpt<int>("itype", 18, FlagGrid::TypeFluid, &_lock); _retval = getPyNone(); flipUpdateSecondaryParticles(mode, pts_sec, @@ -1784,6 +1797,7 @@ static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds) c_s, c_b, dt, + scale, exclude, antitunneling, itype); diff --git a/extern/wcwidth/wcwidth.h b/extern/wcwidth/wcwidth.h index d87eaf20695..3039a50bddd 100644 --- a/extern/wcwidth/wcwidth.h +++ b/extern/wcwidth/wcwidth.h @@ -21,7 +21,7 @@ #define __WCWIDTH_H__ #ifndef __cplusplus -# if defined(__APPLE__) +# if defined(__APPLE__) || defined(__NetBSD__) /* The <uchar.h> standard header is missing on macOS. */ #include <stddef.h> typedef unsigned int char32_t; diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index 4e780dc9f0f..fa18f4d793a 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -20,7 +20,6 @@ # add_subdirectory(atomic) # header only add_subdirectory(clog) -add_subdirectory(string) add_subdirectory(ghost) add_subdirectory(guardedalloc) add_subdirectory(libmv) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 7cf615620a3..08641c05941 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -500,8 +500,9 @@ class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel): col = layout.column() col.prop(cscene, "blur_glossy") - col.prop(cscene, "caustics_reflective") - col.prop(cscene, "caustics_refractive") + col = layout.column(heading="Caustics", align=True) + col.prop(cscene, "caustics_reflective", text="Reflective") + col.prop(cscene, "caustics_refractive", text="Refractive") class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel): @@ -762,22 +763,16 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel): rd = scene.render view_layer = context.view_layer - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() + col = layout.column(heading="Include") col.prop(view_layer, "use_sky", text="Environment") - col = flow.column() col.prop(view_layer, "use_ao", text="Ambient Occlusion") - col = flow.column() col.prop(view_layer, "use_solid", text="Surfaces") - col = flow.column() col.prop(view_layer, "use_strand", text="Hair") - col = flow.column() col.prop(view_layer, "use_volumes", text="Volumes") if with_freestyle: - col = flow.column() - col.prop(view_layer, "use_freestyle", text="Freestyle") - col.active = rd.use_freestyle + sub = col.row(align=True) + sub.prop(view_layer, "use_freestyle", text="Freestyle") + sub.active = rd.use_freestyle class CYCLES_RENDER_PT_override(CyclesButtonsPanel, Panel): @@ -819,36 +814,27 @@ class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel): view_layer = context.view_layer cycles_view_layer = view_layer.cycles - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - col = flow.column() + col = layout.column(heading="Include", align=True) col.prop(view_layer, "use_pass_combined") - col = flow.column() col.prop(view_layer, "use_pass_z") - col = flow.column() col.prop(view_layer, "use_pass_mist") - col = flow.column() col.prop(view_layer, "use_pass_normal") - col = flow.column() - col.prop(view_layer, "use_pass_vector") - col.active = not rd.use_motion_blur - col = flow.column() + sub = col.column() + sub.active = not rd.use_motion_blur + sub.prop(view_layer, "use_pass_vector") col.prop(view_layer, "use_pass_uv") - col = flow.column() + + col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data") + + col = layout.column(heading="Indexes", align=True) col.prop(view_layer, "use_pass_object_index") - col = flow.column() col.prop(view_layer, "use_pass_material_index") - layout.separator() - - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - col = flow.column() - col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data") - col = flow.column() + col = layout.column(heading="Debug", align=True) col.prop(cycles_view_layer, "pass_debug_render_time", text="Render Time") - col = flow.column() col.prop(cycles_view_layer, "pass_debug_sample_count", text="Sample Count") - layout.separator() + layout.prop(view_layer, "pass_alpha_threshold") @@ -866,38 +852,26 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel): view_layer = context.view_layer cycles_view_layer = view_layer.cycles - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Diffuse") - row = split.row(align=True) - row.prop(view_layer, "use_pass_diffuse_direct", text="Direct", toggle=True) - row.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect", toggle=True) - row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Glossy") - row = split.row(align=True) - row.prop(view_layer, "use_pass_glossy_direct", text="Direct", toggle=True) - row.prop(view_layer, "use_pass_glossy_indirect", text="Indirect", toggle=True) - row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Transmission") - row = split.row(align=True) - row.prop(view_layer, "use_pass_transmission_direct", text="Direct", toggle=True) - row.prop(view_layer, "use_pass_transmission_indirect", text="Indirect", toggle=True) - row.prop(view_layer, "use_pass_transmission_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Volume") - row = split.row(align=True) - row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True) - row.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect", toggle=True) + col = layout.column(heading="Diffuse", align=True) + col.prop(view_layer, "use_pass_diffuse_direct", text="Direct") + col.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect") + col.prop(view_layer, "use_pass_diffuse_color", text="Color") - col = layout.column(align=True) + col = layout.column(heading="Glossy", align=True) + col.prop(view_layer, "use_pass_glossy_direct", text="Direct") + col.prop(view_layer, "use_pass_glossy_indirect", text="Indirect") + col.prop(view_layer, "use_pass_glossy_color", text="Color") + + col = layout.column(heading="Transmission", align=True) + col.prop(view_layer, "use_pass_transmission_direct", text="Direct") + col.prop(view_layer, "use_pass_transmission_indirect", text="Indirect") + col.prop(view_layer, "use_pass_transmission_color", text="Color") + + col = layout.column(heading="Volume", align=True) + col.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct") + col.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect") + + col = layout.column(heading="Other", align=True) col.prop(view_layer, "use_pass_emit", text="Emission") col.prop(view_layer, "use_pass_environment") col.prop(view_layer, "use_pass_shadow") @@ -918,11 +892,10 @@ class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, Panel): cycles_view_layer = context.view_layer.cycles - row = layout.row(align=True) - row.use_property_split = False - row.prop(cycles_view_layer, "use_pass_crypto_object", text="Object", toggle=True) - row.prop(cycles_view_layer, "use_pass_crypto_material", text="Material", toggle=True) - row.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset", toggle=True) + col = layout.column(heading="Include", align=True) + col.prop(cycles_view_layer, "use_pass_crypto_object", text="Object") + col.prop(cycles_view_layer, "use_pass_crypto_material", text="Material") + col.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset") layout.prop(cycles_view_layer, "pass_crypto_depth", text="Levels") @@ -1012,10 +985,9 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): view_layer = context.view_layer cycles_view_layer = view_layer.cycles - split = layout.split() - split.active = cycles_view_layer.use_denoising + layout.active = cycles_view_layer.use_denoising - col = split.column(align=True) + col = layout.column() if show_optix_denoising(context): col.prop(cycles_view_layer, "use_optix_denoising") @@ -1026,51 +998,29 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): return col.prop(cycles_view_layer, "denoising_radius", text="Radius") + + col = layout.column() col.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength") col.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength") col.prop(cycles_view_layer, "denoising_relative_pca") layout.separator() - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Diffuse") + col = layout.column() + col.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - row = split.row(align=True) - row.use_property_split = False + row = col.row(heading="Diffuse", align=True) row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True) row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True) - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Glossy") - - row = split.row(align=True) - row.use_property_split = False + row = col.row(heading="Glossy", align=True) row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True) row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True) - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Transmission") - - row = split.row(align=True) - row.use_property_split = False + row = col.row(heading="Transmission", align=True) row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True) row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True) - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel): bl_label = "Post Processing" @@ -1084,7 +1034,7 @@ class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel): rd = context.scene.render - col = layout.column(align=True) + col = layout.column(align=True, heading="Pipeline") col.prop(rd, "use_compositing") col.prop(rd, "use_sequencer") @@ -1273,22 +1223,18 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - layout = self.layout ob = context.object - col = flow.column() - col.prop(ob, "hide_viewport", text="Show in Viewports", invert_checkbox=True, toggle=False) - col = flow.column() - col.prop(ob, "hide_render", text="Show in Renders", invert_checkbox=True, toggle=False) - col = flow.column() - col.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False) + layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False) + + col = layout.column(heading="Show in") + col.prop(ob, "hide_viewport", text="Viewports", invert_checkbox=True, toggle=False) + col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False) if has_geometry_visibility(ob): cob = ob.cycles - col = flow.column() + col = layout.column(heading="Mask") col.prop(cob, "is_shadow_catcher") - col = flow.column() col.prop(cob, "is_holdout") @@ -1312,24 +1258,16 @@ class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel): cob = ob.cycles visibility = ob.cycles_visibility - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() + col = layout.column() col.prop(visibility, "camera") - col = flow.column() col.prop(visibility, "diffuse") - col = flow.column() col.prop(visibility, "glossy") - col = flow.column() col.prop(visibility, "transmission") - col = flow.column() col.prop(visibility, "scatter") if ob.type != 'LIGHT': - col = flow.column() - col.prop(visibility, "shadow") - - layout.separator() + sub = col.column() + sub.prop(visibility, "shadow") class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel): @@ -1352,15 +1290,13 @@ class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel): ob = context.object cob = ob.cycles - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() - col.active = scene.render.use_simplify and cscene.use_camera_cull - col.prop(cob, "use_camera_cull") + row = layout.row() + row.active = scene.render.use_simplify and cscene.use_camera_cull + row.prop(cob, "use_camera_cull") - col = flow.column() - col.active = scene.render.use_simplify and cscene.use_distance_cull - col.prop(cob, "use_distance_cull") + row = layout.row() + row.active = scene.render.use_simplify and cscene.use_distance_cull + row.prop(cob, "use_distance_cull") def panel_node_draw(layout, id_data, output_type, input_name): @@ -1474,6 +1410,8 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + light = context.light panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface') @@ -1523,6 +1461,8 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + world = context.world if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'): @@ -1542,6 +1482,8 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + world = context.world panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume') @@ -1729,6 +1671,8 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + mat = context.material if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'): layout.prop(mat, "diffuse_color") @@ -1747,6 +1691,8 @@ class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + mat = context.material # cmat = mat.cycles @@ -1765,6 +1711,8 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + mat = context.material panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement') @@ -1906,26 +1854,24 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel): sub.prop(cbk, "normal_b", text="B") elif cscene.bake_type == 'COMBINED': - row = col.row(align=True) - row.use_property_split = False - row.prop(cbk, "use_pass_direct", toggle=True) - row.prop(cbk, "use_pass_indirect", toggle=True) - flow = col.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True) + col = layout.column(heading="Lighting", align=True) + col.prop(cbk, "use_pass_direct") + col.prop(cbk, "use_pass_indirect") - flow.active = cbk.use_pass_direct or cbk.use_pass_indirect - flow.prop(cbk, "use_pass_diffuse") - flow.prop(cbk, "use_pass_glossy") - flow.prop(cbk, "use_pass_transmission") - flow.prop(cbk, "use_pass_ambient_occlusion") - flow.prop(cbk, "use_pass_emit") + col = layout.column(heading="Contributions", align=True) + col.active = cbk.use_pass_direct or cbk.use_pass_indirect + col.prop(cbk, "use_pass_diffuse") + col.prop(cbk, "use_pass_glossy") + col.prop(cbk, "use_pass_transmission") + col.prop(cbk, "use_pass_ambient_occlusion") + col.prop(cbk, "use_pass_emit") elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}: - row = col.row(align=True) - row.use_property_split = False - row.prop(cbk, "use_pass_direct", toggle=True) - row.prop(cbk, "use_pass_indirect", toggle=True) - row.prop(cbk, "use_pass_color", toggle=True) + col = layout.column(heading="Contributions", align=True) + col.prop(cbk, "use_pass_direct") + col.prop(cbk, "use_pass_indirect") + col.prop(cbk, "use_pass_color") class CYCLES_RENDER_PT_bake_selected_to_active(CyclesButtonsPanel, Panel): @@ -2131,17 +2077,17 @@ class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel): layout.active = rd.use_simplify - col = layout.column() - col.prop(cscene, "use_camera_cull") - sub = col.column() + row = layout.row(heading="Camera Culling") + row.prop(cscene, "use_camera_cull", text="") + sub = row.column() sub.active = cscene.use_camera_cull - sub.prop(cscene, "camera_cull_margin") + sub.prop(cscene, "camera_cull_margin", text="") - col = layout.column() - col.prop(cscene, "use_distance_cull") - sub = col.column() + row = layout.row(heading="Distance Culling") + row.prop(cscene, "use_distance_cull", text="") + sub = row.column() sub.active = cscene.use_distance_cull - sub.prop(cscene, "distance_cull_margin", text="Distance") + sub.prop(cscene, "distance_cull_margin", text="") class CYCLES_VIEW3D_PT_shading_render_pass(Panel): diff --git a/intern/cycles/util/util_avxb.h b/intern/cycles/util/util_avxb.h index 5c03b1d88d7..34fafd188de 100644 --- a/intern/cycles/util/util_avxb.h +++ b/intern/cycles/util/util_avxb.h @@ -57,7 +57,7 @@ struct avxb { : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a), b, 1)) { } - __forceinline operator const __m256 &(void) const + __forceinline operator const __m256 &(void)const { return m256; } diff --git a/intern/cycles/util/util_avxi.h b/intern/cycles/util/util_avxi.h index 1b3810764b7..e658a4f848f 100644 --- a/intern/cycles/util/util_avxi.h +++ b/intern/cycles/util/util_avxi.h @@ -54,7 +54,7 @@ struct avxi { __forceinline avxi(const __m256i a) : m256(a) { } - __forceinline operator const __m256i &(void) const + __forceinline operator const __m256i &(void)const { return m256; } diff --git a/intern/cycles/util/util_sseb.h b/intern/cycles/util/util_sseb.h index d817e23c47e..56f8f676ba1 100644 --- a/intern/cycles/util/util_sseb.h +++ b/intern/cycles/util/util_sseb.h @@ -57,7 +57,7 @@ struct sseb { __forceinline sseb(const __m128 input) : m128(input) { } - __forceinline operator const __m128 &(void) const + __forceinline operator const __m128 &(void)const { return m128; } diff --git a/intern/cycles/util/util_ssei.h b/intern/cycles/util/util_ssei.h index a4db9193206..e2bf81310cc 100644 --- a/intern/cycles/util/util_ssei.h +++ b/intern/cycles/util/util_ssei.h @@ -57,7 +57,7 @@ struct ssei { __forceinline ssei(const __m128i a) : m128(a) { } - __forceinline operator const __m128i &(void) const + __forceinline operator const __m128i &(void)const { return m128; } diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h index e9bff72a1ce..60cec101545 100644 --- a/intern/dualcon/dualcon.h +++ b/intern/dualcon/dualcon.h @@ -29,7 +29,7 @@ typedef float (*DualConCo)[3]; typedef unsigned int (*DualConTri)[3]; -typedef unsigned int(*DualConLoop); +typedef unsigned int *DualConLoop; typedef struct DualConInput { DualConLoop mloop; diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp index 70b3b8bb457..c9d5639cb5d 100644 --- a/intern/dualcon/intern/octree.cpp +++ b/intern/dualcon/intern/octree.cpp @@ -480,7 +480,7 @@ void Octree::trace() if (chdpath != NULL) { dc_printf("there are incomplete rings.\n"); printPaths(chdpath); - }; + } } Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 68fc9637e02..699ac4afe88 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -21,7 +21,6 @@ set(INC . ../glew-mx - ../string ../../source/blender/imbuf ../../source/blender/makesdna ) @@ -86,7 +85,6 @@ set(SRC set(LIB bf_intern_glew_mx - bf_intern_string ${GLEW_LIBRARY} ) @@ -151,7 +149,7 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL) endif() endif() -elseif(APPLE AND NOT WITH_X11) +elseif(APPLE AND NOT WITH_GHOST_X11) list(APPEND SRC intern/GHOST_DisplayManagerCocoa.mm intern/GHOST_SystemCocoa.mm @@ -179,73 +177,143 @@ elseif(APPLE AND NOT WITH_X11) ) endif() -elseif(WITH_X11) - list(APPEND INC_SYS - ${X11_X11_INCLUDE_PATH} - ) - - list(APPEND SRC - intern/GHOST_DisplayManagerX11.cpp - intern/GHOST_SystemX11.cpp - intern/GHOST_TaskbarX11.cpp - intern/GHOST_WindowX11.cpp - - intern/GHOST_DisplayManagerX11.h - intern/GHOST_IconX11.h - intern/GHOST_SystemX11.h - intern/GHOST_TaskbarX11.h - intern/GHOST_WindowX11.h - ) +elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) + if(WITH_GHOST_X11) + list(APPEND INC_SYS + ${X11_X11_INCLUDE_PATH} + ) - if(NOT WITH_GL_EGL) list(APPEND SRC - intern/GHOST_ContextGLX.cpp - - intern/GHOST_ContextGLX.h + intern/GHOST_DisplayManagerX11.cpp + intern/GHOST_SystemX11.cpp + intern/GHOST_TaskbarX11.cpp + intern/GHOST_WindowX11.cpp + + intern/GHOST_DisplayManagerX11.h + intern/GHOST_IconX11.h + intern/GHOST_SystemX11.h + intern/GHOST_TaskbarX11.h + intern/GHOST_WindowX11.h ) - endif() - if(WITH_GHOST_XDND) - add_definitions(-DWITH_XDND) + if(NOT WITH_GL_EGL) + list(APPEND SRC + intern/GHOST_ContextGLX.cpp - list(APPEND LIB - extern_xdnd - ) + intern/GHOST_ContextGLX.h + ) + endif() - list(APPEND INC - ../../extern/xdnd - ) + if(WITH_GHOST_XDND) + add_definitions(-DWITH_XDND) - list(APPEND SRC - intern/GHOST_DropTargetX11.cpp + list(APPEND LIB + extern_xdnd + ) - intern/GHOST_DropTargetX11.h - ) + list(APPEND INC + ../../extern/xdnd + ) + + list(APPEND SRC + intern/GHOST_DropTargetX11.cpp + + intern/GHOST_DropTargetX11.h + ) + endif() + + if(X11_XF86keysym_INCLUDE_PATH) + add_definitions(-DWITH_XF86KEYSYM) + list(APPEND INC_SYS + ${X11_XF86keysym_INCLUDE_PATH} + ) + endif() + + if(WITH_X11_XF86VMODE) + add_definitions(-DWITH_X11_XF86VMODE) + list(APPEND INC_SYS + ${X11_xf86vmode_INCLUDE_PATH} + ) + endif() + + if(WITH_X11_XFIXES) + add_definitions(-DWITH_X11_XFIXES) + list(APPEND INC_SYS + ${X11_Xfixes_INCLUDE_PATH} + ) + endif() + + if(WITH_X11_ALPHA) + add_definitions(-DWITH_X11_ALPHA) + endif() + + if(WITH_X11_XINPUT) + add_definitions(-DWITH_X11_XINPUT) + list(APPEND INC_SYS + ${X11_Xinput_INCLUDE_PATH} + ) + endif() + + add_definitions(-DWITH_GHOST_X11) endif() - if(X11_XF86keysym_INCLUDE_PATH) - add_definitions(-DWITH_XF86KEYSYM) + if(WITH_GHOST_WAYLAND) list(APPEND INC_SYS - ${X11_XF86keysym_INCLUDE_PATH} + ${wayland-client_INCLUDE_DIRS} + ${wayland-egl_INCLUDE_DIRS} + ${xkbcommon_INCLUDE_DIRS} + ${wayland-cursor_INCLUDE_DIRS} ) - endif() - if(WITH_X11_XF86VMODE) - add_definitions(-DWITH_X11_XF86VMODE) - list(APPEND INC_SYS - ${X11_xf86vmode_INCLUDE_PATH} + list(APPEND SRC + intern/GHOST_SystemWayland.cpp + intern/GHOST_WindowWayland.cpp + + intern/GHOST_SystemWayland.h + intern/GHOST_WindowWayland.h ) - endif() - if(WITH_X11_XFIXES) - add_definitions(-DWITH_X11_XFIXES) + pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner) + pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) + + # Generate protocols bindings. + macro(generate_protocol_bindings NAME PROT_DEF) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h + COMMAND ${WAYLAND_SCANNER} client-header ${PROT_DEF} ${NAME}-client-protocol.h + ) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c + COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${NAME}-client-protocol.c + DEPENDS ${NAME}-client-protocol.h + ) + list(APPEND SRC + ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c + ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h + ) + endmacro() + list(APPEND INC_SYS - ${X11_Xfixes_INCLUDE_PATH} + ${CMAKE_CURRENT_BINARY_DIR} + ) + + # xdg-shell. + generate_protocol_bindings( + xdg-shell + "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml" + ) + # Pointer-constraints. + generate_protocol_bindings( + pointer-constraints + "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" + ) + # Relative-pointer. + generate_protocol_bindings( + relative-pointer + "${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml" ) - endif() - if(WITH_X11_ALPHA) - add_definitions(-DWITH_X11_ALPHA) + add_definitions(-DWITH_GHOST_WAYLAND) endif() if(WITH_INPUT_NDOF) @@ -260,14 +328,6 @@ elseif(WITH_X11) add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}") endif() - if(WITH_X11_XINPUT) - add_definitions(-DWITH_X11_XINPUT) - list(APPEND INC_SYS - ${X11_Xinput_INCLUDE_PATH} - ) - endif() - - add_definitions(-DWITH_X11) elseif(WIN32) # # Warnings as errors, this is too strict! diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h index 1225262a908..8c24261644a 100644 --- a/intern/ghost/GHOST_IContext.h +++ b/intern/ghost/GHOST_IContext.h @@ -26,7 +26,6 @@ #define __GHOST_IContext_H__ #include "GHOST_Types.h" -#include "STR_String.h" /** * Interface for GHOST context. diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 58d1a08da74..9b619f5c684 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -27,6 +27,8 @@ #ifndef __GHOST_ISYSTEM_H__ #define __GHOST_ISYSTEM_H__ +#include <stdlib.h> + #include "GHOST_IContext.h" #include "GHOST_ITimerTask.h" #include "GHOST_IWindow.h" @@ -240,7 +242,7 @@ class GHOST_ISystem { * \param parentWindow: Parent (embedder) window * \return The new window (or 0 if creation failed). */ - virtual GHOST_IWindow *createWindow(const STR_String &title, + virtual GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index daf07b81e01..62290d20f1c 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -27,7 +27,9 @@ #include "GHOST_Rect.h" #include "GHOST_Types.h" -#include "STR_String.h" + +#include <stdlib.h> +#include <string> /** * Interface for GHOST windows. @@ -81,13 +83,13 @@ class GHOST_IWindow { * Sets the title displayed in the title bar. * \param title The title to display in the title bar. */ - virtual void setTitle(const STR_String &title) = 0; + virtual void setTitle(const char *title) = 0; /** * Returns the title displayed in the title bar. * \param title The title displayed in the title bar. */ - virtual void getTitle(STR_String &title) const = 0; + virtual std::string getTitle() const = 0; /** * Returns the window rectangle dimensions. diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index db9fd2e3bf9..843684b6d2e 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -24,6 +24,7 @@ */ #include <stdlib.h> +#include <string.h> #include "GHOST_C-api.h" #include "GHOST_IEvent.h" @@ -527,17 +528,15 @@ void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title) char *GHOST_GetTitle(GHOST_WindowHandle windowhandle) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - STR_String title; + std::string title = window->getTitle(); - window->getTitle(title); - - char *ctitle = (char *)malloc(title.Length() + 1); + char *ctitle = (char *)malloc(title.size() + 1); if (ctitle == NULL) { return NULL; } - strcpy(ctitle, title.Ptr()); + strcpy(ctitle, title.c_str()); return ctitle; } @@ -678,7 +677,7 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle) return context->activateDrawingContext(); } else { - GHOST_PRINT("GHOST_ActivateOpenGLContext: Context not valid"); + GHOST_PRINTF("%s: Context not valid\n", __func__); return GHOST_kFailure; } } diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index 0163197e14a..5b5c2688297 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -33,15 +33,11 @@ #endif #ifdef WITH_GHOST_DEBUG -# define GHOST_DEBUG // spit ghost events to stdout -#endif // WITH_GHOST_DEBUG - -#ifdef GHOST_DEBUG # include <iostream> # include <stdio.h> //for printf() -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG # define GHOST_PRINT(x) \ { \ std::cout << x; \ @@ -52,10 +48,10 @@ printf(x, __VA_ARGS__); \ } \ (void)0 -#else // GHOST_DEBUG +#else // WITH_GHOST_DEBUG # define GHOST_PRINT(x) # define GHOST_PRINTF(x, ...) -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG #ifdef WITH_ASSERT_ABORT # include <stdio.h> //for fprintf() @@ -70,7 +66,7 @@ } \ } \ (void)0 -#elif defined(GHOST_DEBUG) +#elif defined(WITH_GHOST_DEBUG) # define GHOST_ASSERT(x, info) \ { \ if (!(x)) { \ @@ -80,8 +76,8 @@ } \ } \ (void)0 -#else // GHOST_DEBUG +#else // WITH_GHOST_DEBUG # define GHOST_ASSERT(x, info) ((void)0) -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG #endif // __GHOST_DEBUG_H__ diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index aabaffc7732..3557c4cd0c5 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -80,13 +80,13 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TSuccess success; DEVMODE dm; if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) { -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG setting.xPixels = dm.dmPelsWidth; setting.yPixels = dm.dmPelsHeight; setting.bpp = dm.dmBitsPerPel; @@ -142,16 +142,16 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting( * dm.dmSize = sizeof(DEVMODE); * dm.dmDriverExtra = 0; */ -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG printf("display change: Requested settings:\n"); printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel); printf(" dmPelsWidth=%d\n", dm.dmPelsWidth); printf(" dmPelsHeight=%d\n", dm.dmPelsHeight); printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN); -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG switch (status) { case DISP_CHANGE_SUCCESSFUL: printf("display change: The settings change was successful.\n"); @@ -182,6 +182,6 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting( printf("display change: Return value invalid\n"); break; } -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return status == DISP_CHANGE_SUCCESSFUL ? GHOST_kSuccess : GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 9f8ce3b5095..fe11d9a28f2 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -28,10 +28,10 @@ #include "utf_winfunc.h" #include "utfconv.h" -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG // utility void printLastError(void); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system) : m_window(window), m_system(system) @@ -209,9 +209,9 @@ void *GHOST_DropTargetWin32::getGhostData(IDataObject *pDataObject) // return getDropDataAsBitmap(pDataObject); break; default: -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printf("\nGHOST_kDragnDropTypeUnknown"); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return NULL; break; } @@ -284,10 +284,10 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject) // Free memory ::GlobalUnlock(stgmed.hGlobal); ::ReleaseStgMedium(&stgmed); -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n", tmp_string); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return tmp_string; } } @@ -336,9 +336,9 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out) NULL); if (!size) { -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printLastError(); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return 0; } @@ -351,16 +351,16 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out) size = ::WideCharToMultiByte(CP_ACP, 0x00000400, in, -1, (LPSTR)out, size, NULL, NULL); if (!size) { -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printLastError(); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG ::free(out); out = NULL; } return size; } -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG void printLastError(void) { LPTSTR s; @@ -378,4 +378,4 @@ void printLastError(void) LocalFree(s); } } -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h index 24e20b20659..8f59c555914 100644 --- a/intern/ghost/intern/GHOST_EventKey.h +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -25,6 +25,8 @@ #ifndef __GHOST_EVENTKEY_H__ #define __GHOST_EVENTKEY_H__ +#include <string.h> + #include "GHOST_Event.h" /** diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h index fad9ec3cc69..ead16525ec6 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.h +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -27,8 +27,6 @@ #include "GHOST_IEventConsumer.h" -#include "STR_String.h" - /** * An Event consumer that prints all the events to standard out. * Really useful when debugging. diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp index 914f6712676..7c12bfe0306 100644 --- a/intern/ghost/intern/GHOST_ISystem.cpp +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -27,20 +27,22 @@ #include "GHOST_ISystem.h" -#ifdef WITH_X11 +#if defined(WITH_HEADLESS) +# include "GHOST_SystemNULL.h" +#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND) +# include "GHOST_SystemWayland.h" # include "GHOST_SystemX11.h" -#else -# ifdef WITH_HEADLESS -# include "GHOST_SystemNULL.h" -# elif defined(WITH_GHOST_SDL) -# include "GHOST_SystemSDL.h" -# elif defined(WIN32) -# include "GHOST_SystemWin32.h" -# else -# ifdef __APPLE__ -# include "GHOST_SystemCocoa.h" -# endif -# endif +# include <stdexcept> +#elif defined(WITH_GHOST_X11) +# include "GHOST_SystemX11.h" +#elif defined(WITH_GHOST_WAYLAND) +# include "GHOST_SystemWayland.h" +#elif defined(WITH_GHOST_SDL) +# include "GHOST_SystemSDL.h" +#elif defined(WIN32) +# include "GHOST_SystemWin32.h" +#elif defined(__APPLE__) +# include "GHOST_SystemCocoa.h" #endif GHOST_ISystem *GHOST_ISystem::m_system = NULL; @@ -49,20 +51,29 @@ GHOST_TSuccess GHOST_ISystem::createSystem() { GHOST_TSuccess success; if (!m_system) { -#ifdef WITH_X11 - m_system = new GHOST_SystemX11(); -#else -# ifdef WITH_HEADLESS +#if defined(WITH_HEADLESS) m_system = new GHOST_SystemNULL(); -# elif defined(WITH_GHOST_SDL) +#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND) + /* Special case, try Wayland, fall back to X11. */ + try { + m_system = new GHOST_SystemWayland(); + } + catch (const std::runtime_error &) { + /* fallback to X11. */ + } + if (!m_system) { + m_system = new GHOST_SystemX11(); + } +#elif defined(WITH_GHOST_X11) + m_system = new GHOST_SystemX11(); +#elif defined(WITH_GHOST_WAYLAND) + m_system = new GHOST_SystemWayland(); +#elif defined(WITH_GHOST_SDL) m_system = new GHOST_SystemSDL(); -# elif defined(WIN32) +#elif defined(WIN32) m_system = new GHOST_SystemWin32(); -# else -# ifdef __APPLE__ +#elif defined(__APPLE__) m_system = new GHOST_SystemCocoa(); -# endif -# endif #endif success = m_system != NULL ? GHOST_kSuccess : GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h index cddb557d163..5794a682023 100644 --- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h +++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h @@ -33,7 +33,7 @@ class GHOST_IXrGraphicsBinding { public: union { -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) XrGraphicsBindingOpenGLXlibKHR glx; #elif defined(WIN32) XrGraphicsBindingOpenGLWin32KHR wgl; diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index a9fbadab37a..dda78c0ac5b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -19,6 +19,8 @@ #include "GHOST_EventKey.h" #include "GHOST_EventNDOF.h" #include "GHOST_WindowManager.h" + +#include <limits.h> #include <math.h> #include <stdio.h> // for error/info reporting #include <string.h> // for memory functions diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 85eb6d58679..587e4c28102 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -309,12 +309,12 @@ GHOST_TSuccess GHOST_System::init() m_windowManager = new GHOST_WindowManager(); m_eventManager = new GHOST_EventManager(); -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG if (m_eventManager) { m_eventPrinter = new GHOST_EventPrinter(); m_eventManager->addConsumer(m_eventPrinter); } -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG if (m_timerManager && m_windowManager && m_eventManager) { return GHOST_kSuccess; @@ -367,7 +367,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager"); // GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n"); - *window = (GHOST_Window *)createWindow(STR_String(""), + *window = (GHOST_Window *)createWindow("", 0, 0, settings.xPixels, diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index eaaa2ff6ee6..0f58be49dff 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -31,9 +31,9 @@ #include "GHOST_Debug.h" #include "GHOST_EventManager.h" #include "GHOST_ModifierKeys.h" -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG # include "GHOST_EventPrinter.h" -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG class GHOST_DisplayManager; class GHOST_Event; @@ -390,9 +390,9 @@ class GHOST_System : public GHOST_ISystem { #endif /** Prints all the events. */ -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG GHOST_EventPrinter *m_eventPrinter; -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG /** Settings of the display before the display went fullscreen. */ GHOST_DisplaySetting m_preFullScreenSetting; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 1e44c3e31d4..d058697470a 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -100,7 +100,7 @@ class GHOST_SystemCocoa : public GHOST_System { * \param parentWindow Parent (embedder) window * \return The new window (or 0 if creation failed). */ - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 3d6d187587c..5592078e20e 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -698,7 +698,7 @@ void GHOST_SystemCocoa::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3 getMainDisplayDimensions(width, height); } -GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -1063,14 +1063,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, } switch (eventType) { case GHOST_kEventWindowClose: - // check for index of mainwindow as it would quit blender without dialog and discard - if ([windowsList count] > 1 && - window->getCocoaWindow() != [windowsList objectAtIndex:[windowsList count] - 1]) { - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window)); - } - else { - handleQuitRequest(); // -> quit dialog - } + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window)); break; case GHOST_kEventWindowActivate: m_windowManager->setActiveWindow(window); diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h index 68a726f2be8..186cb92d1aa 100644 --- a/intern/ghost/intern/GHOST_SystemNULL.h +++ b/intern/ghost/intern/GHOST_SystemNULL.h @@ -106,7 +106,7 @@ class GHOST_SystemNULL : public GHOST_System { return GHOST_kFailure; } - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index 97a75d7a0f5..b32ec4306e8 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -49,7 +49,7 @@ GHOST_SystemSDL::~GHOST_SystemSDL() SDL_Quit(); } -GHOST_IWindow *GHOST_SystemSDL::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index 1994781530b..8feec9de61d 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -80,7 +80,7 @@ class GHOST_SystemSDL : public GHOST_System { private: GHOST_TSuccess init(); - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp new file mode 100644 index 00000000000..1ec63a0a41b --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -0,0 +1,1673 @@ +/* + * 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 GHOST + */ + +#include "GHOST_SystemWayland.h" +#include "GHOST_Event.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventCursor.h" +#include "GHOST_EventDragnDrop.h" +#include "GHOST_EventKey.h" +#include "GHOST_EventWheel.h" +#include "GHOST_WindowManager.h" + +#include "GHOST_ContextEGL.h" + +#include <EGL/egl.h> +#include <wayland-egl.h> + +#include <algorithm> +#include <atomic> +#include <exception> +#include <thread> +#include <unordered_map> +#include <unordered_set> + +#include <pointer-constraints-client-protocol.h> +#include <relative-pointer-client-protocol.h> +#include <wayland-cursor.h> +#include <xkbcommon/xkbcommon.h> + +#include <fcntl.h> +#include <linux/input-event-codes.h> +#include <sys/mman.h> +#include <unistd.h> + +#include <cstring> + +struct output_t { + struct wl_output *output; + int32_t width, height; + int transform; + int scale; + std::string make; + std::string model; +}; + +struct buffer_t { + void *data; + size_t size; +}; + +struct cursor_t { + bool visible; + struct wl_surface *surface = nullptr; + struct wl_buffer *buffer; + struct wl_cursor_image image; + struct buffer_t *file_buffer = nullptr; +}; + +struct data_offer_t { + std::unordered_set<std::string> types; + uint32_t source_actions; + uint32_t dnd_action; + struct wl_data_offer *id; + std::atomic<bool> in_use; + struct { + int x, y; + } dnd; +}; + +struct data_source_t { + struct wl_data_source *data_source; + /** Last device that was active. */ + uint32_t source_serial; + char *buffer_out; +}; + +struct input_t { + GHOST_SystemWayland *system; + + std::string name; + struct wl_seat *seat; + struct wl_pointer *pointer = nullptr; + struct wl_keyboard *keyboard = nullptr; + + uint32_t pointer_serial; + int x, y; + GHOST_Buttons buttons; + struct cursor_t cursor; + + struct zwp_relative_pointer_v1 *relative_pointer; + struct zwp_locked_pointer_v1 *locked_pointer; + + struct xkb_context *xkb_context; + struct xkb_state *xkb_state; + + struct wl_data_device *data_device = nullptr; + struct data_offer_t *data_offer_dnd; /* Drag & Drop. */ + struct data_offer_t *data_offer_copy_paste; /* Copy & Paste. */ + + struct data_source_t *data_source; +}; + +struct display_t { + GHOST_SystemWayland *system; + + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor = nullptr; + struct xdg_wm_base *xdg_shell = nullptr; + struct wl_shm *shm = nullptr; + std::vector<output_t *> outputs; + std::vector<input_t *> inputs; + struct wl_cursor_theme *cursor_theme = nullptr; + struct wl_data_device_manager *data_device_manager = nullptr; + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; + struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; + + std::vector<struct wl_surface *> os_surfaces; + std::vector<struct wl_egl_window *> os_egl_windows; +}; + +static void display_destroy(display_t *d) +{ + if (d->data_device_manager) { + wl_data_device_manager_destroy(d->data_device_manager); + } + + for (output_t *output : d->outputs) { + wl_output_destroy(output->output); + delete output; + } + + for (input_t *input : d->inputs) { + if (input->data_source) { + free(input->data_source->buffer_out); + if (input->data_source->data_source) { + wl_data_source_destroy(input->data_source->data_source); + } + delete input->data_source; + } + if (input->data_offer_copy_paste) { + wl_data_offer_destroy(input->data_offer_copy_paste->id); + delete input->data_offer_copy_paste; + } + if (input->data_device) { + wl_data_device_release(input->data_device); + } + if (input->pointer) { + if (input->cursor.file_buffer) { + munmap(input->cursor.file_buffer->data, input->cursor.file_buffer->size); + delete input->cursor.file_buffer; + } + if (input->cursor.surface) { + wl_surface_destroy(input->cursor.surface); + } + if (input->pointer) { + wl_pointer_destroy(input->pointer); + } + } + if (input->keyboard) { + wl_keyboard_destroy(input->keyboard); + } + if (input->xkb_state) { + xkb_state_unref(input->xkb_state); + } + if (input->xkb_context) { + xkb_context_unref(input->xkb_context); + } + wl_seat_destroy(input->seat); + delete input; + } + + if (d->cursor_theme) { + wl_cursor_theme_destroy(d->cursor_theme); + } + + if (d->shm) { + wl_shm_destroy(d->shm); + } + + if (d->relative_pointer_manager) { + zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager); + } + + if (d->pointer_constraints) { + zwp_pointer_constraints_v1_destroy(d->pointer_constraints); + } + + for (wl_egl_window *os_egl_window : d->os_egl_windows) { + wl_egl_window_destroy(os_egl_window); + } + + for (wl_surface *os_surface : d->os_surfaces) { + wl_surface_destroy(os_surface); + } + + if (d->compositor) { + wl_compositor_destroy(d->compositor); + } + + if (d->xdg_shell) { + xdg_wm_base_destroy(d->xdg_shell); + } + + if (eglGetDisplay) { + ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display))); + } + + if (d->display) { + wl_display_disconnect(d->display); + } + + delete d; +} + +static GHOST_TKey xkb_map_gkey(const xkb_keysym_t &sym) +{ + + GHOST_TKey gkey; + if (sym >= XKB_KEY_0 && sym <= XKB_KEY_9) { + gkey = GHOST_TKey(sym); + } + else if (sym >= XKB_KEY_KP_0 && sym <= XKB_KEY_KP_9) { + gkey = GHOST_TKey(GHOST_kKeyNumpad0 + sym - XKB_KEY_KP_0); + } + else if (sym >= XKB_KEY_A && sym <= XKB_KEY_Z) { + gkey = GHOST_TKey(sym); + } + else if (sym >= XKB_KEY_a && sym <= XKB_KEY_z) { + gkey = GHOST_TKey(sym - XKB_KEY_a + XKB_KEY_A); + } + else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F24) { + gkey = GHOST_TKey(GHOST_kKeyF1 + sym - XKB_KEY_F1); + } + else { + +#define GXMAP(k, x, y) \ + case x: \ + k = y; \ + break + + switch (sym) { + GXMAP(gkey, XKB_KEY_BackSpace, GHOST_kKeyBackSpace); + GXMAP(gkey, XKB_KEY_Tab, GHOST_kKeyTab); + GXMAP(gkey, XKB_KEY_Linefeed, GHOST_kKeyLinefeed); + GXMAP(gkey, XKB_KEY_Clear, GHOST_kKeyClear); + GXMAP(gkey, XKB_KEY_Return, GHOST_kKeyEnter); + + GXMAP(gkey, XKB_KEY_Escape, GHOST_kKeyEsc); + GXMAP(gkey, XKB_KEY_space, GHOST_kKeySpace); + GXMAP(gkey, XKB_KEY_apostrophe, GHOST_kKeyQuote); + GXMAP(gkey, XKB_KEY_comma, GHOST_kKeyComma); + GXMAP(gkey, XKB_KEY_minus, GHOST_kKeyMinus); + GXMAP(gkey, XKB_KEY_plus, GHOST_kKeyPlus); + GXMAP(gkey, XKB_KEY_period, GHOST_kKeyPeriod); + GXMAP(gkey, XKB_KEY_slash, GHOST_kKeySlash); + + GXMAP(gkey, XKB_KEY_semicolon, GHOST_kKeySemicolon); + GXMAP(gkey, XKB_KEY_equal, GHOST_kKeyEqual); + + GXMAP(gkey, XKB_KEY_bracketleft, GHOST_kKeyLeftBracket); + GXMAP(gkey, XKB_KEY_bracketright, GHOST_kKeyRightBracket); + GXMAP(gkey, XKB_KEY_backslash, GHOST_kKeyBackslash); + GXMAP(gkey, XKB_KEY_grave, GHOST_kKeyAccentGrave); + + GXMAP(gkey, XKB_KEY_Shift_L, GHOST_kKeyLeftShift); + GXMAP(gkey, XKB_KEY_Shift_R, GHOST_kKeyRightShift); + GXMAP(gkey, XKB_KEY_Control_L, GHOST_kKeyLeftControl); + GXMAP(gkey, XKB_KEY_Control_R, GHOST_kKeyRightControl); + GXMAP(gkey, XKB_KEY_Alt_L, GHOST_kKeyLeftAlt); + GXMAP(gkey, XKB_KEY_Alt_R, GHOST_kKeyRightAlt); + GXMAP(gkey, XKB_KEY_Super_L, GHOST_kKeyOS); + GXMAP(gkey, XKB_KEY_Super_R, GHOST_kKeyOS); + GXMAP(gkey, XKB_KEY_Menu, GHOST_kKeyApp); + + GXMAP(gkey, XKB_KEY_Caps_Lock, GHOST_kKeyCapsLock); + GXMAP(gkey, XKB_KEY_Num_Lock, GHOST_kKeyNumLock); + GXMAP(gkey, XKB_KEY_Scroll_Lock, GHOST_kKeyScrollLock); + + GXMAP(gkey, XKB_KEY_Left, GHOST_kKeyLeftArrow); + GXMAP(gkey, XKB_KEY_Right, GHOST_kKeyRightArrow); + GXMAP(gkey, XKB_KEY_Up, GHOST_kKeyUpArrow); + GXMAP(gkey, XKB_KEY_Down, GHOST_kKeyDownArrow); + + GXMAP(gkey, XKB_KEY_Print, GHOST_kKeyPrintScreen); + GXMAP(gkey, XKB_KEY_Pause, GHOST_kKeyPause); + + GXMAP(gkey, XKB_KEY_Insert, GHOST_kKeyInsert); + GXMAP(gkey, XKB_KEY_Delete, GHOST_kKeyDelete); + GXMAP(gkey, XKB_KEY_Home, GHOST_kKeyHome); + GXMAP(gkey, XKB_KEY_End, GHOST_kKeyEnd); + GXMAP(gkey, XKB_KEY_Page_Up, GHOST_kKeyUpPage); + GXMAP(gkey, XKB_KEY_Page_Down, GHOST_kKeyDownPage); + + GXMAP(gkey, XKB_KEY_KP_Decimal, GHOST_kKeyNumpadPeriod); + GXMAP(gkey, XKB_KEY_KP_Enter, GHOST_kKeyNumpadEnter); + GXMAP(gkey, XKB_KEY_KP_Add, GHOST_kKeyNumpadPlus); + GXMAP(gkey, XKB_KEY_KP_Subtract, GHOST_kKeyNumpadMinus); + GXMAP(gkey, XKB_KEY_KP_Multiply, GHOST_kKeyNumpadAsterisk); + GXMAP(gkey, XKB_KEY_KP_Divide, GHOST_kKeyNumpadSlash); + + GXMAP(gkey, XKB_KEY_XF86AudioPlay, GHOST_kKeyMediaPlay); + GXMAP(gkey, XKB_KEY_XF86AudioStop, GHOST_kKeyMediaStop); + GXMAP(gkey, XKB_KEY_XF86AudioPrev, GHOST_kKeyMediaFirst); + GXMAP(gkey, XKB_KEY_XF86AudioNext, GHOST_kKeyMediaLast); + default: + GHOST_PRINT("unhandled key: " << std::hex << std::showbase << sym << std::dec << " (" + << sym << ")" << std::endl); + gkey = GHOST_kKeyUnknown; + } +#undef GXMAP + } + + return gkey; +} + +static const int default_cursor_size = 24; + +static const std::unordered_map<GHOST_TStandardCursor, std::string> cursors = { + {GHOST_kStandardCursorDefault, "left_ptr"}, + {GHOST_kStandardCursorRightArrow, "right_ptr"}, + {GHOST_kStandardCursorLeftArrow, "left_ptr"}, + {GHOST_kStandardCursorInfo, ""}, + {GHOST_kStandardCursorDestroy, ""}, + {GHOST_kStandardCursorHelp, "question_arrow"}, + {GHOST_kStandardCursorWait, "watch"}, + {GHOST_kStandardCursorText, "xterm"}, + {GHOST_kStandardCursorCrosshair, "crosshair"}, + {GHOST_kStandardCursorCrosshairA, ""}, + {GHOST_kStandardCursorCrosshairB, ""}, + {GHOST_kStandardCursorCrosshairC, ""}, + {GHOST_kStandardCursorPencil, ""}, + {GHOST_kStandardCursorUpArrow, "sb_up_arrow"}, + {GHOST_kStandardCursorDownArrow, "sb_down_arrow"}, + {GHOST_kStandardCursorVerticalSplit, ""}, + {GHOST_kStandardCursorHorizontalSplit, ""}, + {GHOST_kStandardCursorEraser, ""}, + {GHOST_kStandardCursorKnife, ""}, + {GHOST_kStandardCursorEyedropper, ""}, + {GHOST_kStandardCursorZoomIn, ""}, + {GHOST_kStandardCursorZoomOut, ""}, + {GHOST_kStandardCursorMove, "move"}, + {GHOST_kStandardCursorNSEWScroll, ""}, + {GHOST_kStandardCursorNSScroll, ""}, + {GHOST_kStandardCursorEWScroll, ""}, + {GHOST_kStandardCursorStop, ""}, + {GHOST_kStandardCursorUpDown, "sb_v_double_arrow"}, + {GHOST_kStandardCursorLeftRight, "sb_h_double_arrow"}, + {GHOST_kStandardCursorTopSide, "top_side"}, + {GHOST_kStandardCursorBottomSide, "bottom_side"}, + {GHOST_kStandardCursorLeftSide, "left_side"}, + {GHOST_kStandardCursorRightSide, "right_side"}, + {GHOST_kStandardCursorTopLeftCorner, "top_left_corner"}, + {GHOST_kStandardCursorTopRightCorner, "top_right_corner"}, + {GHOST_kStandardCursorBottomRightCorner, "bottom_right_corner"}, + {GHOST_kStandardCursorBottomLeftCorner, "bottom_left_corner"}, + {GHOST_kStandardCursorCopy, "copy"}, +}; + +static constexpr const char *mime_text_plain = "text/plain"; +static constexpr const char *mime_text_utf8 = "text/plain;charset=utf-8"; +static constexpr const char *mime_text_uri = "text/uri-list"; + +static const std::unordered_map<std::string, GHOST_TDragnDropTypes> mime_dnd = { + {mime_text_plain, GHOST_kDragnDropTypeString}, + {mime_text_utf8, GHOST_kDragnDropTypeString}, + {mime_text_uri, GHOST_kDragnDropTypeFilenames}, +}; + +static const std::vector<std::string> mime_preference_order = { + mime_text_uri, + mime_text_utf8, + mime_text_plain, +}; + +static const std::vector<std::string> mime_send = { + "UTF8_STRING", + "COMPOUND_TEXT", + "TEXT", + "STRING", + "text/plain;charset=utf-8", + "text/plain", +}; + +/* -------------------------------------------------------------------- */ +/** \name Interface Callbacks + * + * These callbacks are registered for Wayland interfaces and called when + * an event is received from the compositor. + * \{ */ + +static void relative_pointer_relative_motion( + void *data, + struct zwp_relative_pointer_v1 * /*zwp_relative_pointer_v1*/, + uint32_t /*utime_hi*/, + uint32_t /*utime_lo*/, + wl_fixed_t dx, + wl_fixed_t dy, + wl_fixed_t /*dx_unaccel*/, + wl_fixed_t /*dy_unaccel*/) +{ + input_t *input = static_cast<input_t *>(data); + + input->x += wl_fixed_to_int(dx); + input->y += wl_fixed_to_int(dy); + + input->system->pushEvent( + new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + input->system->getWindowManager()->getActiveWindow(), + input->x, + input->y, + GHOST_TABLET_DATA_NONE)); +} + +static const zwp_relative_pointer_v1_listener relative_pointer_listener = { + relative_pointer_relative_motion}; + +static void dnd_events(const input_t *const input, const GHOST_TEventType event) +{ + const GHOST_TUns64 time = input->system->getMilliSeconds(); + GHOST_IWindow *const window = input->system->getWindowManager()->getActiveWindow(); + for (const std::string &type : mime_preference_order) { + input->system->pushEvent(new GHOST_EventDragnDrop(time, + event, + mime_dnd.at(type), + window, + input->data_offer_dnd->dnd.x, + input->data_offer_dnd->dnd.y, + nullptr)); + } +} + +static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive) +{ + int pipefd[2]; + pipe(pipefd); + wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + close(pipefd[1]); + + std::string data; + ssize_t len; + char buffer[4096]; + while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { + data.insert(data.end(), buffer, buffer + len); + } + close(pipefd[0]); + data_offer->in_use.store(false); + + return data; +} + +/** + * A target accepts an offered mime type. + * + * Sent when a target accepts pointer_focus or motion events. If + * a target does not accept any of the offered types, type is NULL. + */ +static void data_source_target(void * /*data*/, + struct wl_data_source * /*wl_data_source*/, + const char * /*mime_type*/) +{ + /* pass */ +} + +static void data_source_send(void *data, + struct wl_data_source * /*wl_data_source*/, + const char * /*mime_type*/, + int32_t fd) +{ + const char *const buffer = static_cast<char *>(data); + write(fd, buffer, strlen(buffer) + 1); + close(fd); +} + +static void data_source_cancelled(void * /*data*/, struct wl_data_source *wl_data_source) +{ + wl_data_source_destroy(wl_data_source); +} + +/** + * The drag-and-drop operation physically finished. + * + * The user performed the drop action. This event does not + * indicate acceptance, #wl_data_source.cancelled may still be + * emitted afterwards if the drop destination does not accept any mime type. + */ +static void data_source_dnd_drop_performed(void * /*data*/, + struct wl_data_source * /*wl_data_source*/) +{ + /* pass */ +} + +/** + * The drag-and-drop operation concluded. + * + * The drop destination finished interoperating with this data + * source, so the client is now free to destroy this data source + * and free all associated data. + */ +static void data_source_dnd_finished(void * /*data*/, struct wl_data_source * /*wl_data_source*/) +{ + /* pass */ +} + +/** + * Notify the selected action. + * + * This event indicates the action selected by the compositor + * after matching the source/destination side actions. Only one + * action (or none) will be offered here. + */ +static void data_source_action(void * /*data*/, + struct wl_data_source * /*wl_data_source*/, + uint32_t /*dnd_action*/) +{ + /* pass */ +} + +static const struct wl_data_source_listener data_source_listener = { + data_source_target, + data_source_send, + data_source_cancelled, + data_source_dnd_drop_performed, + data_source_dnd_finished, + data_source_action, +}; + +static void data_offer_offer(void *data, + struct wl_data_offer * /*wl_data_offer*/, + const char *mime_type) +{ + static_cast<data_offer_t *>(data)->types.insert(mime_type); +} + +static void data_offer_source_actions(void *data, + struct wl_data_offer * /*wl_data_offer*/, + uint32_t source_actions) +{ + static_cast<data_offer_t *>(data)->source_actions = source_actions; +} + +static void data_offer_action(void *data, + struct wl_data_offer * /*wl_data_offer*/, + uint32_t dnd_action) +{ + static_cast<data_offer_t *>(data)->dnd_action = dnd_action; +} + +static const struct wl_data_offer_listener data_offer_listener = { + data_offer_offer, + data_offer_source_actions, + data_offer_action, +}; + +static void data_device_data_offer(void * /*data*/, + struct wl_data_device * /*wl_data_device*/, + struct wl_data_offer *id) +{ + data_offer_t *data_offer = new data_offer_t; + data_offer->id = id; + wl_data_offer_add_listener(id, &data_offer_listener, data_offer); +} + +static void data_device_enter(void *data, + struct wl_data_device * /*wl_data_device*/, + uint32_t serial, + struct wl_surface * /*surface*/, + wl_fixed_t x, + wl_fixed_t y, + struct wl_data_offer *id) +{ + input_t *input = static_cast<input_t *>(data); + input->data_offer_dnd = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id)); + data_offer_t *data_offer = input->data_offer_dnd; + + data_offer->in_use.store(true); + data_offer->dnd.x = wl_fixed_to_int(x); + data_offer->dnd.y = wl_fixed_to_int(y); + + wl_data_offer_set_actions(id, + WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | + WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, + WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); + + for (const std::string &type : mime_preference_order) { + wl_data_offer_accept(id, serial, type.c_str()); + } + + dnd_events(input, GHOST_kEventDraggingEntered); +} + +static void data_device_leave(void *data, struct wl_data_device * /*wl_data_device*/) +{ + input_t *input = static_cast<input_t *>(data); + + dnd_events(input, GHOST_kEventDraggingExited); + + if (input->data_offer_dnd && !input->data_offer_dnd->in_use.load()) { + wl_data_offer_destroy(input->data_offer_dnd->id); + delete input->data_offer_dnd; + input->data_offer_dnd = nullptr; + } +} + +static void data_device_motion(void *data, + struct wl_data_device * /*wl_data_device*/, + uint32_t /*time*/, + wl_fixed_t x, + wl_fixed_t y) +{ + input_t *input = static_cast<input_t *>(data); + input->data_offer_dnd->dnd.x = wl_fixed_to_int(x); + input->data_offer_dnd->dnd.y = wl_fixed_to_int(y); + dnd_events(input, GHOST_kEventDraggingUpdated); +} + +static void data_device_drop(void *data, struct wl_data_device * /*wl_data_device*/) +{ + input_t *input = static_cast<input_t *>(data); + data_offer_t *data_offer = input->data_offer_dnd; + + const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(), + mime_preference_order.end(), + data_offer->types.begin(), + data_offer->types.end()); + + auto read_uris = [](GHOST_SystemWayland *const system, + data_offer_t *data_offer, + const std::string mime_receive) { + const int x = data_offer->dnd.x; + const int y = data_offer->dnd.y; + + const std::string data = read_pipe(data_offer, mime_receive); + + wl_data_offer_finish(data_offer->id); + wl_data_offer_destroy(data_offer->id); + + delete data_offer; + data_offer = nullptr; + + if (mime_receive == mime_text_uri) { + static constexpr const char *file_proto = "file://"; + static constexpr const char *crlf = "\r\n"; + + std::vector<std::string> uris; + + size_t pos = 0; + while (true) { + pos = data.find(file_proto, pos); + const size_t start = pos + sizeof(file_proto) - 1; + pos = data.find(crlf, pos); + const size_t end = pos; + + if (pos == std::string::npos) { + break; + } + uris.push_back(data.substr(start, end - start)); + } + + 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 *))); + for (size_t i = 0; i < uris.size(); i++) { + flist->strings[i] = static_cast<GHOST_TUns8 *>( + malloc((uris[i].size() + 1) * sizeof(GHOST_TUns8))); + memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1); + } + system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(), + GHOST_kEventDraggingDropDone, + GHOST_kDragnDropTypeFilenames, + system->getWindowManager()->getActiveWindow(), + x, + y, + flist)); + } + else if (mime_receive == mime_text_plain || mime_receive == mime_text_utf8) { + /* TODO: enable use of internal functions 'txt_insert_buf' and + * 'text_update_edited' to behave like dropped text was pasted. */ + } + wl_display_roundtrip(system->display()); + }; + + std::thread read_thread(read_uris, input->system, data_offer, mime_receive); + read_thread.detach(); +} + +static void data_device_selection(void *data, + struct wl_data_device * /*wl_data_device*/, + struct wl_data_offer *id) +{ + input_t *input = static_cast<input_t *>(data); + data_offer_t *data_offer = input->data_offer_copy_paste; + + /* Delete old data offer. */ + if (data_offer != nullptr) { + wl_data_offer_destroy(data_offer->id); + delete data_offer; + data_offer = nullptr; + } + + if (id == nullptr) { + return; + } + + /* Get new data offer. */ + data_offer = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id)); + input->data_offer_copy_paste = data_offer; + + std::string mime_receive; + for (const std::string &type : {mime_text_utf8, mime_text_plain}) { + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } + } + + auto read_selection = [](GHOST_SystemWayland *const system, + data_offer_t *data_offer, + const std::string mime_receive) { + const std::string data = read_pipe(data_offer, mime_receive); + system->setSelection(data); + }; + + std::thread read_thread(read_selection, input->system, data_offer, mime_receive); + read_thread.detach(); +} + +static const struct wl_data_device_listener data_device_listener = { + data_device_data_offer, + data_device_enter, + data_device_leave, + data_device_motion, + data_device_drop, + data_device_selection, +}; + +static void buffer_release(void * /*data*/, struct wl_buffer *wl_buffer) +{ + wl_buffer_destroy(wl_buffer); +} + +const struct wl_buffer_listener buffer_listener = { + buffer_release, +}; + +static void pointer_enter(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t surface_x, + wl_fixed_t surface_y) +{ + if (!surface) { + return; + } + input_t *input = static_cast<input_t *>(data); + input->pointer_serial = serial; + input->x = wl_fixed_to_int(surface_x); + input->y = wl_fixed_to_int(surface_y); + + static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface))->activate(); +} + +static void pointer_leave(void * /*data*/, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*serial*/, + struct wl_surface *surface) +{ + if (surface != nullptr) { + static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface))->deactivate(); + } +} + +static void pointer_motion(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*time*/, + wl_fixed_t surface_x, + wl_fixed_t surface_y) +{ + input_t *input = static_cast<input_t *>(data); + + input->x = wl_fixed_to_int(surface_x); + input->y = wl_fixed_to_int(surface_y); + + input->system->pushEvent( + new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + input->system->getWindowManager()->getActiveWindow(), + wl_fixed_to_int(surface_x), + wl_fixed_to_int(surface_y), + GHOST_TABLET_DATA_NONE)); +} + +static void pointer_button(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t serial, + uint32_t /*time*/, + uint32_t button, + uint32_t state) +{ + GHOST_TEventType etype = GHOST_kEventUnknown; + switch (state) { + case WL_POINTER_BUTTON_STATE_RELEASED: + etype = GHOST_kEventButtonUp; + break; + case WL_POINTER_BUTTON_STATE_PRESSED: + etype = GHOST_kEventButtonDown; + break; + } + + GHOST_TButtonMask ebutton = GHOST_kButtonMaskLeft; + switch (button) { + case BTN_LEFT: + ebutton = GHOST_kButtonMaskLeft; + break; + case BTN_MIDDLE: + ebutton = GHOST_kButtonMaskMiddle; + break; + case BTN_RIGHT: + ebutton = GHOST_kButtonMaskRight; + break; + } + + input_t *input = static_cast<input_t *>(data); + input->data_source->source_serial = serial; + input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED); + input->system->pushEvent( + new GHOST_EventButton(input->system->getMilliSeconds(), + etype, + input->system->getWindowManager()->getActiveWindow(), + ebutton, + GHOST_TABLET_DATA_NONE)); +} + +static void pointer_axis(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*time*/, + uint32_t axis, + wl_fixed_t value) +{ + if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) { + return; + } + input_t *input = static_cast<input_t *>(data); + input->system->pushEvent( + new GHOST_EventWheel(input->system->getMilliSeconds(), + input->system->getWindowManager()->getActiveWindow(), + std::signbit(value) ? +1 : -1)); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_enter, + pointer_leave, + pointer_motion, + pointer_button, + pointer_axis, +}; + +static void keyboard_keymap( + void *data, struct wl_keyboard * /*wl_keyboard*/, uint32_t format, int32_t fd, uint32_t size) +{ + input_t *input = static_cast<input_t *>(data); + + if ((!data) || (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)) { + close(fd); + return; + } + + char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0)); + if (map_str == MAP_FAILED) { + close(fd); + throw std::runtime_error("keymap mmap failed: " + std::string(std::strerror(errno))); + } + + struct xkb_keymap *keymap = xkb_keymap_new_from_string( + input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(map_str, size); + close(fd); + + if (!keymap) { + return; + } + + input->xkb_state = xkb_state_new(keymap); + + xkb_keymap_unref(keymap); +} + +/** + * Enter event. + * + * Notification that this seat's keyboard focus is on a certain + * surface. + */ +static void keyboard_enter(void * /*data*/, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + struct wl_surface * /*surface*/, + struct wl_array * /*keys*/) +{ + /* pass */ +} + +/** + * Leave event. + * + * Notification that this seat's keyboard focus is no longer on a + * certain surface. + */ +static void keyboard_leave(void * /*data*/, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + struct wl_surface * /*surface*/) +{ + /* pass */ +} + +/** + * A version of #xkb_state_key_get_one_sym which returns the key without any modifiers pressed. + * Needed because #GHOST_TKey uses these values as key-codes. + */ +static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(struct xkb_state *xkb_state, + xkb_keycode_t key) +{ + /* Use an empty keyboard state to access key symbol without modifiers. */ + xkb_state_get_keymap(xkb_state); + struct xkb_keymap *keymap = xkb_state_get_keymap(xkb_state); + struct xkb_state *xkb_state_empty = xkb_state_new(keymap); + + /* Enable number-lock. */ + { + const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM); + const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock"); + if (num != XKB_MOD_INVALID && mod2 != XKB_MOD_INVALID) { + xkb_state_update_mask(xkb_state_empty, (1 << mod2), 0, (1 << num), 0, 0, 0); + } + } + + const xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state_empty, key); + xkb_state_unref(xkb_state_empty); + return sym; +} + +static void keyboard_key(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t serial, + uint32_t /*time*/, + uint32_t key, + uint32_t state) +{ + input_t *input = static_cast<input_t *>(data); + + GHOST_TEventType etype = GHOST_kEventUnknown; + switch (state) { + case WL_KEYBOARD_KEY_STATE_RELEASED: + etype = GHOST_kEventKeyUp; + break; + case WL_KEYBOARD_KEY_STATE_PRESSED: + etype = GHOST_kEventKeyDown; + break; + } + + const xkb_keysym_t sym = xkb_state_key_get_one_sym_without_modifiers(input->xkb_state, key + 8); + + if (sym == XKB_KEY_NoSymbol) { + return; + } + const GHOST_TKey gkey = xkb_map_gkey(sym); + + GHOST_TEventKeyData key_data; + + if (etype == GHOST_kEventKeyDown) { + xkb_state_key_get_utf8( + input->xkb_state, key + 8, key_data.utf8_buf, sizeof(GHOST_TEventKeyData::utf8_buf)); + } + else { + key_data.utf8_buf[0] = '\0'; + } + + input->data_source->source_serial = serial; + input->system->pushEvent(new GHOST_EventKey(input->system->getMilliSeconds(), + etype, + input->system->getWindowManager()->getActiveWindow(), + gkey, + '\0', + key_data.utf8_buf, + false)); +} + +static void keyboard_modifiers(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group) +{ + xkb_state_update_mask(static_cast<input_t *>(data)->xkb_state, + mods_depressed, + mods_latched, + mods_locked, + 0, + 0, + group); +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_keymap, + keyboard_enter, + keyboard_leave, + keyboard_key, + keyboard_modifiers, +}; + +static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) +{ + input_t *input = static_cast<input_t *>(data); + input->pointer = nullptr; + input->keyboard = nullptr; + + if (capabilities & WL_SEAT_CAPABILITY_POINTER) { + input->pointer = wl_seat_get_pointer(wl_seat); + input->cursor.surface = wl_compositor_create_surface(input->system->compositor()); + input->cursor.visible = true; + input->cursor.buffer = nullptr; + input->cursor.file_buffer = new buffer_t; + wl_pointer_add_listener(input->pointer, &pointer_listener, data); + } + + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + input->keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(input->keyboard, &keyboard_listener, data); + } +} + +static void seat_name(void *data, struct wl_seat * /*wl_seat*/, const char *name) +{ + static_cast<input_t *>(data)->name = std::string(name); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + seat_name, +}; + +static void output_geometry(void *data, + struct wl_output * /*wl_output*/, + int32_t /*x*/, + int32_t /*y*/, + int32_t /*physical_width*/, + int32_t /*physical_height*/, + int32_t /*subpixel*/, + const char *make, + const char *model, + int32_t transform) +{ + output_t *output = static_cast<output_t *>(data); + output->transform = transform; + output->make = std::string(make); + output->model = std::string(model); +} + +static void output_mode(void *data, + struct wl_output * /*wl_output*/, + uint32_t /*flags*/, + int32_t width, + int32_t height, + int32_t /*refresh*/) +{ + output_t *output = static_cast<output_t *>(data); + output->width = width; + output->height = height; +} + +/** + * Sent all information about output. + * + * This event is sent after all other properties have been sent + * after binding to the output object and after any other property + * changes done after that. This allows changes to the output + * properties to be seen as atomic, even if they happen via multiple events. + */ +static void output_done(void * /*data*/, struct wl_output * /*wl_output*/) +{ +} + +static void output_scale(void *data, struct wl_output * /*wl_output*/, int32_t factor) +{ + static_cast<output_t *>(data)->scale = factor; +} + +static const struct wl_output_listener output_listener = { + output_geometry, + output_mode, + output_done, + output_scale, +}; + +static void shell_ping(void * /*data*/, struct xdg_wm_base *xdg_wm_base, uint32_t serial) +{ + xdg_wm_base_pong(xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener shell_listener = { + shell_ping, +}; + +static void global_add(void *data, + struct wl_registry *wl_registry, + uint32_t name, + const char *interface, + uint32_t /*version*/) +{ + struct display_t *display = static_cast<struct display_t *>(data); + if (!strcmp(interface, wl_compositor_interface.name)) { + display->compositor = static_cast<wl_compositor *>( + wl_registry_bind(wl_registry, name, &wl_compositor_interface, 1)); + } + else if (!strcmp(interface, xdg_wm_base_interface.name)) { + display->xdg_shell = static_cast<xdg_wm_base *>( + wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1)); + xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr); + } + else if (!strcmp(interface, wl_output_interface.name)) { + output_t *output = new output_t; + output->scale = 1; + output->output = static_cast<wl_output *>( + wl_registry_bind(wl_registry, name, &wl_output_interface, 2)); + display->outputs.push_back(output); + wl_output_add_listener(output->output, &output_listener, output); + } + else if (!strcmp(interface, wl_seat_interface.name)) { + input_t *input = new input_t; + input->system = display->system; + input->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + input->xkb_state = nullptr; + input->data_offer_dnd = nullptr; + input->data_offer_copy_paste = nullptr; + input->data_source = new data_source_t; + input->data_source->data_source = nullptr; + input->data_source->buffer_out = nullptr; + input->relative_pointer = nullptr; + input->locked_pointer = nullptr; + input->seat = static_cast<wl_seat *>( + wl_registry_bind(wl_registry, name, &wl_seat_interface, 2)); + display->inputs.push_back(input); + wl_seat_add_listener(input->seat, &seat_listener, input); + } + else if (!strcmp(interface, wl_shm_interface.name)) { + display->shm = static_cast<wl_shm *>( + wl_registry_bind(wl_registry, name, &wl_shm_interface, 1)); + } + else if (!strcmp(interface, wl_data_device_manager_interface.name)) { + display->data_device_manager = static_cast<wl_data_device_manager *>( + wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 1)); + } + else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) { + display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>( + wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1)); + } + else if (!strcmp(interface, zwp_pointer_constraints_v1_interface.name)) { + display->pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>( + wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); + } +} + +/** + * Announce removal of global object. + * + * Notify the client of removed global objects. + * + * This event notifies the client that the global identified by + * name is no longer available. If the client bound to the global + * using the bind request, the client should now destroy that object. + */ +static void global_remove(void * /*data*/, struct wl_registry * /*wl_registry*/, uint32_t /*name*/) +{ +} + +static const struct wl_registry_listener registry_listener = { + global_add, + global_remove, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ghost Implementation + * + * Wayland specific implementation of the GHOST_System interface. + * \{ */ + +GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t) +{ + d->system = this; + /* Connect to the Wayland server. */ + d->display = wl_display_connect(nullptr); + if (!d->display) { + display_destroy(d); + throw std::runtime_error("Wayland: unable to connect to display!"); + } + + /* Register interfaces. */ + struct wl_registry *registry = wl_display_get_registry(d->display); + wl_registry_add_listener(registry, ®istry_listener, d); + /* Call callback for registry listener. */ + wl_display_roundtrip(d->display); + /* Call callbacks for registered listeners. */ + wl_display_roundtrip(d->display); + wl_registry_destroy(registry); + + if (!d->xdg_shell) { + display_destroy(d); + throw std::runtime_error("Wayland: unable to access xdg_shell!"); + } + + /* Register data device per seat for IPC between Wayland clients. */ + if (d->data_device_manager) { + for (input_t *input : d->inputs) { + input->data_device = wl_data_device_manager_get_data_device(d->data_device_manager, + input->seat); + wl_data_device_add_listener(input->data_device, &data_device_listener, input); + } + } + + const char *theme = std::getenv("XCURSOR_THEME"); + const char *size = std::getenv("XCURSOR_SIZE"); + const int sizei = size ? std::stoi(size) : default_cursor_size; + + d->cursor_theme = wl_cursor_theme_load(theme, sizei, d->shm); + if (!d->cursor_theme) { + display_destroy(d); + throw std::runtime_error("Wayland: unable to access cursor themes!"); + } +} + +GHOST_SystemWayland::~GHOST_SystemWayland() +{ + display_destroy(d); +} + +bool GHOST_SystemWayland::processEvents(bool /*waitForEvent*/) +{ + wl_display_dispatch(d->display); + return true; +} + +int GHOST_SystemWayland::toggleConsole(int /*action*/) +{ + return 0; +} + +GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const +{ + if (!d->inputs.empty()) { + static const xkb_state_component mods_all = xkb_state_component( + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | + XKB_STATE_MODS_EFFECTIVE); + + keys.set(GHOST_kModifierKeyLeftShift, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == + 1); + keys.set(GHOST_kModifierKeyRightShift, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == + 1); + keys.set(GHOST_kModifierKeyLeftAlt, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LAlt", mods_all) == 1); + keys.set(GHOST_kModifierKeyRightAlt, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RAlt", mods_all) == 1); + keys.set(GHOST_kModifierKeyLeftControl, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LControl", mods_all) == 1); + keys.set(GHOST_kModifierKeyRightControl, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RControl", mods_all) == 1); + keys.set(GHOST_kModifierKeyOS, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "Super", mods_all) == 1); + keys.set(GHOST_kModifierKeyNumMasks, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "NumLock", mods_all) == 1); + + return GHOST_kSuccess; + } + return GHOST_kFailure; +} + +GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const +{ + if (!d->inputs.empty()) { + buttons = d->inputs[0]->buttons; + return GHOST_kSuccess; + } + return GHOST_kFailure; +} + +GHOST_TUns8 *GHOST_SystemWayland::getClipboard(bool /*selection*/) const +{ + GHOST_TUns8 *clipboard = static_cast<GHOST_TUns8 *>(malloc((selection.size() + 1))); + memcpy(clipboard, selection.data(), selection.size() + 1); + return clipboard; +} + +void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/) const +{ + if (!d->data_device_manager || d->inputs.empty()) { + return; + } + + data_source_t *data_source = d->inputs[0]->data_source; + + /* Copy buffer. */ + data_source->buffer_out = static_cast<char *>(malloc(strlen(buffer) + 1)); + std::strcpy(data_source->buffer_out, buffer); + + data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager); + + wl_data_source_add_listener( + data_source->data_source, &data_source_listener, data_source->buffer_out); + + for (const std::string &type : mime_send) { + wl_data_source_offer(data_source->data_source, type.c_str()); + } + + if (!d->inputs.empty() && d->inputs[0]->data_device) { + wl_data_device_set_selection( + d->inputs[0]->data_device, data_source->data_source, data_source->source_serial); + } +} + +GHOST_TUns8 GHOST_SystemWayland::getNumDisplays() const +{ + return d ? GHOST_TUns8(d->outputs.size()) : 0; +} + +GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const +{ + if (getWindowManager()->getActiveWindow() != nullptr && !d->inputs.empty()) { + x = d->inputs[0]->x; + y = d->inputs[0]->y; + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(GHOST_TInt32 /*x*/, GHOST_TInt32 /*y*/) +{ + return GHOST_kFailure; +} + +void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +{ + if (getNumDisplays() > 0) { + /* We assume first output as main. */ + width = uint32_t(d->outputs[0]->width); + height = uint32_t(d->outputs[0]->height); + } +} + +void GHOST_SystemWayland::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +{ + getMainDisplayDimensions(width, height); +} + +GHOST_IContext *GHOST_SystemWayland::createOffscreenContext() +{ + /* Create new off-screen window. */ + wl_surface *os_surface = wl_compositor_create_surface(compositor()); + wl_egl_window *os_egl_window = wl_egl_window_create(os_surface, int(1), int(1)); + + d->os_surfaces.push_back(os_surface); + d->os_egl_windows.push_back(os_egl_window); + + GHOST_Context *context = new GHOST_ContextEGL(false, + EGLNativeWindowType(os_egl_window), + EGLNativeDisplayType(d->display), + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, + 3, + 3, + GHOST_OPENGL_EGL_CONTEXT_FLAGS, + GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, + EGL_OPENGL_API); + + if (context->initializeDrawingContext()) { + return context; + } + else { + delete context; + } + + GHOST_PRINT("Cannot create off-screen EGL context" << std::endl); + + return nullptr; +} + +GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context) +{ + delete context; + return GHOST_kSuccess; +} + +GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + GHOST_GLSettings glSettings, + const bool exclusive, + const bool /*is_dialog*/, + const GHOST_IWindow *parentWindow) +{ + GHOST_WindowWayland *window = new GHOST_WindowWayland( + this, + title, + left, + top, + width, + height, + state, + parentWindow, + type, + ((glSettings.flags & GHOST_glStereoVisual) != 0), + exclusive); + + if (window) { + if (window->getValid()) { + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); + } + else { + delete window; + window = nullptr; + } + } + + return window; +} + +wl_display *GHOST_SystemWayland::display() +{ + return d->display; +} + +wl_compositor *GHOST_SystemWayland::compositor() +{ + return d->compositor; +} + +xdg_wm_base *GHOST_SystemWayland::shell() +{ + return d->xdg_shell; +} + +void GHOST_SystemWayland::setSelection(const std::string &selection) +{ + this->selection = selection; +} + +static void set_cursor_buffer(input_t *input, wl_buffer *buffer) +{ + input->cursor.visible = (buffer != nullptr); + + wl_surface_attach(input->cursor.surface, buffer, 0, 0); + wl_surface_commit(input->cursor.surface); + + if (input->cursor.visible) { + wl_surface_damage(input->cursor.surface, + 0, + 0, + int32_t(input->cursor.image.width), + int32_t(input->cursor.image.height)); + wl_pointer_set_cursor(input->pointer, + input->pointer_serial, + input->cursor.surface, + int32_t(input->cursor.image.hotspot_x), + int32_t(input->cursor.image.hotspot_y)); + } +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) : + cursors.at(GHOST_kStandardCursorDefault); + + wl_cursor *cursor = wl_cursor_theme_get_cursor(d->cursor_theme, cursor_name.c_str()); + + if (!cursor) { + GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl); + return GHOST_kFailure; + } + + struct wl_cursor_image *image = cursor->images[0]; + struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); + if (!buffer) { + return GHOST_kFailure; + } + cursor_t *c = &d->inputs[0]->cursor; + c->buffer = buffer; + c->image = *image; + + set_cursor_buffer(d->inputs[0], buffer); + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(GHOST_TStandardCursor cursorShape) +{ + return GHOST_TSuccess(cursors.count(cursorShape) && !cursors.at(cursorShape).empty()); +} + +GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool /*canInvertColor*/) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + + cursor_t *cursor = &d->inputs[0]->cursor; + + static const int32_t stride = sizex * 4; /* ARGB */ + cursor->file_buffer->size = size_t(stride * sizey); + + 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)); + + cursor->file_buffer->data = mmap( + nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + 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( + pool, 0, sizex, sizey, stride, WL_SHM_FORMAT_ARGB8888); + + wl_shm_pool_destroy(pool); + close(fd); + + wl_buffer_add_listener(buffer, &buffer_listener, nullptr); + + static constexpr uint32_t black = 0xFF000000; + static constexpr uint32_t white = 0xFFFFFFFF; + static constexpr uint32_t transparent = 0x00000000; + + uint8_t datab = 0, maskb = 0; + uint32_t *pixel; + + for (int y = 0; y < sizey; ++y) { + pixel = &static_cast<uint32_t *>(cursor->file_buffer->data)[y * sizex]; + for (int x = 0; x < sizex; ++x) { + if ((x % 8) == 0) { + datab = *bitmap++; + maskb = *mask++; + + /* Reverse bit order. */ + datab = uint8_t((datab * 0x0202020202ULL & 0x010884422010ULL) % 1023); + maskb = uint8_t((maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023); + } + + if (maskb & 0x80) { + *pixel++ = (datab & 0x80) ? white : black; + } + else { + *pixel++ = (datab & 0x80) ? white : transparent; + } + datab <<= 1; + maskb <<= 1; + } + } + + cursor->buffer = buffer; + cursor->image.width = uint32_t(sizex); + cursor->image.height = uint32_t(sizey); + cursor->image.hotspot_x = uint32_t(hotX); + cursor->image.hotspot_y = uint32_t(hotY); + + set_cursor_buffer(d->inputs[0], buffer); + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + + cursor_t *cursor = &d->inputs[0]->cursor; + if (visible) { + if (!cursor->visible) { + set_cursor_buffer(d->inputs[0], d->inputs[0]->cursor.buffer); + } + } + else { + if (cursor->visible) { + set_cursor_buffer(d->inputs[0], nullptr); + } + } + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode, + wl_surface *surface) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + + input_t *input = d->inputs[0]; + + switch (mode) { + case GHOST_kGrabDisable: + if (input->relative_pointer) { + zwp_relative_pointer_v1_destroy(input->relative_pointer); + input->relative_pointer = nullptr; + } + if (input->locked_pointer) { + zwp_locked_pointer_v1_destroy(input->locked_pointer); + input->locked_pointer = nullptr; + } + break; + + case GHOST_kGrabNormal: + case GHOST_kGrabWrap: + input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( + d->relative_pointer_manager, input->pointer); + zwp_relative_pointer_v1_add_listener( + input->relative_pointer, &relative_pointer_listener, input); + input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer( + d->pointer_constraints, + surface, + input->pointer, + nullptr, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + break; + + case GHOST_kGrabHide: + setCursorVisibility(false); + break; + } + + return GHOST_kSuccess; +} + +/** \} */ diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h new file mode 100644 index 00000000000..89cd3406b69 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -0,0 +1,111 @@ +/* + * 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 GHOST + * Declaration of GHOST_SystemWayland class. + */ + +#ifndef __GHOST_SYSTEMWAYLAND_H__ +#define __GHOST_SYSTEMWAYLAND_H__ + +#include "../GHOST_Types.h" +#include "GHOST_System.h" +#include "GHOST_WindowWayland.h" + +#include <wayland-client.h> +#include <xdg-shell-client-protocol.h> + +#include <string> + +class GHOST_WindowWayland; + +struct display_t; + +class GHOST_SystemWayland : public GHOST_System { + public: + GHOST_SystemWayland(); + + ~GHOST_SystemWayland() override; + + bool processEvents(bool waitForEvent) override; + + int toggleConsole(int action) override; + + GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override; + + GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override; + + GHOST_TUns8 *getClipboard(bool selection) const override; + + void putClipboard(GHOST_TInt8 *buffer, bool selection) const override; + + GHOST_TUns8 getNumDisplays() const override; + + GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const override; + + GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) override; + + void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override; + + void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override; + + GHOST_IContext *createOffscreenContext() 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, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + GHOST_GLSettings glSettings, + const bool exclusive, + const bool is_dialog, + const GHOST_IWindow *parentWindow) override; + + wl_display *display(); + + wl_compositor *compositor(); + + xdg_wm_base *shell(); + + void setSelection(const std::string &selection); + + GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape); + + GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape); + + GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool canInvertColor); + + GHOST_TSuccess setCursorVisibility(bool visible); + + GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode, wl_surface *surface); + + private: + struct display_t *d; + std::string selection; +}; + +#endif /* __GHOST_SYSTEMWAYLAND_H__ */ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index fdd022e44ac..849aa5a96f5 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -282,7 +282,7 @@ void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3 height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); } -GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index c6d810d2a38..b23f907608c 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -126,7 +126,7 @@ class GHOST_SystemWin32 : public GHOST_System { * \param parentWindow Parent window * \return The new window (or 0 if creation failed). */ - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 9c7368355b4..5c1f34e3a63 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -338,7 +338,7 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 * \param parentWindow Parent window * \return The new window (or 0 if creation failed). */ -GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -1881,7 +1881,7 @@ static GHOST_TKey ghost_key_from_keysym(const KeySym key) # endif #endif default: -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG printf("%s: unknown key: %lu / 0x%lx\n", __func__, key, key); #endif type = GHOST_kKeyUnknown; @@ -1905,7 +1905,7 @@ static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCo switch (id) { case MAKE_ID('T', 'L', 'D', 'E'): return GHOST_kKeyAccentGrave; -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG default: printf("%s unhandled keycode: %.*s\n", __func__, XkbKeyNameLength, id_str); break; diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index d0e0506e77b..bb01ef7e0cc 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -137,7 +137,7 @@ class GHOST_SystemX11 : public GHOST_System { * \param parentWindow Parent (embedder) window * \return The new window (or 0 if creation failed). */ - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 553a7d89df4..472149148e6 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -27,7 +27,6 @@ #include "GHOST_IWindow.h" -class STR_String; class GHOST_Context; /** @@ -61,8 +60,8 @@ class GHOST_Window : public GHOST_IWindow { * \section Interface inherited from GHOST_IWindow left for derived class * implementation. * virtual bool getValid() const = 0; - * virtual void setTitle(const STR_String& title) = 0; - * virtual void getTitle(STR_String& title) const = 0; + * virtual void setTitle(const char * title) = 0; + * 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; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index efa418deee2..15429eab5db 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -30,7 +30,6 @@ #endif // __APPLE__ #include "GHOST_Window.h" -#include "STR_String.h" @class CAMetalLayer; @class CocoaMetalView; @@ -58,7 +57,7 @@ class GHOST_WindowCocoa : public GHOST_Window { * \param stereoVisual Stereo visual for quad buffered stereo. */ GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 bottom, GHOST_TUns32 width, @@ -92,13 +91,12 @@ class GHOST_WindowCocoa : public GHOST_Window { * Sets the title displayed in the title bar. * \param title The title to display in the title bar. */ - void setTitle(const STR_String &title); - + void setTitle(const char *title); /** * Returns the title displayed in the title bar. * \param title The title displayed in the title bar. */ - void getTitle(STR_String &title) const; + std::string getTitle() const; /** * Returns the window rectangle dimensions. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 10ab05a0de1..05adc41cb8e 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -291,7 +291,7 @@ /* clang-format on */ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 bottom, GHOST_TUns32 width, @@ -482,7 +482,7 @@ void *GHOST_WindowCocoa::getOSWindow() const return (void *)m_window; } -void GHOST_WindowCocoa::setTitle(const STR_String &title) +void GHOST_WindowCocoa::setTitle(const char *title) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -524,7 +524,7 @@ void GHOST_WindowCocoa::setTitle(const STR_String &title) [pool drain]; } -void GHOST_WindowCocoa::getTitle(STR_String &title) const +std::string GHOST_WindowCocoa::getTitle() const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid"); @@ -532,11 +532,14 @@ void GHOST_WindowCocoa::getTitle(STR_String &title) const NSString *windowTitle = [m_window title]; + std::string title; if (windowTitle != nil) { title = [windowTitle UTF8String]; } [pool drain]; + + return title; } void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index db40075e6ca..e1aa0cb7f13 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -26,7 +26,6 @@ #include <map> -class STR_String; class GHOST_SystemNULL; class GHOST_WindowNULL : public GHOST_Window { @@ -37,7 +36,7 @@ class GHOST_WindowNULL : public GHOST_Window { } GHOST_WindowNULL(GHOST_SystemNULL *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -83,12 +82,12 @@ class GHOST_WindowNULL : public GHOST_Window { { return true; } - void setTitle(const STR_String &title) + void setTitle(const char *title) { /* nothing */ } - void getTitle(STR_String &title) const + std::string getTitle() const { - title = "untitled"; + return "untitled"; } void getWindowBounds(GHOST_Rect &bounds) const { diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index e8d129f45fe..dcb1ab8c78c 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -27,7 +27,7 @@ #include <assert.h> GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -148,14 +148,14 @@ bool GHOST_WindowSDL::getValid() const return GHOST_Window::getValid() && m_valid_setup; } -void GHOST_WindowSDL::setTitle(const STR_String &title) +void GHOST_WindowSDL::setTitle(const char *title) { - SDL_SetWindowTitle(m_sdl_win, title.ReadPtr()); + SDL_SetWindowTitle(m_sdl_win, title); } -void GHOST_WindowSDL::getTitle(STR_String &title) const +std::string GHOST_WindowSDL::getTitle() const { - title = SDL_GetWindowTitle(m_sdl_win); + return SDL_GetWindowTitle(m_sdl_win); } void GHOST_WindowSDL::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h index eadd1b7df9d..5039c742c9d 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.h +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -35,7 +35,6 @@ extern "C" { # error "SDL 2.0 or newer is needed to build with Ghost" #endif -class STR_String; class GHOST_SystemSDL; class GHOST_WindowSDL : public GHOST_Window { @@ -49,7 +48,7 @@ class GHOST_WindowSDL : public GHOST_Window { public: GHOST_WindowSDL(GHOST_SystemSDL *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -107,9 +106,9 @@ class GHOST_WindowSDL : public GHOST_Window { GHOST_TSuccess setWindowCursorVisibility(bool visible); - void setTitle(const STR_String &title); + void setTitle(const char *title); - void getTitle(STR_String &title) const; + std::string getTitle() const; GHOST_TSuccess setClientWidth(GHOST_TUns32 width); diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp new file mode 100644 index 00000000000..0ea6f5f8ecb --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -0,0 +1,406 @@ +/* + * 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 GHOST + */ + +#include "GHOST_WindowWayland.h" +#include "GHOST_SystemWayland.h" +#include "GHOST_WindowManager.h" + +#include "GHOST_Event.h" + +#include "GHOST_ContextEGL.h" +#include "GHOST_ContextNone.h" + +#include <wayland-egl.h> + +struct window_t { + GHOST_WindowWayland *w; + wl_surface *surface; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + wl_egl_window *egl_window; + int32_t pending_width, pending_height; + bool is_maximised; + bool is_fullscreen; + bool is_active; + int32_t width, height; +}; + +/* -------------------------------------------------------------------- */ +/** \name Wayland Interface Callbacks + * + * These callbacks are registered for Wayland interfaces and called when + * an event is received from the compositor. + * \{ */ + +static void toplevel_configure( + void *data, xdg_toplevel * /*xdg_toplevel*/, int32_t width, int32_t height, wl_array *states) +{ + window_t *win = static_cast<window_t *>(data); + win->pending_width = width; + win->pending_height = height; + + win->is_maximised = false; + win->is_fullscreen = false; + win->is_active = false; + + /* Note that the macro 'wl_array_for_each' would typically be used to simplify this logic, + * however it's not compatible with C++, so perform casts instead. + * If this needs to be done more often we could define our own C++ compatible macro. */ + for (enum xdg_toplevel_state *state = static_cast<xdg_toplevel_state *>(states->data); + reinterpret_cast<uint8_t *>(state) < (static_cast<uint8_t *>(states->data) + states->size); + state++) { + switch (*state) { + case XDG_TOPLEVEL_STATE_MAXIMIZED: + win->is_maximised = true; + break; + case XDG_TOPLEVEL_STATE_FULLSCREEN: + win->is_fullscreen = true; + break; + case XDG_TOPLEVEL_STATE_ACTIVATED: + win->is_active = true; + break; + default: + break; + } + } +} + +static void toplevel_close(void *data, xdg_toplevel * /*xdg_toplevel*/) +{ + static_cast<window_t *>(data)->w->close(); +} + +static const xdg_toplevel_listener toplevel_listener = { + toplevel_configure, + toplevel_close, +}; + +static void surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial) +{ + window_t *win = static_cast<window_t *>(data); + + int w, h; + wl_egl_window_get_attached_size(win->egl_window, &w, &h); + if (win->pending_width != 0 && win->pending_height != 0 && win->pending_width != w && + win->pending_height != h) { + win->width = win->pending_width; + win->height = win->pending_height; + wl_egl_window_resize(win->egl_window, win->pending_width, win->pending_height, 0, 0); + win->pending_width = 0; + win->pending_height = 0; + win->w->notify_size(); + } + + if (win->is_active) { + win->w->activate(); + } + else { + win->w->deactivate(); + } + + xdg_surface_ack_configure(xdg_surface, serial); +} + +static const xdg_surface_listener surface_listener = { + surface_configure, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ghost Implementation + * + * Wayland specific implementation of the GHOST_Window interface. + * \{ */ + +GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorShape) +{ + return m_system->hasCursorShape(cursorShape); +} + +GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, + const char *title, + GHOST_TInt32 /*left*/, + GHOST_TInt32 /*top*/, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_IWindow *parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const bool exclusive) + : GHOST_Window(width, height, state, stereoVisual, exclusive), + m_system(system), + w(new window_t) +{ + w->w = this; + + w->width = int32_t(width); + w->height = int32_t(height); + + /* Window surfaces. */ + w->surface = wl_compositor_create_surface(m_system->compositor()); + w->egl_window = wl_egl_window_create(w->surface, int(width), int(height)); + + w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->shell(), w->surface); + w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface); + + wl_surface_set_user_data(w->surface, this); + + xdg_surface_add_listener(w->xdg_surface, &surface_listener, w); + xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w); + + if (parentWindow) { + xdg_toplevel_set_parent( + w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel); + } + + /* Call top-level callbacks. */ + wl_surface_commit(w->surface); + wl_display_roundtrip(m_system->display()); + + setState(state); + + setTitle(title); + + /* EGL context. */ + if (setDrawingContextType(type) == GHOST_kFailure) { + GHOST_PRINT("Failed to create EGL context" << std::endl); + } +} + +GHOST_TSuccess GHOST_WindowWayland::close() +{ + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowClose, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::activate() +{ + if (m_system->getWindowManager()->setActiveWindow(this) == GHOST_kFailure) { + return GHOST_kFailure; + } + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowActivate, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::deactivate() +{ + m_system->getWindowManager()->setWindowInactive(this); + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowDeactivate, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::notify_size() +{ + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mode) +{ + return m_system->setCursorGrab(mode, w->surface); +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor shape) +{ + const GHOST_TSuccess ok = m_system->setCursorShape(shape); + m_cursorShape = (ok == GHOST_kSuccess) ? shape : GHOST_kStandardCursorDefault; + return ok; +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool canInvertColor) +{ + return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor); +} + +void GHOST_WindowWayland::setTitle(const char *title) +{ + xdg_toplevel_set_title(w->xdg_toplevel, title); + xdg_toplevel_set_app_id(w->xdg_toplevel, title); + this->title = title; +} + +std::string GHOST_WindowWayland::getTitle() const +{ + return this->title.empty() ? "untitled" : this->title; +} + +void GHOST_WindowWayland::getWindowBounds(GHOST_Rect &bounds) const +{ + getClientBounds(bounds); +} + +void GHOST_WindowWayland::getClientBounds(GHOST_Rect &bounds) const +{ + bounds.set(0, 0, w->width, w->height); +} + +GHOST_TSuccess GHOST_WindowWayland::setClientWidth(GHOST_TUns32 width) +{ + return setClientSize(width, GHOST_TUns32(w->height)); +} + +GHOST_TSuccess GHOST_WindowWayland::setClientHeight(GHOST_TUns32 height) +{ + return setClientSize(GHOST_TUns32(w->width), height); +} + +GHOST_TSuccess GHOST_WindowWayland::setClientSize(GHOST_TUns32 width, GHOST_TUns32 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 +{ + outX = inX; + outY = inY; +} + +void GHOST_WindowWayland::clientToScreen(GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32 &outX, + GHOST_TInt32 &outY) const +{ + outX = inX; + outY = inY; +} + +GHOST_WindowWayland::~GHOST_WindowWayland() +{ + releaseNativeHandles(); + + wl_egl_window_destroy(w->egl_window); + xdg_toplevel_destroy(w->xdg_toplevel); + xdg_surface_destroy(w->xdg_surface); + wl_surface_destroy(w->surface); + + delete w; +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible) +{ + return m_system->setCursorVisibility(visible); +} + +GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state) +{ + switch (state) { + case GHOST_kWindowStateNormal: + /* Unset states. */ + switch (getState()) { + case GHOST_kWindowStateMaximized: + xdg_toplevel_unset_maximized(w->xdg_toplevel); + break; + case GHOST_kWindowStateFullScreen: + xdg_toplevel_unset_fullscreen(w->xdg_toplevel); + break; + default: + break; + } + break; + case GHOST_kWindowStateMaximized: + xdg_toplevel_set_maximized(w->xdg_toplevel); + break; + case GHOST_kWindowStateMinimized: + xdg_toplevel_set_minimized(w->xdg_toplevel); + break; + case GHOST_kWindowStateFullScreen: + xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr); + break; + case GHOST_kWindowStateEmbedded: + return GHOST_kFailure; + } + return GHOST_kSuccess; +} + +GHOST_TWindowState GHOST_WindowWayland::getState() const +{ + if (w->is_fullscreen) { + return GHOST_kWindowStateFullScreen; + } + else if (w->is_maximised) { + return GHOST_kWindowStateMaximized; + } + else { + return GHOST_kWindowStateNormal; + } +} + +GHOST_TSuccess GHOST_WindowWayland::invalidate() +{ + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/) +{ + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const +{ + xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr); + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const +{ + xdg_toplevel_unset_fullscreen(w->xdg_toplevel); + return GHOST_kSuccess; +} + +/** + * \param type The type of rendering context create. + * \return Indication of success. + */ +GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType type) +{ + GHOST_Context *context; + switch (type) { + case GHOST_kDrawingContextTypeNone: + context = new GHOST_ContextNone(m_wantStereoVisual); + break; + case GHOST_kDrawingContextTypeOpenGL: + context = new GHOST_ContextEGL(m_wantStereoVisual, + EGLNativeWindowType(w->egl_window), + EGLNativeDisplayType(m_system->display()), + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, + 3, + 3, + GHOST_OPENGL_EGL_CONTEXT_FLAGS, + GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, + EGL_OPENGL_API); + break; + } + + return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr; +} + +/** \} */ diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h new file mode 100644 index 00000000000..39c35f77d7d --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -0,0 +1,121 @@ +/* + * 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 GHOST + * + * Declaration of GHOST_WindowWayland class. + */ + +#ifndef __GHOST_WINDOWWAYLAND_H__ +#define __GHOST_WINDOWWAYLAND_H__ + +#include "GHOST_Window.h" + +class GHOST_SystemWayland; + +struct window_t; + +class GHOST_WindowWayland : public GHOST_Window { + public: + GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape) override; + + GHOST_WindowWayland(GHOST_SystemWayland *system, + const char *title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_IWindow *parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const bool exclusive); + + ~GHOST_WindowWayland() override; + + GHOST_TSuccess close(); + + GHOST_TSuccess activate(); + + GHOST_TSuccess deactivate(); + + GHOST_TSuccess notify_size(); + + protected: + GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override; + + GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override; + + GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool canInvertColor) override; + + void setTitle(const char *title) override; + + std::string getTitle() const override; + + void getWindowBounds(GHOST_Rect &bounds) const override; + + void getClientBounds(GHOST_Rect &bounds) const override; + + GHOST_TSuccess setClientWidth(GHOST_TUns32 width) override; + + GHOST_TSuccess setClientHeight(GHOST_TUns32 height) override; + + GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) override; + + void screenToClient(GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32 &outX, + GHOST_TInt32 &outY) const override; + + void clientToScreen(GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32 &outX, + GHOST_TInt32 &outY) const override; + + GHOST_TSuccess setWindowCursorVisibility(bool visible) override; + + GHOST_TSuccess setState(GHOST_TWindowState state) override; + + GHOST_TWindowState getState() const override; + + GHOST_TSuccess invalidate() override; + + GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override; + + GHOST_TSuccess beginFullScreen() const override; + + GHOST_TSuccess endFullScreen() const override; + + private: + GHOST_SystemWayland *m_system; + struct window_t *w; + std::string title; + + /** + * \param type The type of rendering context create. + * \return Indication of success. + */ + GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override; +}; + +#endif // __GHOST_WINDOWWAYLAND_H__ diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 8b95cdd6351..55525157753 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -59,7 +59,7 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; } GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -158,7 +158,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, height = rect.bottom - rect.top; } - wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0); + wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name title_16, // pointer to window name wintype, // window style @@ -173,7 +173,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, free(title_16); } else { - wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0); + wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name title_16, // pointer to window name WS_MAXIMIZE, // window style @@ -430,19 +430,18 @@ HWND GHOST_WindowWin32::getHWND() const return m_hWnd; } -void GHOST_WindowWin32::setTitle(const STR_String &title) +void GHOST_WindowWin32::setTitle(const char *title) { - wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0); + wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); ::SetWindowTextW(m_hWnd, (wchar_t *)title_16); free(title_16); } -void GHOST_WindowWin32::getTitle(STR_String &title) const +std::string GHOST_WindowWin32::getTitle() const { char buf[s_maxTitleLength]; /*CHANGE + never used yet*/ ::GetWindowText(m_hWnd, buf, s_maxTitleLength); - STR_String temp(buf); - title = buf; + return std::string(buf); } void GHOST_WindowWin32::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 489d3032552..dbed7c5ee5f 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -261,7 +261,7 @@ class GHOST_WindowWin32 : public GHOST_Window { * \param parentWindowHwnd */ GHOST_WindowWin32(GHOST_SystemWin32 *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -296,13 +296,13 @@ class GHOST_WindowWin32 : public GHOST_Window { * Sets the title displayed in the title bar. * \param title The title to display in the title bar. */ - void setTitle(const STR_String &title); + void setTitle(const char *title); /** * Returns the title displayed in the title bar. - * \param title The title displayed in the title bar. + * \return The title displayed in the title bar. */ - void getTitle(STR_String &title) const; + std::string getTitle() const; /** * Returns the window rectangle dimensions. diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index db9f6846b11..691f1790a2d 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -33,7 +33,6 @@ #include "GHOST_IconX11.h" #include "GHOST_SystemX11.h" #include "GHOST_WindowX11.h" -#include "STR_String.h" #ifdef WITH_XDND # include "GHOST_DropTargetX11.h" @@ -61,6 +60,7 @@ #include <unistd.h> #include <algorithm> +#include <limits.h> #include <math.h> #include <string> @@ -212,7 +212,7 @@ static XVisualInfo *x11_visualinfo_from_glx(Display *display, GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -414,9 +414,9 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, /* XClassHint, title */ { XClassHint *xclasshint = XAllocClassHint(); - const int len = title.Length() + 1; + const int len = strlen(title) + 1; char *wmclass = (char *)malloc(sizeof(char) * len); - memcpy(wmclass, title.ReadPtr(), len * sizeof(char)); + memcpy(wmclass, title, len * sizeof(char)); xclasshint->res_name = wmclass; xclasshint->res_class = wmclass; XSetClassHint(m_display, m_window, xclasshint); @@ -617,7 +617,7 @@ bool GHOST_WindowX11::getValid() const return GHOST_Window::getValid() && m_valid_setup; } -void GHOST_WindowX11::setTitle(const STR_String &title) +void GHOST_WindowX11::setTitle(const char *title) { Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0); Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0); @@ -627,8 +627,8 @@ void GHOST_WindowX11::setTitle(const STR_String &title) utf8str, 8, PropModeReplace, - (const unsigned char *)title.ReadPtr(), - title.Length()); + (const unsigned char *)title, + strlen(title)); /* This should convert to valid x11 string * and getTitle would need matching change */ @@ -637,13 +637,14 @@ void GHOST_WindowX11::setTitle(const STR_String &title) XFlush(m_display); } -void GHOST_WindowX11::getTitle(STR_String &title) const +std::string GHOST_WindowX11::getTitle() const { char *name = NULL; XFetchName(m_display, m_window, &name); - title = name ? name : "untitled"; + std::string title = name ? name : "untitled"; XFree(name); + return title; } void GHOST_WindowX11::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 4704cb45e58..4232ff40b52 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -37,7 +37,6 @@ #include <map> -class STR_String; class GHOST_SystemX11; #ifdef WITH_XDND @@ -69,7 +68,7 @@ class GHOST_WindowX11 : public GHOST_Window { */ GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -85,9 +84,9 @@ class GHOST_WindowX11 : public GHOST_Window { bool getValid() const; - void setTitle(const STR_String &title); + void setTitle(const char *title); - void getTitle(STR_String &title) const; + std::string getTitle() const; void getWindowBounds(GHOST_Rect &bounds) const; diff --git a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp index 60b3b06f6a8..5e30502f7ff 100644 --- a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp +++ b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp @@ -22,7 +22,7 @@ #include <list> #include <sstream> -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) # include "GHOST_ContextGLX.h" #elif defined(WIN32) # include "GHOST_ContextD3D.h" @@ -68,7 +68,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding { XrSystemId system_id, std::string *r_requirement_info) const override { -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) GHOST_ContextGLX *ctx_gl = static_cast<GHOST_ContextGLX *>(ghost_ctx); #else GHOST_ContextWGL *ctx_gl = static_cast<GHOST_ContextWGL *>(ghost_ctx); @@ -107,7 +107,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding { void initFromGhostContext(GHOST_Context *ghost_ctx) override { -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) GHOST_ContextGLX *ctx_glx = static_cast<GHOST_ContextGLX *>(ghost_ctx); XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx->m_display, ctx_glx->m_fbconfig); diff --git a/intern/ghost/intern/GHOST_Xr_openxr_includes.h b/intern/ghost/intern/GHOST_Xr_openxr_includes.h index 925d6037750..9cac43b1549 100644 --- a/intern/ghost/intern/GHOST_Xr_openxr_includes.h +++ b/intern/ghost/intern/GHOST_Xr_openxr_includes.h @@ -42,7 +42,7 @@ #ifdef XR_USE_GRAPHICS_API_D3D12 # include <d3d12.h> #endif -#ifdef WITH_X11 +#ifdef WITH_GHOST_X11 # include <GL/glxew.h> #endif diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt index eda41eb9c1a..b6e3c0ecf5f 100644 --- a/intern/ghost/test/CMakeLists.txt +++ b/intern/ghost/test/CMakeLists.txt @@ -85,8 +85,9 @@ endif() # Libraries if(UNIX AND NOT APPLE) - set(WITH_X11 ON) + set(WITH_GHOST_X11 ON) endif() + # for now... default to this add_definitions(-DWITH_GL_PROFILE_COMPAT) # BLF needs this to ignore GPU library diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index a554bfeebef..c9c497aacb4 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -27,6 +27,7 @@ #include <iostream> #include <math.h> +#include <string> #if defined(WIN32) || defined(__APPLE__) # ifdef WIN32 @@ -43,7 +44,6 @@ #endif // defined(WIN32) || defined(__APPLE__) #include "GHOST_Rect.h" -#include "STR_String.h" #include "GHOST_IEvent.h" #include "GHOST_IEventConsumer.h" @@ -427,8 +427,7 @@ Application::Application(GHOST_ISystem *system) fApp = this; // Create the main window - STR_String title1("gears - main window"); - m_mainWindow = system->createWindow(title1, + m_mainWindow = system->createWindow("gears - main window", 10, 64, 320, @@ -443,8 +442,7 @@ Application::Application(GHOST_ISystem *system) } // Create a secondary window - STR_String title2("gears - secondary window"); - m_secondaryWindow = system->createWindow(title2, + m_secondaryWindow = system->createWindow("gears - secondary window", 340, 64, 320, @@ -598,8 +596,7 @@ bool Application::processEvent(GHOST_IEvent *event) case GHOST_kKeyW: if (m_mainWindow) { - STR_String title; - m_mainWindow->getTitle(title); + std::string title = m_mainWindow->getTitle(); title += "-"; m_mainWindow->setTitle(title); } diff --git a/intern/libmv/intern/camera_intrinsics.cc b/intern/libmv/intern/camera_intrinsics.cc index 89e3d0d1178..554c4350b0a 100644 --- a/intern/libmv/intern/camera_intrinsics.cc +++ b/intern/libmv/intern/camera_intrinsics.cc @@ -24,6 +24,7 @@ using libmv::CameraIntrinsics; using libmv::DivisionCameraIntrinsics; using libmv::PolynomialCameraIntrinsics; +using libmv::NukeCameraIntrinsics; libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) { @@ -55,6 +56,14 @@ libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy( *division_intrinsics); break; } + case libmv::DISTORTION_MODEL_NUKE: + { + const NukeCameraIntrinsics *nuke_intrinsics = + static_cast<const NukeCameraIntrinsics*>(orig_intrinsics); + new_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics, + *nuke_intrinsics); + break; + } default: assert(!"Unknown distortion model"); } @@ -136,6 +145,25 @@ void libmv_cameraIntrinsicsUpdate( break; } + case LIBMV_DISTORTION_MODEL_NUKE: + { + assert(camera_intrinsics->GetDistortionModelType() == + libmv::DISTORTION_MODEL_NUKE); + + NukeCameraIntrinsics *nuke_intrinsics = + (NukeCameraIntrinsics *) camera_intrinsics; + + double k1 = libmv_camera_intrinsics_options->nuke_k1; + double k2 = libmv_camera_intrinsics_options->nuke_k2; + + if (nuke_intrinsics->k1() != k1 || + nuke_intrinsics->k2() != k2) { + nuke_intrinsics->SetDistortion(k1, k2); + } + + break; + } + default: assert(!"Unknown distortion model"); } @@ -189,6 +217,17 @@ void libmv_cameraIntrinsicsExtractOptions( break; } + case libmv::DISTORTION_MODEL_NUKE: + { + const NukeCameraIntrinsics *nuke_intrinsics = + static_cast<const NukeCameraIntrinsics *>(camera_intrinsics); + camera_intrinsics_options->distortion_model = + LIBMV_DISTORTION_MODEL_NUKE; + camera_intrinsics_options->nuke_k1 = nuke_intrinsics->k1(); + camera_intrinsics_options->nuke_k2 = nuke_intrinsics->k2(); + break; + } + default: assert(!"Unknown distortion model"); } @@ -316,6 +355,17 @@ static void libmv_cameraIntrinsicsFillFromOptions( break; } + case LIBMV_DISTORTION_MODEL_NUKE: + { + NukeCameraIntrinsics *nuke_intrinsics = + static_cast<NukeCameraIntrinsics*>(camera_intrinsics); + + nuke_intrinsics->SetDistortion( + camera_intrinsics_options->nuke_k1, + camera_intrinsics_options->nuke_k2); + break; + } + default: assert(!"Unknown distortion model"); } @@ -331,6 +381,9 @@ CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions( case LIBMV_DISTORTION_MODEL_DIVISION: camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics); break; + case LIBMV_DISTORTION_MODEL_NUKE: + camera_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics); + break; default: assert(!"Unknown distortion model"); } diff --git a/intern/libmv/intern/camera_intrinsics.h b/intern/libmv/intern/camera_intrinsics.h index 40a5826a9c4..b3d259893bd 100644 --- a/intern/libmv/intern/camera_intrinsics.h +++ b/intern/libmv/intern/camera_intrinsics.h @@ -29,6 +29,7 @@ typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics; enum { LIBMV_DISTORTION_MODEL_POLYNOMIAL = 0, LIBMV_DISTORTION_MODEL_DIVISION = 1, + LIBMV_DISTORTION_MODEL_NUKE = 2, }; typedef struct libmv_CameraIntrinsicsOptions { @@ -45,6 +46,9 @@ typedef struct libmv_CameraIntrinsicsOptions { // Division distortion model. double division_k1, division_k2; + + // Nuke distortion model. + double nuke_k1, nuke_k2; } libmv_CameraIntrinsicsOptions; libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( diff --git a/intern/libmv/libmv/simple_pipeline/bundle.cc b/intern/libmv/libmv/simple_pipeline/bundle.cc index e61650fb371..a70fdbc9888 100644 --- a/intern/libmv/libmv/simple_pipeline/bundle.cc +++ b/intern/libmv/libmv/simple_pipeline/bundle.cc @@ -66,18 +66,221 @@ enum { namespace { -// Cost functor which computes reprojection error of 3D point X -// on camera defined by angle-axis rotation and it's translation -// (which are in the same block due to optimization reasons). +bool NeedUseInvertIntrinsicsPipeline(const CameraIntrinsics *intrinsics) { + const DistortionModelType distortion_model = + intrinsics->GetDistortionModelType(); + return (distortion_model == DISTORTION_MODEL_NUKE); +} + +// Apply distortion model (distort the input) on the input point in the +// normalized space to get distorted coordinate in the image space. +// +// Using intrinsics values from the parameter block, which makes this function +// suitable for use from a cost functor. +// +// Only use for distortion models which are analytically defined for their +// Apply() function. +// +// The invariant_intrinsics are used to access intrinsics which are never +// packed into parameter block: for example, distortion model type and image +// dimension. +template<typename T> +void ApplyDistortionModelUsingIntrinsicsBlock( + const CameraIntrinsics *invariant_intrinsics, + const T* const intrinsics_block, + const T& normalized_x, const T& normalized_y, + T* distorted_x, T* distorted_y) { + // Unpack the intrinsics. + const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH]; + const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X]; + const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]; + + // TODO(keir): Do early bailouts for zero distortion; these are expensive + // jet operations. + switch (invariant_intrinsics->GetDistortionModelType()) { + case DISTORTION_MODEL_POLYNOMIAL: + { + const T& k1 = intrinsics_block[OFFSET_K1]; + const T& k2 = intrinsics_block[OFFSET_K2]; + const T& k3 = intrinsics_block[OFFSET_K3]; + const T& p1 = intrinsics_block[OFFSET_P1]; + const T& p2 = intrinsics_block[OFFSET_P2]; + + ApplyPolynomialDistortionModel(focal_length, + focal_length, + principal_point_x, + principal_point_y, + k1, k2, k3, + p1, p2, + normalized_x, normalized_y, + distorted_x, distorted_y); + return; + } + + case DISTORTION_MODEL_DIVISION: + { + const T& k1 = intrinsics_block[OFFSET_K1]; + const T& k2 = intrinsics_block[OFFSET_K2]; + + ApplyDivisionDistortionModel(focal_length, + focal_length, + principal_point_x, + principal_point_y, + k1, k2, + normalized_x, normalized_y, + distorted_x, distorted_y); + return; + } + + case DISTORTION_MODEL_NUKE: + { + LOG(FATAL) << "Unsupported distortion model."; + return; + } + } + + LOG(FATAL) << "Unknown distortion model."; +} + +// Invert distortion model (undistort the input) on the input point in the +// image space to get undistorted coordinate in the normalized space. +// +// Using intrinsics values from the parameter block, which makes this function +// suitable for use from a cost functor. +// +// Only use for distortion models which are analytically defined for their +// Invert() function. +// +// The invariant_intrinsics are used to access intrinsics which are never +// packed into parameter block: for example, distortion model type and image +// dimension. +template<typename T> +void InvertDistortionModelUsingIntrinsicsBlock( + const CameraIntrinsics *invariant_intrinsics, + const T* const intrinsics_block, + const T& image_x, const T& image_y, + T* normalized_x, T* normalized_y) { + // Unpack the intrinsics. + const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH]; + const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X]; + const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]; + + // TODO(keir): Do early bailouts for zero distortion; these are expensive + // jet operations. + switch (invariant_intrinsics->GetDistortionModelType()) { + case DISTORTION_MODEL_POLYNOMIAL: + case DISTORTION_MODEL_DIVISION: + LOG(FATAL) << "Unsupported distortion model."; + return; + + case DISTORTION_MODEL_NUKE: + { + const T& k1 = intrinsics_block[OFFSET_K1]; + const T& k2 = intrinsics_block[OFFSET_K2]; + + InvertNukeDistortionModel(focal_length, + focal_length, + principal_point_x, + principal_point_y, + invariant_intrinsics->image_width(), + invariant_intrinsics->image_height(), + k1, k2, + image_x, image_y, + normalized_x, normalized_y); + return; + } + } + + LOG(FATAL) << "Unknown distortion model."; +} + +template<typename T> +void NormalizedToImageSpace(const T* const intrinsics_block, + const T& normalized_x, const T& normalized_y, + T* image_x, T* image_y) { + // Unpack the intrinsics. + const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH]; + const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X]; + const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]; + + *image_x = normalized_x * focal_length + principal_point_x; + *image_y = normalized_y * focal_length + principal_point_y; +} + +// Cost functor which computes reprojection error of 3D point X on camera +// defined by angle-axis rotation and it's translation (which are in the same +// block due to optimization reasons). +// +// This functor can only be used for distortion models which have analytically +// defined Apply() function. +struct ReprojectionErrorApplyIntrinsics { + ReprojectionErrorApplyIntrinsics( + const CameraIntrinsics *invariant_intrinsics, + const double observed_distorted_x, + const double observed_distorted_y, + const double weight) + : invariant_intrinsics_(invariant_intrinsics), + observed_distorted_x_(observed_distorted_x), + observed_distorted_y_(observed_distorted_y), + weight_(weight) {} + + template <typename T> + bool operator()(const T* const intrinsics, + const T* const R_t, // Rotation denoted by angle axis + // followed with translation + const T* const X, // Point coordinates 3x1. + T* residuals) const { + // Compute projective coordinates: x = RX + t. + T x[3]; + + ceres::AngleAxisRotatePoint(R_t, X, x); + x[0] += R_t[3]; + x[1] += R_t[4]; + x[2] += R_t[5]; + + // Prevent points from going behind the camera. + if (x[2] < T(0)) { + return false; + } + + // Compute normalized coordinates: x /= x[2]. + T xn = x[0] / x[2]; + T yn = x[1] / x[2]; + + T predicted_distorted_x, predicted_distorted_y; + ApplyDistortionModelUsingIntrinsicsBlock( + invariant_intrinsics_, + intrinsics, + xn, yn, + &predicted_distorted_x, &predicted_distorted_y); + + // The error is the difference between the predicted and observed position. + residuals[0] = (predicted_distorted_x - T(observed_distorted_x_)) * weight_; + residuals[1] = (predicted_distorted_y - T(observed_distorted_y_)) * weight_; + return true; + } + + const CameraIntrinsics *invariant_intrinsics_; + const double observed_distorted_x_; + const double observed_distorted_y_; + const double weight_; +}; + +// Cost functor which computes reprojection error of 3D point X on camera +// defined by angle-axis rotation and it's translation (which are in the same +// block due to optimization reasons). // -// This functor uses a radial distortion model. -struct OpenCVReprojectionError { - OpenCVReprojectionError(const DistortionModelType distortion_model, - const double observed_x, - const double observed_y, - const double weight) - : distortion_model_(distortion_model), - observed_x_(observed_x), observed_y_(observed_y), +// This functor can only be used for distortion models which have analytically +// defined Invert() function. +struct ReprojectionErrorInvertIntrinsics { + ReprojectionErrorInvertIntrinsics( + const CameraIntrinsics *invariant_intrinsics, + const double observed_distorted_x, + const double observed_distorted_y, + const double weight) + : invariant_intrinsics_(invariant_intrinsics), + observed_distorted_x_(observed_distorted_x), + observed_distorted_y_(observed_distorted_y), weight_(weight) {} template <typename T> @@ -108,63 +311,37 @@ struct OpenCVReprojectionError { T xn = x[0] / x[2]; T yn = x[1] / x[2]; - T predicted_x, predicted_y; - - // Apply distortion to the normalized points to get (xd, yd). - // TODO(keir): Do early bailouts for zero distortion; these are expensive - // jet operations. - switch (distortion_model_) { - case DISTORTION_MODEL_POLYNOMIAL: - { - const T& k1 = intrinsics[OFFSET_K1]; - const T& k2 = intrinsics[OFFSET_K2]; - const T& k3 = intrinsics[OFFSET_K3]; - const T& p1 = intrinsics[OFFSET_P1]; - const T& p2 = intrinsics[OFFSET_P2]; - - ApplyPolynomialDistortionModel(focal_length, - focal_length, - principal_point_x, - principal_point_y, - k1, k2, k3, - p1, p2, - xn, yn, - &predicted_x, - &predicted_y); - break; - } - case DISTORTION_MODEL_DIVISION: - { - const T& k1 = intrinsics[OFFSET_K1]; - const T& k2 = intrinsics[OFFSET_K2]; + // Compute image space coordinate from normalized. + T predicted_x = focal_length * xn + principal_point_x; + T predicted_y = focal_length * yn + principal_point_y; - ApplyDivisionDistortionModel(focal_length, - focal_length, - principal_point_x, - principal_point_y, - k1, k2, - xn, yn, - &predicted_x, - &predicted_y); - break; - } - default: - LOG(FATAL) << "Unknown distortion model"; - } + T observed_undistorted_normalized_x, observed_undistorted_normalized_y; + InvertDistortionModelUsingIntrinsicsBlock( + invariant_intrinsics_, + intrinsics, + T(observed_distorted_x_), T(observed_distorted_y_), + &observed_undistorted_normalized_x, &observed_undistorted_normalized_y); + + T observed_undistorted_image_x, observed_undistorted_image_y; + NormalizedToImageSpace( + intrinsics, + observed_undistorted_normalized_x, observed_undistorted_normalized_y, + &observed_undistorted_image_x, &observed_undistorted_image_y); // The error is the difference between the predicted and observed position. - residuals[0] = (predicted_x - T(observed_x_)) * weight_; - residuals[1] = (predicted_y - T(observed_y_)) * weight_; + residuals[0] = (predicted_x - observed_undistorted_image_x) * weight_; + residuals[1] = (predicted_y - observed_undistorted_image_y) * weight_; + return true; } - const DistortionModelType distortion_model_; - const double observed_x_; - const double observed_y_; + const CameraIntrinsics *invariant_intrinsics_; + const double observed_distorted_x_; + const double observed_distorted_y_; const double weight_; }; -// Print a message to the log which camera intrinsics are gonna to be optimixed. +// Print a message to the log which camera intrinsics are gonna to be optimized. void BundleIntrinsicsLogMessage(const int bundle_intrinsics) { if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) { LOG(INFO) << "Bundling only camera positions."; @@ -193,29 +370,29 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) { // Pack intrinsics from object to an array for easier // and faster minimization. void PackIntrinisicsIntoArray(const CameraIntrinsics &intrinsics, - double ceres_intrinsics[OFFSET_MAX]) { - ceres_intrinsics[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length(); - ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x(); - ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y(); + double intrinsics_block[OFFSET_MAX]) { + intrinsics_block[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length(); + intrinsics_block[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x(); + intrinsics_block[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y(); int num_distortion_parameters = intrinsics.num_distortion_parameters(); assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS); const double *distortion_parameters = intrinsics.distortion_parameters(); for (int i = 0; i < num_distortion_parameters; ++i) { - ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i] = + intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i] = distortion_parameters[i]; } } // Unpack intrinsics back from an array to an object. -void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX], +void UnpackIntrinsicsFromArray(const double intrinsics_block[OFFSET_MAX], CameraIntrinsics *intrinsics) { - intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH], - ceres_intrinsics[OFFSET_FOCAL_LENGTH]); + intrinsics->SetFocalLength(intrinsics_block[OFFSET_FOCAL_LENGTH], + intrinsics_block[OFFSET_FOCAL_LENGTH]); - intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X], - ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]); + intrinsics->SetPrincipalPoint(intrinsics_block[OFFSET_PRINCIPAL_POINT_X], + intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]); int num_distortion_parameters = intrinsics->num_distortion_parameters(); assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS); @@ -223,7 +400,7 @@ void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX], double *distortion_parameters = intrinsics->distortion_parameters(); for (int i = 0; i < num_distortion_parameters; ++i) { distortion_parameters[i] = - ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i]; + intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i]; } } @@ -302,68 +479,117 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks, vector<Vec6> *all_cameras_R_t, ceres::Problem *problem, BundleEvaluation *evaluation) { - int max_track = tracks.MaxTrack(); - // Number of camera rotations equals to number of translation, - int num_cameras = all_cameras_R_t->size(); - int num_points = 0; - - vector<EuclideanPoint*> minimized_points; - for (int i = 0; i <= max_track; i++) { - EuclideanPoint *point = reconstruction->PointForTrack(i); - if (point) { - // We need to know whether the track is constant zero weight, - // and it so it wouldn't have parameter block in the problem. - // - // Getting all markers for track is not so bac currently since - // this code is only used by keyframe selection when there are - // not so much tracks and only 2 frames anyway. - vector<Marker> markera_of_track = tracks.MarkersForTrack(i); - for (int j = 0; j < markera_of_track.size(); j++) { - if (markera_of_track.at(j).weight != 0.0) { - minimized_points.push_back(point); - num_points++; - break; - } + int max_track = tracks.MaxTrack(); + // Number of camera rotations equals to number of translation, + int num_cameras = all_cameras_R_t->size(); + int num_points = 0; + + vector<EuclideanPoint*> minimized_points; + for (int i = 0; i <= max_track; i++) { + EuclideanPoint *point = reconstruction->PointForTrack(i); + if (point) { + // We need to know whether the track is a constant zero weight. + // If it is so it wouldn't have a parameter block in the problem. + // + // Usually getting all markers of a track is considered slow, but this + // code is only used by the keyframe selection code where there aren't + // that many tracks in the storage and there are only 2 frames for each + // of the tracks. + vector<Marker> markera_of_track = tracks.MarkersForTrack(i); + for (int j = 0; j < markera_of_track.size(); j++) { + if (markera_of_track.at(j).weight != 0.0) { + minimized_points.push_back(point); + num_points++; + break; } } } + } - LG << "Number of cameras " << num_cameras; - LG << "Number of points " << num_points; + LG << "Number of cameras " << num_cameras; + LG << "Number of points " << num_points; - evaluation->num_cameras = num_cameras; - evaluation->num_points = num_points; + evaluation->num_cameras = num_cameras; + evaluation->num_points = num_points; - if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix. - ceres::CRSMatrix evaluated_jacobian; - ceres::Problem::EvaluateOptions eval_options; + if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix. + ceres::CRSMatrix evaluated_jacobian; + ceres::Problem::EvaluateOptions eval_options; - // Cameras goes first in the ordering. - int max_image = tracks.MaxImage(); - for (int i = 0; i <= max_image; i++) { - const EuclideanCamera *camera = reconstruction->CameraForImage(i); - if (camera) { - double *current_camera_R_t = &(*all_cameras_R_t)[i](0); + // Cameras goes first in the ordering. + int max_image = tracks.MaxImage(); + for (int i = 0; i <= max_image; i++) { + const EuclideanCamera *camera = reconstruction->CameraForImage(i); + if (camera) { + double *current_camera_R_t = &(*all_cameras_R_t)[i](0); - // All cameras are variable now. - problem->SetParameterBlockVariable(current_camera_R_t); + // All cameras are variable now. + problem->SetParameterBlockVariable(current_camera_R_t); - eval_options.parameter_blocks.push_back(current_camera_R_t); - } + eval_options.parameter_blocks.push_back(current_camera_R_t); } + } - // Points goes at the end of ordering, - for (int i = 0; i < minimized_points.size(); i++) { - EuclideanPoint *point = minimized_points.at(i); - eval_options.parameter_blocks.push_back(&point->X(0)); - } + // Points goes at the end of ordering, + for (int i = 0; i < minimized_points.size(); i++) { + EuclideanPoint *point = minimized_points.at(i); + eval_options.parameter_blocks.push_back(&point->X(0)); + } - problem->Evaluate(eval_options, - NULL, NULL, NULL, - &evaluated_jacobian); + problem->Evaluate(eval_options, + NULL, NULL, NULL, + &evaluated_jacobian); - CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian); - } + CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian); + } +} + +template<typename CostFunction> +void AddResidualBlockToProblemImpl(const CameraIntrinsics *invariant_intrinsics, + double observed_x, double observed_y, + double weight, + double intrinsics_block[OFFSET_MAX], + double *camera_R_t, + EuclideanPoint *point, + ceres::Problem* problem) { + problem->AddResidualBlock(new ceres::AutoDiffCostFunction< + CostFunction, 2, OFFSET_MAX, 6, 3>( + new CostFunction( + invariant_intrinsics, + observed_x, observed_y, + weight)), + NULL, + intrinsics_block, + camera_R_t, + &point->X(0)); +} + +void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics, + const Marker &marker, + double marker_weight, + double intrinsics_block[OFFSET_MAX], + double *camera_R_t, + EuclideanPoint *point, + ceres::Problem* problem) { + if (NeedUseInvertIntrinsicsPipeline(invariant_intrinsics)) { + AddResidualBlockToProblemImpl<ReprojectionErrorInvertIntrinsics>( + invariant_intrinsics, + marker.x, marker.y, + marker_weight, + intrinsics_block, + camera_R_t, + point, + problem); + } else { + AddResidualBlockToProblemImpl<ReprojectionErrorApplyIntrinsics>( + invariant_intrinsics, + marker.x, marker.y, + marker_weight, + intrinsics_block, + camera_R_t, + point, + problem); + } } // This is an utility function to only bundle 3D position of @@ -375,10 +601,10 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks, // // At this point we only need to bundle points positions, cameras // are to be totally still here. -void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, +void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics, const vector<Marker> &markers, vector<Vec6> &all_cameras_R_t, - double ceres_intrinsics[OFFSET_MAX], + double intrinsics_block[OFFSET_MAX], EuclideanReconstruction *reconstruction) { ceres::Problem::Options problem_options; ceres::Problem problem(problem_options); @@ -392,20 +618,16 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, } // Rotation of camera denoted in angle axis followed with - // camera translaiton. + // camera translation. double *current_camera_R_t = &all_cameras_R_t[camera->image](0); - problem.AddResidualBlock(new ceres::AutoDiffCostFunction< - OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>( - new OpenCVReprojectionError( - distortion_model, - marker.x, - marker.y, - 1.0)), - NULL, - ceres_intrinsics, - current_camera_R_t, - &point->X(0)); + AddResidualBlockToProblem(invariant_intrinsics, + marker, + 1.0, + intrinsics_block, + current_camera_R_t, + point, + &problem); problem.SetParameterBlockConstant(current_camera_R_t); num_residuals++; @@ -417,7 +639,7 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, return; } - problem.SetParameterBlockConstant(ceres_intrinsics); + problem.SetParameterBlockConstant(intrinsics_block); // Configure the solver. ceres::Solver::Options options; @@ -438,7 +660,6 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, ceres::Solve(options, &problem, &summary); LG << "Final report:\n" << summary.FullReport(); - } } // namespace @@ -464,14 +685,14 @@ void EuclideanBundleCommonIntrinsics( LG << "Original intrinsics: " << *intrinsics; vector<Marker> markers = tracks.AllMarkers(); - // N-th element denotes whether track N is a constant zero-weigthed track. + // N-th element denotes whether track N is a constant zero-weighted track. vector<bool> zero_weight_tracks_flags(tracks.MaxTrack() + 1, true); // Residual blocks with 10 parameters are unwieldly with Ceres, so pack the // intrinsics into a single block and rely on local parameterizations to // control which intrinsics are allowed to vary. - double ceres_intrinsics[OFFSET_MAX]; - PackIntrinisicsIntoArray(*intrinsics, ceres_intrinsics); + double intrinsics_block[OFFSET_MAX]; + PackIntrinisicsIntoArray(*intrinsics, intrinsics_block); // Convert cameras rotations to angle axis and merge with translation // into single parameter block for maximal minimization speed. @@ -509,24 +730,20 @@ void EuclideanBundleCommonIntrinsics( } // Rotation of camera denoted in angle axis followed with - // camera translaiton. + // camera translation. double *current_camera_R_t = &all_cameras_R_t[camera->image](0); // Skip residual block for markers which does have absolutely // no affect on the final solution. // This way ceres is not gonna to go crazy. if (marker.weight != 0.0) { - problem.AddResidualBlock(new ceres::AutoDiffCostFunction< - OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>( - new OpenCVReprojectionError( - intrinsics->GetDistortionModelType(), - marker.x, - marker.y, - marker.weight)), - NULL, - ceres_intrinsics, - current_camera_R_t, - &point->X(0)); + AddResidualBlockToProblem(intrinsics, + marker, + marker.weight, + intrinsics_block, + current_camera_R_t, + point, + &problem); // We lock the first camera to better deal with scene orientation ambiguity. if (!have_locked_camera) { @@ -561,7 +778,7 @@ void EuclideanBundleCommonIntrinsics( if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) { // No camera intrinsics are being refined, // set the whole parameter block as constant for best performance. - problem.SetParameterBlockConstant(ceres_intrinsics); + problem.SetParameterBlockConstant(intrinsics_block); } else { // Set the camera intrinsics that are not to be bundled as // constant using some macro trickery. @@ -586,7 +803,7 @@ void EuclideanBundleCommonIntrinsics( ceres::SubsetParameterization *subset_parameterization = new ceres::SubsetParameterization(OFFSET_MAX, constant_intrinsics); - problem.SetParameterization(ceres_intrinsics, subset_parameterization); + problem.SetParameterization(intrinsics_block, subset_parameterization); } // Configure the solver. @@ -616,7 +833,7 @@ void EuclideanBundleCommonIntrinsics( // Copy intrinsics back. if (bundle_intrinsics != BUNDLE_NO_INTRINSICS) - UnpackIntrinsicsFromArray(ceres_intrinsics, intrinsics); + UnpackIntrinsicsFromArray(intrinsics_block, intrinsics); LG << "Final intrinsics: " << *intrinsics; @@ -641,10 +858,10 @@ void EuclideanBundleCommonIntrinsics( if (zero_weight_markers.size()) { LG << "Refining position of constant zero-weighted tracks"; - EuclideanBundlePointsOnly(intrinsics->GetDistortionModelType(), + EuclideanBundlePointsOnly(intrinsics, zero_weight_markers, all_cameras_R_t, - ceres_intrinsics, + intrinsics_block, reconstruction); } } diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc index 5e4e07b3c4c..a95b394ad06 100644 --- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc +++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc @@ -131,6 +131,8 @@ void CameraIntrinsics::ResetLookupGrids() { undistort_.Reset(); } +// Polynomial model. + PolynomialCameraIntrinsics::PolynomialCameraIntrinsics() : CameraIntrinsics() { SetRadialDistortion(0.0, 0.0, 0.0); @@ -193,6 +195,8 @@ void PolynomialCameraIntrinsics::InvertIntrinsics( normalized_y); } +// Division model. + DivisionCameraIntrinsics::DivisionCameraIntrinsics() : CameraIntrinsics() { SetDistortion(0.0, 0.0); @@ -241,6 +245,57 @@ void DivisionCameraIntrinsics::InvertIntrinsics(double image_x, normalized_y); } +// Nuke model. + +NukeCameraIntrinsics::NukeCameraIntrinsics() + : CameraIntrinsics() { + SetDistortion(0.0, 0.0); +} + +NukeCameraIntrinsics::NukeCameraIntrinsics( + const NukeCameraIntrinsics &from) + : CameraIntrinsics(from) { + SetDistortion(from.k1(), from.k1()); +} + +void NukeCameraIntrinsics::SetDistortion(double k1, double k2) { + parameters_[OFFSET_K1] = k1; + parameters_[OFFSET_K2] = k2; + ResetLookupGrids(); +} + +void NukeCameraIntrinsics::ApplyIntrinsics(double normalized_x, + double normalized_y, + double *image_x, + double *image_y) const { + ApplyNukeDistortionModel(focal_length_x(), + focal_length_y(), + principal_point_x(), + principal_point_y(), + image_width(), image_height(), + k1(), k2(), + normalized_x, + normalized_y, + image_x, + image_y); +} + +void NukeCameraIntrinsics::InvertIntrinsics(double image_x, + double image_y, + double *normalized_x, + double *normalized_y) const { + InvertNukeDistortionModel(focal_length_x(), + focal_length_y(), + principal_point_x(), + principal_point_y(), + image_width(), image_height(), + k1(), k2(), + image_x, + image_y, + normalized_x, + normalized_y); +} + std::ostream& operator <<(std::ostream &os, const CameraIntrinsics &intrinsics) { if (intrinsics.focal_length_x() == intrinsics.focal_length_x()) { @@ -281,6 +336,14 @@ std::ostream& operator <<(std::ostream &os, PRINT_NONZERO_COEFFICIENT(division_intrinsics, k2); break; } + case DISTORTION_MODEL_NUKE: + { + const NukeCameraIntrinsics *nuke_intrinsics = + static_cast<const NukeCameraIntrinsics *>(&intrinsics); + PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k1); + PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k2); + break; + } default: LOG(FATAL) << "Unknown distortion model."; } diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h index 6a3ade81089..782fd56c54c 100644 --- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h +++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h @@ -276,7 +276,7 @@ class CameraIntrinsics { class PolynomialCameraIntrinsics : public CameraIntrinsics { public: // This constants defines an offset of corresponding coefficients - // in the arameters_ array. + // in the parameters_ array. enum { OFFSET_K1, OFFSET_K2, @@ -342,7 +342,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics { class DivisionCameraIntrinsics : public CameraIntrinsics { public: // This constants defines an offset of corresponding coefficients - // in the arameters_ array. + // in the parameters_ array. enum { OFFSET_K1, OFFSET_K2, @@ -393,6 +393,60 @@ class DivisionCameraIntrinsics : public CameraIntrinsics { double parameters_[NUM_PARAMETERS]; }; +class NukeCameraIntrinsics : public CameraIntrinsics { + public: + // This constants defines an offset of corresponding coefficients + // in the parameters_ array. + enum { + OFFSET_K1, + OFFSET_K2, + + // This defines the size of array which we need to have in order + // to store all the coefficients. + NUM_PARAMETERS, + }; + + NukeCameraIntrinsics(); + NukeCameraIntrinsics(const NukeCameraIntrinsics &from); + + DistortionModelType GetDistortionModelType() const { + return DISTORTION_MODEL_NUKE; + } + + int num_distortion_parameters() const { return NUM_PARAMETERS; } + double *distortion_parameters() { return parameters_; }; + const double *distortion_parameters() const { return parameters_; }; + + double k1() const { return parameters_[OFFSET_K1]; } + double k2() const { return parameters_[OFFSET_K2]; } + + // Set radial distortion coeffcients. + void SetDistortion(double k1, double k2); + + // Apply camera intrinsics to the normalized point to get image coordinates. + // + // This applies the lens distortion to a point which is in normalized + // camera coordinates (i.e. the principal point is at (0, 0)) to get image + // coordinates in pixels. + void ApplyIntrinsics(double normalized_x, + double normalized_y, + double *image_x, + double *image_y) const; + + // Invert camera intrinsics on the image point to get normalized coordinates. + // + // This reverses the effect of lens distortion on a point which is in image + // coordinates to get normalized camera coordinates. + void InvertIntrinsics(double image_x, + double image_y, + double *normalized_x, + double *normalized_y) const; + + private: + // Double-parameter division distortion model. + double parameters_[NUM_PARAMETERS]; +}; + /// A human-readable representation of the camera intrinsic parameters. std::ostream& operator <<(std::ostream &os, const CameraIntrinsics &intrinsics); diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.cc b/intern/libmv/libmv/simple_pipeline/distortion_models.cc index 9b6dca2678a..c069fc6f623 100644 --- a/intern/libmv/libmv/simple_pipeline/distortion_models.cc +++ b/intern/libmv/libmv/simple_pipeline/distortion_models.cc @@ -194,4 +194,96 @@ void InvertDivisionDistortionModel(const double focal_length_x, *normalized_y = normalized(1); } +struct ApplyNukeIntrinsicsCostFunction { + public: + typedef Vec2 FMatrixType; + typedef Vec2 XMatrixType; + + ApplyNukeIntrinsicsCostFunction(const double focal_length_x, + const double focal_length_y, + const double principal_point_x, + const double principal_point_y, + const int image_width, + const int image_height, + const double k1, + const double k2, + const double expected_normalized_x, + const double expected_normalized_y) + : focal_length_x_(focal_length_x), + focal_length_y_(focal_length_y), + principal_point_x_(principal_point_x), + principal_point_y_(principal_point_y), + image_width_(image_width), + image_height_(image_height), + k1_(k1), k2_(k2), + expected_normalized_x_(expected_normalized_x), + expected_normalized_y_(expected_normalized_y) {} + + Vec2 operator()(const Vec2 &image_coordinate) const { + double actual_normalized_x, actual_normalized_y; + + InvertNukeDistortionModel(focal_length_x_, + focal_length_y_, + principal_point_x_, + principal_point_y_, + image_width_, image_height_, + k1_, k2_, + image_coordinate(0), image_coordinate(1), + &actual_normalized_x, &actual_normalized_y); + + Vec2 fx; + fx << (actual_normalized_x - expected_normalized_x_), + (actual_normalized_y - expected_normalized_y_); + return fx; + } + double focal_length_x_; + double focal_length_y_; + double principal_point_x_; + double principal_point_y_; + int image_width_; + int image_height_; + double k1_, k2_; + double expected_normalized_x_, expected_normalized_y_; +}; + +void ApplyNukeDistortionModel(const double focal_length_x, + const double focal_length_y, + const double principal_point_x, + const double principal_point_y, + const int image_width, + const int image_height, + const double k1, + const double k2, + const double normalized_x, + const double normalized_y, + double *image_x, + double *image_y) { + // Compute the initial guess. For a camera with no distortion, this will also + // be the final answer; the LM iteration will terminate immediately. + Vec2 image; + image(0) = normalized_x * focal_length_x + principal_point_x; + image(1) = normalized_y * focal_length_y + principal_point_y; + + // TODO(sergey): Use Ceres minimizer instead. + typedef LevenbergMarquardt<ApplyNukeIntrinsicsCostFunction> Solver; + + ApplyNukeIntrinsicsCostFunction intrinsics_cost(focal_length_x, + focal_length_y, + principal_point_x, + principal_point_y, + image_width, + image_height, + k1, k2, + normalized_x, normalized_y); + Solver::SolverParameters params; + Solver solver(intrinsics_cost); + + /*Solver::Results results =*/ solver.minimize(params, &image); + + // TODO(keir): Better error handling. + + *image_x = image(0); + *image_y = image(1); +} + } // namespace libmv diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.h b/intern/libmv/libmv/simple_pipeline/distortion_models.h index 4f8e2295a0e..6ba351d729d 100644 --- a/intern/libmv/libmv/simple_pipeline/distortion_models.h +++ b/intern/libmv/libmv/simple_pipeline/distortion_models.h @@ -21,11 +21,14 @@ #ifndef LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_ #define LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_ +#include <algorithm> + namespace libmv { enum DistortionModelType { DISTORTION_MODEL_POLYNOMIAL, - DISTORTION_MODEL_DIVISION + DISTORTION_MODEL_DIVISION, + DISTORTION_MODEL_NUKE, }; // Invert camera intrinsics on the image point to get normalized coordinates. @@ -126,6 +129,79 @@ inline void ApplyDivisionDistortionModel(const T &focal_length_x, *image_y = focal_length_y * yd + principal_point_y; } +// Invert camera intrinsics on the image point to get normalized coordinates. +// This inverts the radial lens distortion to a point which is in image pixel +// coordinates to get normalized coordinates. +// +// Uses Nuke distortion model. +template <typename T> +void InvertNukeDistortionModel(const T &focal_length_x, + const T &focal_length_y, + const T &principal_point_x, + const T &principal_point_y, + const int image_width, + const int image_height, + const T &k1, + const T &k2, + const T &image_x, + const T &image_y, + T *normalized_x, + T *normalized_y) { + // According to the documentation: + // + // xu = xd / (1 + k0 * rd^2 + k1 * rd^4) + // yu = yd / (1 + k0 * rd^2 + k1 * rd^4) + // + // Legend: + // (xd, yd) are the distorted cartesian coordinates, + // (rd, phid) are the distorted polar coordinates, + // (xu, yu) are the undistorted cartesian coordinates, + // (ru, phiu) are the undistorted polar coordinates, + // the k-values are the distortion coefficients. + // + // The coordinate systems are relative to the distortion centre. + + const int max_image_size = std::max(image_width, image_height); + const double max_half_image_size = max_image_size * 0.5; + + if (max_half_image_size == 0.0) { + *normalized_x = image_x * max_half_image_size / focal_length_x; + *normalized_y = image_y * max_half_image_size / focal_length_y; + return; + } + + const T xd = (image_x - principal_point_x) / max_half_image_size; + const T yd = (image_y - principal_point_y) / max_half_image_size; + + T rd2 = xd*xd + yd*yd; + T rd4 = rd2 * rd2; + T r_coeff = T(1) / (T(1) + k1*rd2 + k2*rd4); + T xu = xd * r_coeff; + T yu = yd * r_coeff; + + *normalized_x = xu * max_half_image_size / focal_length_x; + *normalized_y = yu * max_half_image_size / focal_length_y; +} + +// Apply camera intrinsics to the normalized point to get image coordinates. +// This applies the radial lens distortion to a point which is in normalized +// camera coordinates (i.e. the principal point is at (0, 0)) to get image +// coordinates in pixels. Templated for use with autodifferentiation. +// +// Uses Nuke distortion model. +void ApplyNukeDistortionModel(const double focal_length_x, + const double focal_length_y, + const double principal_point_x, + const double principal_point_y, + const int image_width, + const int image_height, + const double k1, + const double k2, + const double normalized_x, + const double normalized_y, + double *image_x, + double *image_y); + } // namespace libmv #endif // LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_ diff --git a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h index 744436246b0..32cd4285190 100644 --- a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h +++ b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h @@ -33,7 +33,7 @@ class ProjectiveReconstruction; Initialize the \link EuclideanReconstruction reconstruction \endlink using two frames. - \a markers should contain all \l Marker markers \endlink belonging to + \a markers should contain all \link Marker markers \endlink belonging to tracks visible in both frames. The pose estimation of the camera for these frames will be inserted into \a *reconstruction. @@ -54,7 +54,7 @@ bool EuclideanReconstructTwoFrames(const vector<Marker> &markers, Initialize the \link ProjectiveReconstruction reconstruction \endlink using two frames. - \a markers should contain all \l Marker markers \endlink belonging to + \a markers should contain all \link Marker markers \endlink belonging to tracks visible in both frames. An estimate of the projection matrices for the two frames will get added to the reconstruction. diff --git a/intern/libmv/libmv/simple_pipeline/intersect.h b/intern/libmv/libmv/simple_pipeline/intersect.h index 3a0ffa7418b..15d6f998557 100644 --- a/intern/libmv/libmv/simple_pipeline/intersect.h +++ b/intern/libmv/libmv/simple_pipeline/intersect.h @@ -35,10 +35,10 @@ namespace libmv { the frames for which there is a marker for that track must have a corresponding reconstructed camera in \a *reconstruction. - \a markers should contain all \l Marker markers \endlink belonging to + \a markers should contain all \link Marker markers \endlink belonging to tracks visible in all frames. \a reconstruction should contain the cameras for all frames. - The new \l Point points \endlink will be inserted in \a reconstruction. + The new \link Point points \endlink will be inserted in \a reconstruction. \note This assumes a calibrated reconstruction, e.g. the markers are already corrected for camera intrinsics and radial distortion. @@ -57,10 +57,10 @@ bool EuclideanIntersect(const vector<Marker> &markers, track. Each of the frames for which there is a marker for that track must have a corresponding reconstructed camera in \a *reconstruction. - \a markers should contain all \l Marker markers \endlink belonging to + \a markers should contain all \link Marker markers \endlink belonging to tracks visible in all frames. \a reconstruction should contain the cameras for all frames. - The new \l Point points \endlink will be inserted in \a reconstruction. + The new \link Point points \endlink will be inserted in \a reconstruction. \note This assumes that radial distortion is already corrected for, but does not assume that e.g. focal length and principal point are diff --git a/intern/libmv/libmv/simple_pipeline/reconstruction.h b/intern/libmv/libmv/simple_pipeline/reconstruction.h index 947a0636476..79c693c5e6d 100644 --- a/intern/libmv/libmv/simple_pipeline/reconstruction.h +++ b/intern/libmv/libmv/simple_pipeline/reconstruction.h @@ -29,7 +29,7 @@ namespace libmv { /*! A EuclideanCamera is the location and rotation of the camera viewing \a image. - \a image identify which image from \l Tracks this camera represents. + \a image identify which image from \link Tracks this camera represents. \a R is a 3x3 matrix representing the rotation of the camera. \a t is a translation vector representing its positions. @@ -47,7 +47,7 @@ struct EuclideanCamera { /*! A Point is the 3D location of a track. - \a track identify which track from \l Tracks this point corresponds to. + \a track identify which track from \link Tracks this point corresponds to. \a X represents the 3D position of the track. \sa Reconstruction @@ -89,7 +89,7 @@ class EuclideanReconstruction { \a image is the key used to retrieve the cameras with the other methods in this class. - \note You should use the same \a image identifier as in \l Tracks. + \note You should use the same \a image identifier as in \link Tracks. */ void InsertCamera(int image, const Mat3 &R, const Vec3 &t); @@ -101,7 +101,7 @@ class EuclideanReconstruction { \a track is the key used to retrieve the points with the other methods in this class. - \note You should use the same \a track identifier as in \l Tracks. + \note You should use the same \a track identifier as in \link Tracks. */ void InsertPoint(int track, const Vec3 &X); @@ -127,7 +127,7 @@ class EuclideanReconstruction { /*! A ProjectiveCamera is the projection matrix for the camera of \a image. - \a image identify which image from \l Tracks this camera represents. + \a image identify which image from \link Tracks this camera represents. \a P is the 3x4 projection matrix. \sa ProjectiveReconstruction @@ -143,7 +143,7 @@ struct ProjectiveCamera { /*! A Point is the 3D location of a track. - \a track identifies which track from \l Tracks this point corresponds to. + \a track identifies which track from \link Tracks this point corresponds to. \a X is the homogeneous 3D position of the track. \sa Reconstruction @@ -177,7 +177,7 @@ class ProjectiveReconstruction { \a image is the key used to retrieve the cameras with the other methods in this class. - \note You should use the same \a image identifier as in \l Tracks. + \note You should use the same \a image identifier as in \link Tracks. */ void InsertCamera(int image, const Mat34 &P); @@ -189,7 +189,7 @@ class ProjectiveReconstruction { \a track is the key used to retrieve the points with the other methods in this class. - \note You should use the same \a track identifier as in \l Tracks. + \note You should use the same \a track identifier as in \link Tracks. */ void InsertPoint(int track, const Vec4 &X); diff --git a/intern/libmv/libmv/simple_pipeline/resect.h b/intern/libmv/libmv/simple_pipeline/resect.h index 7ca3237437e..f13d2e2d425 100644 --- a/intern/libmv/libmv/simple_pipeline/resect.h +++ b/intern/libmv/libmv/simple_pipeline/resect.h @@ -35,7 +35,7 @@ namespace libmv { reconstruction object, and solves for the pose and orientation of the camera for that frame. - \a markers should contain \l Marker markers \endlink belonging to tracks + \a markers should contain \link Marker markers \endlink belonging to tracks visible in the one frame to be resectioned. Each of the tracks associated with the markers must have a corresponding reconstructed 3D position in the \a *reconstruction object. @@ -62,7 +62,7 @@ bool EuclideanResect(const vector<Marker> &markers, frame in the reconstruction object, and solves for the projective matrix of the camera for that frame. - \a markers should contain \l Marker markers \endlink belonging to tracks + \a markers should contain \link Marker markers \endlink belonging to tracks visible in the one frame to be resectioned. Each of the tracks associated with the markers must have a corresponding reconstructed homogeneous 3D position in the \a *reconstruction object. diff --git a/intern/libmv/libmv/simple_pipeline/tracks.h b/intern/libmv/libmv/simple_pipeline/tracks.h index a54a43659b7..752d2790a1c 100644 --- a/intern/libmv/libmv/simple_pipeline/tracks.h +++ b/intern/libmv/libmv/simple_pipeline/tracks.h @@ -36,7 +36,7 @@ namespace libmv { \a weight is used by bundle adjustment and weight means how much the track affects on a final solution. - \note Markers are typically aggregated with the help of the \l Tracks class. + \note Markers are typically aggregated with the help of the \link Tracks class. \sa Tracks */ @@ -56,7 +56,7 @@ struct Marker { images, which must get created before any 3D reconstruction can take place. The container has several fast lookups for queries typically needed for - structure from motion algorithms, such as \l MarkersForTracksInBothImages(). + structure from motion algorithms, such as \link MarkersForTracksInBothImages(). \sa Marker */ @@ -81,7 +81,7 @@ class Tracks { \a weight is used by bundle adjustment and weight means how much the track affects on a final solution. - \note To get an identifier for a new track, use \l MaxTrack() + 1. + \note To get an identifier for a new track, use \link MaxTrack() + 1. */ // TODO(sergey): Consider using InsetWeightedMarker istead of using // stupid default value? diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index 35d4629d195..6671fbc0d7d 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -48,7 +48,16 @@ #include "MEM_guardedalloc.h" -std::atomic<int> MANTA::solverID(0); +using std::cerr; +using std::cout; +using std::endl; +using std::ifstream; +using std::istringstream; +using std::ofstream; +using std::ostringstream; +using std::to_string; + +atomic<int> MANTA::solverID(0); int MANTA::with_debug(0); /* Number of particles that the cache reads at once (with zlib). */ @@ -61,29 +70,30 @@ int MANTA::with_debug(0); MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) { if (with_debug) - std::cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " - << res[2] << ")" << std::endl; - - mmd->domain->fluid = this; - - mUsingLiquid = (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID); - mUsingSmoke = (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS); - mUsingNoise = (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke; - mUsingFractions = (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid; - mUsingMesh = (mmd->domain->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid; - mUsingMVel = (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid; - mUsingGuiding = (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE); - mUsingDrops = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid; - mUsingBubbles = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid; - mUsingFloats = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid; - mUsingTracers = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid; - - mUsingHeat = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke; - mUsingFire = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke; - mUsingColors = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke; - mUsingObstacle = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE); - mUsingInvel = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL); - mUsingOutflow = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW); + cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " << res[2] + << ")" << endl; + + FluidDomainSettings *mds = mmd->domain; + mds->fluid = this; + + mUsingLiquid = (mds->type == FLUID_DOMAIN_TYPE_LIQUID); + mUsingSmoke = (mds->type == FLUID_DOMAIN_TYPE_GAS); + mUsingNoise = (mds->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke; + mUsingFractions = (mds->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid; + mUsingMesh = (mds->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid; + mUsingMVel = (mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid; + mUsingGuiding = (mds->flags & FLUID_DOMAIN_USE_GUIDE); + mUsingDrops = (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid; + mUsingBubbles = (mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid; + mUsingFloats = (mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid; + mUsingTracers = (mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid; + + mUsingHeat = (mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke; + mUsingFire = (mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke; + mUsingColors = (mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke; + mUsingObstacle = (mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE); + mUsingInvel = (mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL); + mUsingOutflow = (mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW); // Simulation constants mTempAmb = 0; // TODO: Maybe use this later for buoyancy calculation @@ -91,10 +101,8 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) mResY = res[1]; mResZ = res[2]; mMaxRes = MAX3(mResX, mResY, mResZ); - mConstantScaling = 64.0f / mMaxRes; - mConstantScaling = (mConstantScaling < 1.0f) ? 1.0f : mConstantScaling; mTotalCells = mResX * mResY * mResZ; - mResGuiding = mmd->domain->res; + mResGuiding = mds->res; // Smoke low res grids mDensity = nullptr; @@ -184,86 +192,89 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) // Setup Mantaflow in Python initializeMantaflow(); + // Initializa RNA map with values that Python will need + initializeRNAMap(mmd); + // Initialize Mantaflow variables in Python // Liquid if (mUsingLiquid) { - initDomain(mmd); - initLiquid(mmd); + initDomain(); + initLiquid(); if (mUsingObstacle) - initObstacle(mmd); + initObstacle(); if (mUsingInvel) - initInVelocity(mmd); + initInVelocity(); if (mUsingOutflow) - initOutflow(mmd); + initOutflow(); if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) { - mUpresParticle = mmd->domain->particle_scale; + mUpresParticle = mds->particle_scale; mResXParticle = mUpresParticle * mResX; mResYParticle = mUpresParticle * mResY; mResZParticle = mUpresParticle * mResZ; mTotalCellsParticles = mResXParticle * mResYParticle * mResZParticle; - initSndParts(mmd); - initLiquidSndParts(mmd); + initSndParts(); + initLiquidSndParts(); } if (mUsingMesh) { - mUpresMesh = mmd->domain->mesh_scale; + mUpresMesh = mds->mesh_scale; mResXMesh = mUpresMesh * mResX; mResYMesh = mUpresMesh * mResY; mResZMesh = mUpresMesh * mResZ; mTotalCellsMesh = mResXMesh * mResYMesh * mResZMesh; // Initialize Mantaflow variables in Python - initMesh(mmd); - initLiquidMesh(mmd); + initMesh(); + initLiquidMesh(); } if (mUsingGuiding) { - mResGuiding = (mmd->domain->guide_parent) ? mmd->domain->guide_res : mmd->domain->res; - initGuiding(mmd); + mResGuiding = (mds->guide_parent) ? mds->guide_res : mds->res; + initGuiding(); } if (mUsingFractions) { - initFractions(mmd); + initFractions(); } } // Smoke if (mUsingSmoke) { - initDomain(mmd); - initSmoke(mmd); + initDomain(); + initSmoke(); if (mUsingHeat) - initHeat(mmd); + initHeat(); if (mUsingFire) - initFire(mmd); + initFire(); if (mUsingColors) - initColors(mmd); + initColors(); if (mUsingObstacle) - initObstacle(mmd); + initObstacle(); if (mUsingInvel) - initInVelocity(mmd); + initInVelocity(); if (mUsingOutflow) - initOutflow(mmd); + initOutflow(); if (mUsingGuiding) { - mResGuiding = (mmd->domain->guide_parent) ? mmd->domain->guide_res : mmd->domain->res; - initGuiding(mmd); + mResGuiding = (mds->guide_parent) ? mds->guide_res : mds->res; + initGuiding(); } if (mUsingNoise) { - int amplify = mmd->domain->noise_scale; + int amplify = mds->noise_scale; mResXNoise = amplify * mResX; mResYNoise = amplify * mResY; mResZNoise = amplify * mResZ; mTotalCellsHigh = mResXNoise * mResYNoise * mResZNoise; // Initialize Mantaflow variables in Python - initNoise(mmd); - initSmokeNoise(mmd); + initNoise(); + initSmokeNoise(); if (mUsingFire) - initFireHigh(mmd); + initFireHigh(); if (mUsingColors) - initColorsHigh(mmd); + initColorsHigh(); } } updatePointers(); @@ -272,32 +283,32 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) void MANTA::initDomain(FluidModifierData *mmd) { // Vector will hold all python commands that are to be executed - std::vector<std::string> pythonCommands; + vector<string> pythonCommands; // Set manta debug level first pythonCommands.push_back(manta_import + manta_debuglevel); - std::ostringstream ss; + ostringstream ss; ss << "set_manta_debuglevel(" << with_debug << ")"; pythonCommands.push_back(ss.str()); // Now init basic fluid domain - std::string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper + - fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise + - fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding + - fluid_file_import + fluid_file_export + fluid_save_data + - fluid_load_data + fluid_pre_step + fluid_post_step + - fluid_adapt_time_step + fluid_time_stepping; - std::string finalString = parseScript(tmpString, mmd); + string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper + + fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise + + fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding + + fluid_file_import + fluid_file_export + fluid_save_data + fluid_load_data + + fluid_pre_step + fluid_post_step + fluid_adapt_time_step + + fluid_time_stepping; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); } void MANTA::initNoise(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_noise + fluid_solver_noise; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_noise + fluid_solver_noise; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -305,10 +316,10 @@ void MANTA::initNoise(FluidModifierData *mmd) void MANTA::initSmoke(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data + - smoke_load_data + smoke_step; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data + + smoke_load_data + smoke_step; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -316,10 +327,10 @@ void MANTA::initSmoke(FluidModifierData *mmd) void MANTA::initSmokeNoise(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_variables_noise + smoke_alloc_noise + smoke_wavelet_noise + - smoke_save_noise + smoke_load_noise + smoke_step_noise; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_variables_noise + smoke_alloc_noise + smoke_wavelet_noise + + smoke_save_noise + smoke_load_noise + smoke_step_noise; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -329,9 +340,9 @@ void MANTA::initSmokeNoise(FluidModifierData *mmd) void MANTA::initHeat(FluidModifierData *mmd) { if (!mHeat) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_heat + smoke_with_heat; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_heat + smoke_with_heat; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -342,9 +353,9 @@ void MANTA::initHeat(FluidModifierData *mmd) void MANTA::initFire(FluidModifierData *mmd) { if (!mFuel) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_fire + smoke_with_fire; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_fire + smoke_with_fire; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -355,9 +366,9 @@ void MANTA::initFire(FluidModifierData *mmd) void MANTA::initFireHigh(FluidModifierData *mmd) { if (!mFuelHigh) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_fire_noise + smoke_with_fire; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_fire_noise + smoke_with_fire; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -368,9 +379,9 @@ void MANTA::initFireHigh(FluidModifierData *mmd) void MANTA::initColors(FluidModifierData *mmd) { if (!mColorR) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_colors + smoke_init_colors + smoke_with_colors; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_colors + smoke_init_colors + smoke_with_colors; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -381,9 +392,9 @@ void MANTA::initColors(FluidModifierData *mmd) void MANTA::initColorsHigh(FluidModifierData *mmd) { if (!mColorRHigh) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_colors_noise + smoke_init_colors_noise + smoke_with_colors; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_colors_noise + smoke_init_colors_noise + smoke_with_colors; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -394,10 +405,10 @@ void MANTA::initColorsHigh(FluidModifierData *mmd) void MANTA::initLiquid(FluidModifierData *mmd) { if (!mPhiIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = liquid_variables + liquid_alloc + liquid_init_phi + liquid_save_data + - liquid_load_data + liquid_adaptive_step + liquid_step; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = liquid_variables + liquid_alloc + liquid_init_phi + liquid_save_data + + liquid_load_data + liquid_adaptive_step + liquid_step; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -407,9 +418,9 @@ void MANTA::initLiquid(FluidModifierData *mmd) void MANTA::initMesh(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -418,9 +429,9 @@ void MANTA::initMesh(FluidModifierData *mmd) void MANTA::initLiquidMesh(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -430,9 +441,9 @@ void MANTA::initLiquidMesh(FluidModifierData *mmd) void MANTA::initObstacle(FluidModifierData *mmd) { if (!mPhiObsIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_obstacle + fluid_with_obstacle; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_obstacle + fluid_with_obstacle; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -443,10 +454,10 @@ void MANTA::initObstacle(FluidModifierData *mmd) void MANTA::initGuiding(FluidModifierData *mmd) { if (!mPhiGuideIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_guiding + fluid_solver_guiding + fluid_alloc_guiding + - fluid_save_guiding + fluid_load_vel + fluid_load_guiding; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_guiding + fluid_solver_guiding + fluid_alloc_guiding + + fluid_save_guiding + fluid_load_vel + fluid_load_guiding; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -456,9 +467,9 @@ void MANTA::initGuiding(FluidModifierData *mmd) void MANTA::initFractions(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_fractions + fluid_with_fractions; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_fractions + fluid_with_fractions; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -468,9 +479,9 @@ void MANTA::initFractions(FluidModifierData *mmd) void MANTA::initInVelocity(FluidModifierData *mmd) { if (!mInVelocityX) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_invel + fluid_with_invel; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_invel + fluid_with_invel; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -481,9 +492,9 @@ void MANTA::initInVelocity(FluidModifierData *mmd) void MANTA::initOutflow(FluidModifierData *mmd) { if (!mPhiOutIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_outflow + fluid_with_outflow; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_outflow + fluid_with_outflow; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -493,9 +504,9 @@ void MANTA::initOutflow(FluidModifierData *mmd) void MANTA::initSndParts(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_particles + fluid_solver_particles; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_particles + fluid_solver_particles; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -504,11 +515,11 @@ void MANTA::initSndParts(FluidModifierData *mmd) void MANTA::initLiquidSndParts(FluidModifierData *mmd) { if (!mSndParticleData) { - std::vector<std::string> pythonCommands; - std::string tmpString = liquid_alloc_particles + liquid_variables_particles + - liquid_step_particles + fluid_with_sndparts + liquid_load_particles + - liquid_save_particles; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = liquid_alloc_particles + liquid_variables_particles + + liquid_step_particles + fluid_with_sndparts + liquid_load_particles + + liquid_save_particles; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -518,19 +529,22 @@ void MANTA::initLiquidSndParts(FluidModifierData *mmd) MANTA::~MANTA() { if (with_debug) - std::cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " - << mResZ << ")" << std::endl; + cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " << mResZ + << ")" << endl; // Destruction string for Python - std::string tmpString = ""; - std::vector<std::string> pythonCommands; + string tmpString = ""; + vector<string> pythonCommands; bool result = false; tmpString += manta_import; tmpString += fluid_delete_all; + // Initializa RNA map with values that Python will need + initializeRNAMap(); + // Leave out mmd argument in parseScript since only looking up IDs - std::string finalString = parseScript(tmpString); + string finalString = parseScript(tmpString); pythonCommands.push_back(finalString); result = runPythonString(pythonCommands); @@ -551,7 +565,7 @@ MANTA::~MANTA() */ static PyObject *manta_main_module = nullptr; -bool MANTA::runPythonString(std::vector<std::string> commands) +bool MANTA::runPythonString(vector<string> commands) { bool success = true; PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -560,7 +574,7 @@ bool MANTA::runPythonString(std::vector<std::string> commands) manta_main_module = PyImport_ImportModule("__main__"); } - for (std::vector<std::string>::iterator it = commands.begin(); it != commands.end(); ++it) { + for (vector<std::string>::iterator it = commands.begin(); it != commands.end(); ++it) { std::string command = *it; PyObject *globals_dict = PyModule_GetDict(manta_main_module); @@ -586,10 +600,10 @@ bool MANTA::runPythonString(std::vector<std::string> commands) void MANTA::initializeMantaflow() { if (with_debug) - std::cout << "Fluid: Initializing Mantaflow framework" << std::endl; + cout << "Fluid: Initializing Mantaflow framework" << endl; - std::string filename = "manta_scene_" + std::to_string(mCurrentID) + ".py"; - std::vector<std::string> fill = std::vector<std::string>(); + string filename = "manta_scene_" + to_string(mCurrentID) + ".py"; + vector<string> fill = vector<string>(); // Initialize extension classes and wrappers srand(0); @@ -601,17 +615,17 @@ void MANTA::initializeMantaflow() void MANTA::terminateMantaflow() { if (with_debug) - std::cout << "Fluid: Releasing Mantaflow framework" << std::endl; + cout << "Fluid: Releasing Mantaflow framework" << endl; PyGILState_STATE gilstate = PyGILState_Ensure(); Pb::finalize(); // Namespace from Mantaflow (registry) PyGILState_Release(gilstate); } -static std::string getCacheFileEnding(char cache_format) +static string getCacheFileEnding(char cache_format) { if (MANTA::with_debug) - std::cout << "MANTA::getCacheFileEnding()" << std::endl; + cout << "MANTA::getCacheFileEnding()" << endl; switch (cache_format) { case FLUID_DOMAIN_FILE_UNI: @@ -625,409 +639,237 @@ static std::string getCacheFileEnding(char cache_format) case FLUID_DOMAIN_FILE_OBJECT: return FLUID_DOMAIN_EXTENSION_OBJ; default: - std::cerr << "Fluid Error -- Could not find file extension. Using default file extension." - << std::endl; + cerr << "Fluid Error -- Could not find file extension. Using default file extension." + << endl; return FLUID_DOMAIN_EXTENSION_UNI; } } -std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *mmd) +static string getBooleanString(int value) { - std::ostringstream ss; - bool is2D = false; - int tmpVar; - float tmpFloat; + return (value) ? "True" : "False"; +} - if (varName == "ID") { - ss << mCurrentID; - return ss.str(); - } +void MANTA::initializeRNAMap(FluidModifierData *mmd) +{ + if (with_debug) + cout << "MANTA::initializeRNAMap()" << endl; + + mRNAMap["ID"] = to_string(mCurrentID); if (!mmd) { - std::cerr << "Fluid Error -- Invalid modifier data." << std::endl; - ss << "ERROR - INVALID MODIFIER DATA"; - return ss.str(); - } - - is2D = (mmd->domain->solver_res == 2); - - if (varName == "USING_SMOKE") - ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_GAS) ? "True" : "False"); - else if (varName == "USING_LIQUID") - ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) ? "True" : "False"); - else if (varName == "USING_COLORS") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS ? "True" : "False"); - else if (varName == "USING_HEAT") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT ? "True" : "False"); - else if (varName == "USING_FIRE") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE ? "True" : "False"); - else if (varName == "USING_NOISE") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE ? "True" : "False"); - else if (varName == "USING_OBSTACLE") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE ? "True" : "False"); - else if (varName == "USING_GUIDING") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE ? "True" : "False"); - else if (varName == "USING_INVEL") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL ? "True" : "False"); - else if (varName == "USING_OUTFLOW") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW ? "True" : "False"); - else if (varName == "USING_LOG_DISSOLVE") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG ? "True" : "False"); - else if (varName == "USING_DISSOLVE") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE ? "True" : "False"); - else if (varName == "SOLVER_DIM") - ss << mmd->domain->solver_res; - else if (varName == "DO_OPEN") { - tmpVar = (FLUID_DOMAIN_BORDER_BACK | FLUID_DOMAIN_BORDER_FRONT | FLUID_DOMAIN_BORDER_LEFT | - FLUID_DOMAIN_BORDER_RIGHT | FLUID_DOMAIN_BORDER_BOTTOM | FLUID_DOMAIN_BORDER_TOP); - ss << (((mmd->domain->border_collisions & tmpVar) == tmpVar) ? "False" : "True"); - } - else if (varName == "BOUND_CONDITIONS") { - if (mmd->domain->solver_res == 2) { - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) - ss << "x"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) - ss << "X"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) - ss << "y"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) - ss << "Y"; - } - if (mmd->domain->solver_res == 3) { - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) - ss << "x"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) - ss << "X"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) - ss << "y"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) - ss << "Y"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0) - ss << "z"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) - ss << "Z"; - } - } - else if (varName == "BOUNDARY_WIDTH") - ss << mmd->domain->boundary_width; - else if (varName == "RES") - ss << mMaxRes; - else if (varName == "RESX") - ss << mResX; - else if (varName == "RESY") - if (is2D) { - ss << mResZ; - } - else { - ss << mResY; - } - else if (varName == "RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZ; - } - } - else if (varName == "FRAME_LENGTH") - ss << mmd->domain->frame_length; - else if (varName == "CFL") - ss << mmd->domain->cfl_condition; - else if (varName == "DT") - ss << mmd->domain->dt; - else if (varName == "TIMESTEPS_MIN") - ss << mmd->domain->timesteps_minimum; - else if (varName == "TIMESTEPS_MAX") - ss << mmd->domain->timesteps_maximum; - else if (varName == "TIME_TOTAL") - ss << mmd->domain->time_total; - else if (varName == "TIME_PER_FRAME") - ss << mmd->domain->time_per_frame; - else if (varName == "VORTICITY") - ss << mmd->domain->vorticity / mConstantScaling; - else if (varName == "FLAME_VORTICITY") - ss << mmd->domain->flame_vorticity / mConstantScaling; - else if (varName == "NOISE_SCALE") - ss << mmd->domain->noise_scale; - else if (varName == "MESH_SCALE") - ss << mmd->domain->mesh_scale; - else if (varName == "PARTICLE_SCALE") - ss << mmd->domain->particle_scale; - else if (varName == "NOISE_RESX") - ss << mResXNoise; - else if (varName == "NOISE_RESY") { - if (is2D) { - ss << mResZNoise; - } - else { - ss << mResYNoise; - } - } - else if (varName == "NOISE_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZNoise; - } - } - else if (varName == "MESH_RESX") - ss << mResXMesh; - else if (varName == "MESH_RESY") { - if (is2D) { - ss << mResZMesh; - } - else { - ss << mResYMesh; - } - } - else if (varName == "MESH_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZMesh; - } - } - else if (varName == "PARTICLE_RESX") - ss << mResXParticle; - else if (varName == "PARTICLE_RESY") { - if (is2D) { - ss << mResZParticle; - } - else { - ss << mResYParticle; - } - } - else if (varName == "PARTICLE_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZParticle; - } - } - else if (varName == "GUIDING_RESX") - ss << mResGuiding[0]; - else if (varName == "GUIDING_RESY") { - if (is2D) { - ss << mResGuiding[2]; - } - else { - ss << mResGuiding[1]; - } + if (with_debug) + cout << "No modifier data given in RNA map setup - returning early" << endl; + return; } - else if (varName == "GUIDING_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResGuiding[2]; - } + + FluidDomainSettings *mds = mmd->domain; + bool is2D = (mds->solver_res == 2); + + string borderCollisions = ""; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) + borderCollisions += "x"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) + borderCollisions += "X"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) + borderCollisions += "y"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) + borderCollisions += "Y"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0) + borderCollisions += "z"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) + borderCollisions += "Z"; + + string simulationMethod = ""; + if (mds->simulation_method & FLUID_DOMAIN_METHOD_FLIP) + simulationMethod += "'FLIP'"; + else if (mds->simulation_method & FLUID_DOMAIN_METHOD_APIC) + simulationMethod += "'APIC'"; + + string particleTypesStr = ""; + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) + particleTypesStr += "PtypeSpray"; + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) { + if (!particleTypesStr.empty()) + particleTypesStr += "|"; + particleTypesStr += "PtypeBubble"; + } + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) { + if (!particleTypesStr.empty()) + particleTypesStr += "|"; + particleTypesStr += "PtypeFoam"; + } + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) { + if (!particleTypesStr.empty()) + particleTypesStr += "|"; + particleTypesStr += "PtypeTracer"; + } + if (particleTypesStr.empty()) + particleTypesStr = "0"; + + int particleTypes = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE | + FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER); + + string cacheDirectory(mds->cache_directory); + + float viscosity = mds->viscosity_base * pow(10.0f, -mds->viscosity_exponent); + float domainSize = MAX3(mds->global_size[0], mds->global_size[1], mds->global_size[2]); + + mRNAMap["USING_SMOKE"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_GAS); + mRNAMap["USING_LIQUID"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_LIQUID); + mRNAMap["USING_COLORS"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS); + mRNAMap["USING_HEAT"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT); + mRNAMap["USING_FIRE"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE); + mRNAMap["USING_NOISE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_NOISE); + mRNAMap["USING_OBSTACLE"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE); + mRNAMap["USING_GUIDING"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_GUIDE); + mRNAMap["USING_INVEL"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL); + mRNAMap["USING_OUTFLOW"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW); + mRNAMap["USING_LOG_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG); + mRNAMap["USING_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE); + mRNAMap["DO_OPEN"] = getBooleanString(mds->border_collisions == 0); + mRNAMap["CACHE_RESUMABLE"] = getBooleanString(mds->cache_type != FLUID_DOMAIN_CACHE_FINAL); + mRNAMap["USING_ADAPTIVETIME"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME); + mRNAMap["USING_SPEEDVECTORS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS); + mRNAMap["USING_FRACTIONS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_FRACTIONS); + mRNAMap["DELETE_IN_OBSTACLE"] = getBooleanString(mds->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE); + mRNAMap["USING_DIFFUSION"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DIFFUSION); + mRNAMap["USING_MESH"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_MESH); + mRNAMap["USING_IMPROVED_MESH"] = getBooleanString(mds->mesh_generator == + FLUID_DOMAIN_MESH_IMPROVED); + mRNAMap["USING_SNDPARTS"] = getBooleanString(mds->particle_type & particleTypes); + mRNAMap["SNDPARTICLE_BOUNDARY_DELETE"] = getBooleanString(mds->sndparticle_boundary == + SNDPARTICLE_BOUNDARY_DELETE); + mRNAMap["SNDPARTICLE_BOUNDARY_PUSHOUT"] = getBooleanString(mds->sndparticle_boundary == + SNDPARTICLE_BOUNDARY_PUSHOUT); + + mRNAMap["SOLVER_DIM"] = to_string(mds->solver_res); + mRNAMap["BOUND_CONDITIONS"] = borderCollisions; + mRNAMap["BOUNDARY_WIDTH"] = to_string(mds->boundary_width); + mRNAMap["RES"] = to_string(mMaxRes); + mRNAMap["RESX"] = to_string(mResX); + mRNAMap["RESY"] = (is2D) ? to_string(mResZ) : to_string(mResY); + mRNAMap["RESZ"] = (is2D) ? to_string(1) : to_string(mResZ); + mRNAMap["TIME_SCALE"] = to_string(mds->time_scale); + mRNAMap["FRAME_LENGTH"] = to_string(mds->frame_length); + mRNAMap["CFL"] = to_string(mds->cfl_condition); + mRNAMap["DT"] = to_string(mds->dt); + mRNAMap["TIMESTEPS_MIN"] = to_string(mds->timesteps_minimum); + mRNAMap["TIMESTEPS_MAX"] = to_string(mds->timesteps_maximum); + mRNAMap["TIME_TOTAL"] = to_string(mds->time_total); + mRNAMap["TIME_PER_FRAME"] = to_string(mds->time_per_frame); + mRNAMap["VORTICITY"] = to_string(mds->vorticity); + mRNAMap["FLAME_VORTICITY"] = to_string(mds->flame_vorticity); + mRNAMap["NOISE_SCALE"] = to_string(mds->noise_scale); + mRNAMap["MESH_SCALE"] = to_string(mds->mesh_scale); + mRNAMap["PARTICLE_SCALE"] = to_string(mds->particle_scale); + mRNAMap["NOISE_RESX"] = to_string(mResXNoise); + mRNAMap["NOISE_RESY"] = (is2D) ? to_string(mResZNoise) : to_string(mResYNoise); + mRNAMap["NOISE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZNoise); + mRNAMap["MESH_RESX"] = to_string(mResXMesh); + mRNAMap["MESH_RESY"] = (is2D) ? to_string(mResZMesh) : to_string(mResYMesh); + mRNAMap["MESH_RESZ"] = (is2D) ? to_string(1) : to_string(mResZMesh); + mRNAMap["PARTICLE_RESX"] = to_string(mResXParticle); + mRNAMap["PARTICLE_RESY"] = (is2D) ? to_string(mResZParticle) : to_string(mResYParticle); + mRNAMap["PARTICLE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZParticle); + mRNAMap["GUIDING_RESX"] = to_string(mResGuiding[0]); + mRNAMap["GUIDING_RESY"] = (is2D) ? to_string(mResGuiding[2]) : to_string(mResGuiding[1]); + mRNAMap["GUIDING_RESZ"] = (is2D) ? to_string(1) : to_string(mResGuiding[2]); + mRNAMap["MIN_RESX"] = to_string(mds->res_min[0]); + mRNAMap["MIN_RESY"] = to_string(mds->res_min[1]); + mRNAMap["MIN_RESZ"] = to_string(mds->res_min[2]); + mRNAMap["BASE_RESX"] = to_string(mds->base_res[0]); + mRNAMap["BASE_RESY"] = to_string(mds->base_res[1]); + mRNAMap["BASE_RESZ"] = to_string(mds->base_res[2]); + mRNAMap["WLT_STR"] = to_string(mds->noise_strength); + mRNAMap["NOISE_POSSCALE"] = to_string(mds->noise_pos_scale); + mRNAMap["NOISE_TIMEANIM"] = to_string(mds->noise_time_anim); + mRNAMap["COLOR_R"] = to_string(mds->active_color[0]); + mRNAMap["COLOR_G"] = to_string(mds->active_color[1]); + mRNAMap["COLOR_B"] = to_string(mds->active_color[2]); + mRNAMap["BUOYANCY_ALPHA"] = to_string(mds->alpha); + mRNAMap["BUOYANCY_BETA"] = to_string(mds->beta); + mRNAMap["DISSOLVE_SPEED"] = to_string(mds->diss_speed); + mRNAMap["BURNING_RATE"] = to_string(mds->burning_rate); + mRNAMap["FLAME_SMOKE"] = to_string(mds->flame_smoke); + mRNAMap["IGNITION_TEMP"] = to_string(mds->flame_ignition); + mRNAMap["MAX_TEMP"] = to_string(mds->flame_max_temp); + mRNAMap["FLAME_SMOKE_COLOR_X"] = to_string(mds->flame_smoke_color[0]); + mRNAMap["FLAME_SMOKE_COLOR_Y"] = to_string(mds->flame_smoke_color[1]); + mRNAMap["FLAME_SMOKE_COLOR_Z"] = to_string(mds->flame_smoke_color[2]); + mRNAMap["CURRENT_FRAME"] = to_string(mmd->time); + mRNAMap["START_FRAME"] = to_string(mds->cache_frame_start); + mRNAMap["END_FRAME"] = to_string(mds->cache_frame_end); + mRNAMap["CACHE_DATA_FORMAT"] = to_string(mds->cache_data_format); + mRNAMap["CACHE_MESH_FORMAT"] = to_string(mds->cache_mesh_format); + mRNAMap["CACHE_NOISE_FORMAT"] = to_string(mds->cache_noise_format); + mRNAMap["CACHE_PARTICLE_FORMAT"] = to_string(mds->cache_particle_format); + mRNAMap["SIMULATION_METHOD"] = simulationMethod; + mRNAMap["FLIP_RATIO"] = to_string(mds->flip_ratio); + mRNAMap["PARTICLE_RANDOMNESS"] = to_string(mds->particle_randomness); + mRNAMap["PARTICLE_NUMBER"] = to_string(mds->particle_number); + mRNAMap["PARTICLE_MINIMUM"] = to_string(mds->particle_minimum); + mRNAMap["PARTICLE_MAXIMUM"] = to_string(mds->particle_maximum); + mRNAMap["PARTICLE_RADIUS"] = to_string(mds->particle_radius); + mRNAMap["FRACTIONS_THRESHOLD"] = to_string(mds->fractions_threshold); + mRNAMap["MESH_CONCAVE_UPPER"] = to_string(mds->mesh_concave_upper); + mRNAMap["MESH_CONCAVE_LOWER"] = to_string(mds->mesh_concave_lower); + mRNAMap["MESH_PARTICLE_RADIUS"] = to_string(mds->mesh_particle_radius); + mRNAMap["MESH_SMOOTHEN_POS"] = to_string(mds->mesh_smoothen_pos); + mRNAMap["MESH_SMOOTHEN_NEG"] = to_string(mds->mesh_smoothen_neg); + mRNAMap["PARTICLE_BAND_WIDTH"] = to_string(mds->particle_band_width); + mRNAMap["SNDPARTICLE_TAU_MIN_WC"] = to_string(mds->sndparticle_tau_min_wc); + mRNAMap["SNDPARTICLE_TAU_MAX_WC"] = to_string(mds->sndparticle_tau_max_wc); + mRNAMap["SNDPARTICLE_TAU_MIN_TA"] = to_string(mds->sndparticle_tau_min_ta); + mRNAMap["SNDPARTICLE_TAU_MAX_TA"] = to_string(mds->sndparticle_tau_max_ta); + mRNAMap["SNDPARTICLE_TAU_MIN_K"] = to_string(mds->sndparticle_tau_min_k); + mRNAMap["SNDPARTICLE_TAU_MAX_K"] = to_string(mds->sndparticle_tau_max_k); + mRNAMap["SNDPARTICLE_K_WC"] = to_string(mds->sndparticle_k_wc); + mRNAMap["SNDPARTICLE_K_TA"] = to_string(mds->sndparticle_k_ta); + mRNAMap["SNDPARTICLE_K_B"] = to_string(mds->sndparticle_k_b); + mRNAMap["SNDPARTICLE_K_D"] = to_string(mds->sndparticle_k_d); + mRNAMap["SNDPARTICLE_L_MIN"] = to_string(mds->sndparticle_l_min); + mRNAMap["SNDPARTICLE_L_MAX"] = to_string(mds->sndparticle_l_max); + mRNAMap["SNDPARTICLE_POTENTIAL_RADIUS"] = to_string(mds->sndparticle_potential_radius); + mRNAMap["SNDPARTICLE_UPDATE_RADIUS"] = to_string(mds->sndparticle_update_radius); + mRNAMap["LIQUID_SURFACE_TENSION"] = to_string(mds->surface_tension); + mRNAMap["FLUID_VISCOSITY"] = to_string(viscosity); + mRNAMap["FLUID_DOMAIN_SIZE"] = to_string(domainSize); + mRNAMap["SNDPARTICLE_TYPES"] = particleTypesStr; + mRNAMap["GUIDING_ALPHA"] = to_string(mds->guide_alpha); + mRNAMap["GUIDING_BETA"] = to_string(mds->guide_beta); + mRNAMap["GUIDING_FACTOR"] = to_string(mds->guide_vel_factor); + mRNAMap["GRAVITY_X"] = to_string(mds->gravity[0]); + mRNAMap["GRAVITY_Y"] = to_string(mds->gravity[1]); + mRNAMap["GRAVITY_Z"] = to_string(mds->gravity[2]); + mRNAMap["CACHE_DIR"] = cacheDirectory; +} + +string MANTA::getRealValue(const string &varName) +{ + if (with_debug) + cout << "MANTA::getRealValue()" << endl; + + unordered_map<string, string>::iterator it; + it = mRNAMap.find(varName); + + if (it == mRNAMap.end()) { + cerr << "Fluid Error -- variable " << varName << " not found in RNA map " << it->second + << endl; + return ""; } - else if (varName == "MIN_RESX") - ss << mmd->domain->res_min[0]; - else if (varName == "MIN_RESY") - ss << mmd->domain->res_min[1]; - else if (varName == "MIN_RESZ") - ss << mmd->domain->res_min[2]; - else if (varName == "BASE_RESX") - ss << mmd->domain->base_res[0]; - else if (varName == "BASE_RESY") - ss << mmd->domain->base_res[1]; - else if (varName == "BASE_RESZ") - ss << mmd->domain->base_res[2]; - else if (varName == "WLT_STR") - ss << mmd->domain->noise_strength; - else if (varName == "NOISE_POSSCALE") - ss << mmd->domain->noise_pos_scale; - else if (varName == "NOISE_TIMEANIM") - ss << mmd->domain->noise_time_anim; - else if (varName == "COLOR_R") - ss << mmd->domain->active_color[0]; - else if (varName == "COLOR_G") - ss << mmd->domain->active_color[1]; - else if (varName == "COLOR_B") - ss << mmd->domain->active_color[2]; - else if (varName == "BUOYANCY_ALPHA") - ss << mmd->domain->alpha; - else if (varName == "BUOYANCY_BETA") - ss << mmd->domain->beta; - else if (varName == "DISSOLVE_SPEED") - ss << mmd->domain->diss_speed; - else if (varName == "BURNING_RATE") - ss << mmd->domain->burning_rate; - else if (varName == "FLAME_SMOKE") - ss << mmd->domain->flame_smoke; - else if (varName == "IGNITION_TEMP") - ss << mmd->domain->flame_ignition; - else if (varName == "MAX_TEMP") - ss << mmd->domain->flame_max_temp; - else if (varName == "FLAME_SMOKE_COLOR_X") - ss << mmd->domain->flame_smoke_color[0]; - else if (varName == "FLAME_SMOKE_COLOR_Y") - ss << mmd->domain->flame_smoke_color[1]; - else if (varName == "FLAME_SMOKE_COLOR_Z") - ss << mmd->domain->flame_smoke_color[2]; - else if (varName == "CURRENT_FRAME") - ss << mmd->time; - else if (varName == "START_FRAME") - ss << mmd->domain->cache_frame_start; - else if (varName == "END_FRAME") - ss << mmd->domain->cache_frame_end; - else if (varName == "CACHE_DATA_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_data_format); - else if (varName == "CACHE_MESH_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_mesh_format); - else if (varName == "CACHE_NOISE_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_noise_format); - else if (varName == "CACHE_PARTICLE_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_particle_format); - else if (varName == "SIMULATION_METHOD") { - if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_FLIP) { - ss << "'FLIP'"; - } - else if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_APIC) { - ss << "'APIC'"; - } - else { - ss << "'NONE'"; - } + if (with_debug) { + cout << "Found variable " << varName << " with value " << it->second << endl; } - else if (varName == "FLIP_RATIO") - ss << mmd->domain->flip_ratio; - else if (varName == "PARTICLE_RANDOMNESS") - ss << mmd->domain->particle_randomness; - else if (varName == "PARTICLE_NUMBER") - ss << mmd->domain->particle_number; - else if (varName == "PARTICLE_MINIMUM") - ss << mmd->domain->particle_minimum; - else if (varName == "PARTICLE_MAXIMUM") - ss << mmd->domain->particle_maximum; - else if (varName == "PARTICLE_RADIUS") - ss << mmd->domain->particle_radius; - else if (varName == "FRACTIONS_THRESHOLD") - ss << mmd->domain->fractions_threshold; - else if (varName == "MESH_CONCAVE_UPPER") - ss << mmd->domain->mesh_concave_upper; - else if (varName == "MESH_CONCAVE_LOWER") - ss << mmd->domain->mesh_concave_lower; - else if (varName == "MESH_PARTICLE_RADIUS") - ss << mmd->domain->mesh_particle_radius; - else if (varName == "MESH_SMOOTHEN_POS") - ss << mmd->domain->mesh_smoothen_pos; - else if (varName == "MESH_SMOOTHEN_NEG") - ss << mmd->domain->mesh_smoothen_neg; - else if (varName == "USING_MESH") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_MESH ? "True" : "False"); - else if (varName == "USING_IMPROVED_MESH") - ss << (mmd->domain->mesh_generator == FLUID_DOMAIN_MESH_IMPROVED ? "True" : "False"); - else if (varName == "PARTICLE_BAND_WIDTH") - ss << mmd->domain->particle_band_width; - else if (varName == "SNDPARTICLE_TAU_MIN_WC") - ss << mmd->domain->sndparticle_tau_min_wc; - else if (varName == "SNDPARTICLE_TAU_MAX_WC") - ss << mmd->domain->sndparticle_tau_max_wc; - else if (varName == "SNDPARTICLE_TAU_MIN_TA") - ss << mmd->domain->sndparticle_tau_min_ta; - else if (varName == "SNDPARTICLE_TAU_MAX_TA") - ss << mmd->domain->sndparticle_tau_max_ta; - else if (varName == "SNDPARTICLE_TAU_MIN_K") - ss << mmd->domain->sndparticle_tau_min_k; - else if (varName == "SNDPARTICLE_TAU_MAX_K") - ss << mmd->domain->sndparticle_tau_max_k; - else if (varName == "SNDPARTICLE_K_WC") - ss << mmd->domain->sndparticle_k_wc; - else if (varName == "SNDPARTICLE_K_TA") - ss << mmd->domain->sndparticle_k_ta; - else if (varName == "SNDPARTICLE_K_B") - ss << mmd->domain->sndparticle_k_b; - else if (varName == "SNDPARTICLE_K_D") - ss << mmd->domain->sndparticle_k_d; - else if (varName == "SNDPARTICLE_L_MIN") - ss << mmd->domain->sndparticle_l_min; - else if (varName == "SNDPARTICLE_L_MAX") - ss << mmd->domain->sndparticle_l_max; - else if (varName == "SNDPARTICLE_BOUNDARY_DELETE") - ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_DELETE); - else if (varName == "SNDPARTICLE_BOUNDARY_PUSHOUT") - ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_PUSHOUT); - else if (varName == "SNDPARTICLE_POTENTIAL_RADIUS") - ss << mmd->domain->sndparticle_potential_radius; - else if (varName == "SNDPARTICLE_UPDATE_RADIUS") - ss << mmd->domain->sndparticle_update_radius; - else if (varName == "LIQUID_SURFACE_TENSION") - ss << mmd->domain->surface_tension; - else if (varName == "FLUID_VISCOSITY") - ss << mmd->domain->viscosity_base * pow(10.0f, -mmd->domain->viscosity_exponent); - else if (varName == "FLUID_DOMAIN_SIZE") { - tmpFloat = MAX3( - mmd->domain->global_size[0], mmd->domain->global_size[1], mmd->domain->global_size[2]); - ss << tmpFloat; - } - else if (varName == "SNDPARTICLE_TYPES") { - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) { - ss << "PtypeSpray"; - } - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) { - if (!ss.str().empty()) - ss << "|"; - ss << "PtypeBubble"; - } - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) { - if (!ss.str().empty()) - ss << "|"; - ss << "PtypeFoam"; - } - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) { - if (!ss.str().empty()) - ss << "|"; - ss << "PtypeTracer"; - } - if (ss.str().empty()) - ss << "0"; - } - else if (varName == "USING_SNDPARTS") { - tmpVar = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE | - FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER); - ss << (((mmd->domain->particle_type & tmpVar)) ? "True" : "False"); - } - else if (varName == "GUIDING_ALPHA") - ss << mmd->domain->guide_alpha; - else if (varName == "GUIDING_BETA") - ss << mmd->domain->guide_beta; - else if (varName == "GUIDING_FACTOR") - ss << mmd->domain->guide_vel_factor; - else if (varName == "GRAVITY_X") - ss << mmd->domain->gravity[0]; - else if (varName == "GRAVITY_Y") - ss << mmd->domain->gravity[1]; - else if (varName == "GRAVITY_Z") - ss << mmd->domain->gravity[2]; - else if (varName == "CACHE_DIR") - ss << mmd->domain->cache_directory; - else if (varName == "CACHE_RESUMABLE") - ss << (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL ? "False" : "True"); - else if (varName == "USING_ADAPTIVETIME") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME ? "True" : "False"); - else if (varName == "USING_SPEEDVECTORS") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS ? "True" : "False"); - else if (varName == "USING_FRACTIONS") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS ? "True" : "False"); - else if (varName == "DELETE_IN_OBSTACLE") - ss << (mmd->domain->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE ? "True" : "False"); - else if (varName == "USING_DIFFUSION") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DIFFUSION ? "True" : "False"); - else - std::cerr << "Fluid Error -- Unknown option: " << varName << std::endl; - return ss.str(); -} - -std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd) + + return it->second; +} + +string MANTA::parseLine(const string &line) { if (line.size() == 0) return ""; - std::string res = ""; + string res = ""; int currPos = 0, start_del = 0, end_del = -1; bool readingVar = false; const char delimiter = '$'; @@ -1040,7 +882,7 @@ std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd) else if (line[currPos] == delimiter && readingVar) { readingVar = false; end_del = currPos; - res += getRealValue(line.substr(start_del, currPos - start_del), mmd); + res += getRealValue(line.substr(start_del, currPos - start_del)); } currPos++; } @@ -1048,13 +890,21 @@ std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd) return res; } -std::string MANTA::parseScript(const std::string &setup_string, FluidModifierData *mmd) +string MANTA::parseScript(const string &setup_string, FluidModifierData *mmd) { - std::istringstream f(setup_string); - std::ostringstream res; - std::string line = ""; + if (MANTA::with_debug) + cout << "MANTA::parseScript()" << endl; + + istringstream f(setup_string); + ostringstream res; + string line = ""; + + // Update RNA map if modifier data is handed over + if (mmd) { + initializeRNAMap(mmd); + } while (getline(f, line)) { - res << parseLine(line, mmd) << "\n"; + res << parseLine(line) << "\n"; } return res.str(); } @@ -1062,13 +912,14 @@ std::string MANTA::parseScript(const std::string &setup_string, FluidModifierDat bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateFlipStructures()" << std::endl; + cout << "MANTA::updateFlipStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mFlipFromFile = false; if (!mUsingLiquid) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; @@ -1081,8 +932,8 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr) mFlipParticleData->clear(); mFlipParticleVelocity->clear(); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); - std::string file = getFile( + string pformat = getCacheFileEnding(mds->cache_particle_format); + string file = getFile( mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_PP, pformat.c_str(), framenr); expected += 1; @@ -1104,13 +955,14 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateMeshStructures()" << std::endl; + cout << "MANTA::updateMeshStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mMeshFromFile = false; if (!mUsingMesh) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; @@ -1126,9 +978,9 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr) if (mMeshVelocities) mMeshVelocities->clear(); - std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, mformat, framenr); + string mformat = getCacheFileEnding(mds->cache_mesh_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, mformat, framenr); expected += 1; if (BLI_exists(file.c_str())) { @@ -1151,13 +1003,14 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateParticleStructures()" << std::endl; + cout << "MANTA::updateParticleStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mParticlesFromFile = false; if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; @@ -1171,8 +1024,8 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) mSndParticleVelocity->clear(); mSndParticleLife->clear(); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); - std::string file = getFile( + string pformat = getCacheFileEnding(mds->cache_particle_format); + string file = getFile( mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PPSND, pformat, framenr); expected += 1; @@ -1201,21 +1054,21 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateGridStructures()" << std::endl; + cout << "MANTA::updateGridStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mSmokeFromFile = false; if (!mUsingSmoke) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; int expected = 0; /* Expected number of read successes for this frame. */ - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string file = getFile( - mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_DENSITY, dformat, framenr); + string dformat = getCacheFileEnding(mds->cache_data_format); + string file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_DENSITY, dformat, framenr); expected += 1; if (BLI_exists(file.c_str())) { @@ -1291,21 +1144,22 @@ bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateNoiseStructures()" << std::endl; + cout << "MANTA::updateNoiseStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mNoiseFromFile = false; if (!mUsingSmoke || !mUsingNoise) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; int expected = 0; /* Expected number of read successes for this frame. */ - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); - std::string file = getFile( + string dformat = getCacheFileEnding(mds->cache_data_format); + string nformat = getCacheFileEnding(mds->cache_noise_format); + string file = getFile( mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_DENSITYNOISE, nformat, framenr); expected += 1; @@ -1371,10 +1225,10 @@ bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr) } /* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */ -static std::string escapeSlashes(std::string const &s) +static string escapeSlashes(string const &s) { - std::string result = ""; - for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) { + string result = ""; + for (string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) { unsigned char c = *i; if (c == '\\') result += "\\\\"; @@ -1387,21 +1241,20 @@ static std::string escapeSlashes(std::string const &s) bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::writeConfiguration()" << std::endl; + cout << "MANTA::writeConfiguration()" << endl; FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); - std::string format = FLUID_DOMAIN_EXTENSION_UNI; - std::string file = getFile( - mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); + string format = FLUID_DOMAIN_EXTENSION_UNI; + string file = getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); /* Create 'config' subdir if it does not exist already. */ BLI_dir_create_recursive(directory.c_str()); gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "wb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- Cannot open file " << file << std::endl; + cerr << "Fluid Error -- Cannot open file " << file << endl; return false; } @@ -1419,6 +1272,7 @@ bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr) gzwrite(gzf, &mds->res_min, 3 * sizeof(int)); gzwrite(gzf, &mds->res_max, 3 * sizeof(int)); gzwrite(gzf, &mds->active_color, 3 * sizeof(float)); + gzwrite(gzf, &mds->time_total, sizeof(int)); return (gzclose(gzf) == Z_OK); } @@ -1426,17 +1280,18 @@ bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr) bool MANTA::writeData(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::writeData()" << std::endl; + cout << "MANTA::writeData()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; ss.str(""); ss << "fluid_save_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr @@ -1461,16 +1316,17 @@ bool MANTA::writeData(FluidModifierData *mmd, int framenr) bool MANTA::writeNoise(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::writeNoise()" << std::endl; + cout << "MANTA::writeNoise()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); + string nformat = getCacheFileEnding(mds->cache_noise_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; if (mUsingSmoke && mUsingNoise) { ss.str(""); @@ -1484,22 +1340,21 @@ bool MANTA::writeNoise(FluidModifierData *mmd, int framenr) bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readConfiguration()" << std::endl; + cout << "MANTA::readConfiguration()" << endl; FluidDomainSettings *mds = mmd->domain; float dummy; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); - std::string format = FLUID_DOMAIN_EXTENSION_UNI; - std::string file = getFile( - mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); + string format = FLUID_DOMAIN_EXTENSION_UNI; + string file = getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); if (!hasConfig(mmd, framenr)) return false; gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- Cannot open file " << file << std::endl; + cerr << "Fluid Error -- Cannot open file " << file << endl; return false; } @@ -1517,6 +1372,8 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) gzread(gzf, &mds->res_min, 3 * sizeof(int)); gzread(gzf, &mds->res_max, 3 * sizeof(int)); gzread(gzf, &mds->active_color, 3 * sizeof(float)); + gzread(gzf, &mds->time_total, sizeof(int)); + mds->total_cells = mds->res[0] * mds->res[1] * mds->res[2]; return (gzclose(gzf) == Z_OK); @@ -1525,21 +1382,22 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) bool MANTA::readData(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readData()" << std::endl; + cout << "MANTA::readData()" << endl; if (!mUsingSmoke && !mUsingLiquid) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; bool result = true; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; /* Sanity check: Are cache files present? */ if (!hasData(mmd, framenr)) @@ -1570,19 +1428,20 @@ bool MANTA::readData(FluidModifierData *mmd, int framenr) bool MANTA::readNoise(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readNoise()" << std::endl; + cout << "MANTA::readNoise()" << endl; if (!mUsingSmoke || !mUsingNoise) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); + string nformat = getCacheFileEnding(mds->cache_noise_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; /* Sanity check: Are cache files present? */ if (!hasNoise(mmd, framenr)) @@ -1602,17 +1461,18 @@ bool MANTA::readNoise(FluidModifierData *mmd, int framenr) bool MANTA::readMesh(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readMesh()" << std::endl; + cout << "MANTA::readMesh()" << endl; if (!mUsingLiquid || !mUsingMesh) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_MESH); - std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_MESH); + string mformat = getCacheFileEnding(mds->cache_mesh_format); + string dformat = getCacheFileEnding(mds->cache_data_format); /* Sanity check: Are cache files present? */ if (!hasMesh(mmd, framenr)) @@ -1639,21 +1499,22 @@ bool MANTA::readMesh(FluidModifierData *mmd, int framenr) bool MANTA::readParticles(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readParticles()" << std::endl; + cout << "MANTA::readParticles()" << endl; if (!mUsingLiquid) return false; if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_PARTICLES); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_PARTICLES); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; /* Sanity check: Are cache files present? */ if (!hasParticles(mmd, framenr)) @@ -1670,19 +1531,21 @@ bool MANTA::readParticles(FluidModifierData *mmd, int framenr) bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) { if (with_debug) - std::cout << "MANTA::readGuiding()" << std::endl; + cout << "MANTA::readGuiding()" << endl; + + FluidDomainSettings *mds = mmd->domain; if (!mUsingGuiding) return false; - if (!mmd->domain) + if (!mds) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; - std::string directory = (sourceDomain) ? getDirectory(mmd, FLUID_DOMAIN_DIR_DATA) : - getDirectory(mmd, FLUID_DOMAIN_DIR_GUIDE); - std::string gformat = getCacheFileEnding(mmd->domain->cache_data_format); + string directory = (sourceDomain) ? getDirectory(mmd, FLUID_DOMAIN_DIR_DATA) : + getDirectory(mmd, FLUID_DOMAIN_DIR_GUIDE); + string gformat = getCacheFileEnding(mds->cache_data_format); /* Sanity check: Are cache files present? */ if (!hasGuiding(mmd, framenr, sourceDomain)) @@ -1706,28 +1569,26 @@ bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) bool MANTA::bakeData(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeData()" << std::endl; + cout << "MANTA::bakeData()" << endl; - std::string tmpString, finalString; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + string tmpString, finalString; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirGuiding[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirGuiding[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); - std::string gformat = dformat; // Use same data format for guiding format + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); + string gformat = dformat; // Use same data format for guiding format - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); BLI_path_join(cacheDirGuiding, sizeof(cacheDirGuiding), - mmd->domain->cache_directory, + mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, nullptr); BLI_path_make_safe(cacheDirData); @@ -1745,31 +1606,26 @@ bool MANTA::bakeData(FluidModifierData *mmd, int framenr) bool MANTA::bakeNoise(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeNoise()" << std::endl; + cout << "MANTA::bakeNoise()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirNoise[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirNoise[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string nformat = getCacheFileEnding(mds->cache_noise_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); - BLI_path_join(cacheDirNoise, - sizeof(cacheDirNoise), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_NOISE, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); + BLI_path_join( + cacheDirNoise, sizeof(cacheDirNoise), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, nullptr); BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirNoise); @@ -1785,29 +1641,24 @@ bool MANTA::bakeNoise(FluidModifierData *mmd, int framenr) bool MANTA::bakeMesh(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeMesh()" << std::endl; + cout << "MANTA::bakeMesh()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirMesh[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirMesh[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string mformat = getCacheFileEnding(mds->cache_mesh_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); - BLI_path_join(cacheDirMesh, - sizeof(cacheDirMesh), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_MESH, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); + BLI_path_join( + cacheDirMesh, sizeof(cacheDirMesh), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, nullptr); BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirMesh); @@ -1823,29 +1674,27 @@ bool MANTA::bakeMesh(FluidModifierData *mmd, int framenr) bool MANTA::bakeParticles(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeParticles()" << std::endl; + cout << "MANTA::bakeParticles()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirParticles[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirParticles[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); BLI_path_join(cacheDirParticles, sizeof(cacheDirParticles), - mmd->domain->cache_directory, + mds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, nullptr); BLI_path_make_safe(cacheDirData); @@ -1863,22 +1712,23 @@ bool MANTA::bakeParticles(FluidModifierData *mmd, int framenr) bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeGuiding()" << std::endl; + cout << "MANTA::bakeGuiding()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirGuiding[FILE_MAX]; cacheDirGuiding[0] = '\0'; - std::string gformat = getCacheFileEnding(mmd->domain->cache_data_format); + string gformat = getCacheFileEnding(mds->cache_data_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; BLI_path_join(cacheDirGuiding, sizeof(cacheDirGuiding), - mmd->domain->cache_directory, + mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, nullptr); BLI_path_make_safe(cacheDirGuiding); @@ -1893,8 +1743,8 @@ bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr) bool MANTA::updateVariables(FluidModifierData *mmd) { - std::string tmpString, finalString; - std::vector<std::string> pythonCommands; + string tmpString, finalString; + vector<string> pythonCommands; tmpString += fluid_variables; if (mUsingSmoke) @@ -1924,13 +1774,15 @@ bool MANTA::updateVariables(FluidModifierData *mmd) void MANTA::exportSmokeScript(FluidModifierData *mmd) { if (with_debug) - std::cout << "MANTA::exportSmokeScript()" << std::endl; + cout << "MANTA::exportSmokeScript()" << endl; char cacheDir[FILE_MAX] = "\0"; char cacheDirScript[FILE_MAX] = "\0"; + FluidDomainSettings *mds = mmd->domain; + BLI_path_join( - cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); + cacheDir, sizeof(cacheDir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); BLI_path_make_safe(cacheDir); /* Create 'script' subdir if it does not exist already */ BLI_dir_create_recursive(cacheDir); @@ -1938,16 +1790,16 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd) cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_SMOKE_SCRIPT, nullptr); BLI_path_make_safe(cacheDir); - bool noise = mmd->domain->flags & FLUID_DOMAIN_USE_NOISE; - bool heat = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT; - bool colors = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS; - bool fire = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE; - bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; - bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; - bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; - bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; + bool noise = mds->flags & FLUID_DOMAIN_USE_NOISE; + bool heat = mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT; + bool colors = mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS; + bool fire = mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE; + bool obstacle = mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; + bool guiding = mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; + bool invel = mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; + bool outflow = mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; - std::string manta_script; + string manta_script; // Libraries manta_script += header_libraries + manta_import; @@ -2019,10 +1871,10 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd) manta_script += header_main + smoke_standalone + fluid_standalone; // Fill in missing variables in script - std::string final_script = MANTA::parseScript(manta_script, mmd); + string final_script = MANTA::parseScript(manta_script, mmd); // Write script - std::ofstream myfile; + ofstream myfile; myfile.open(cacheDirScript); myfile << final_script; myfile.close(); @@ -2031,13 +1883,15 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd) void MANTA::exportLiquidScript(FluidModifierData *mmd) { if (with_debug) - std::cout << "MANTA::exportLiquidScript()" << std::endl; + cout << "MANTA::exportLiquidScript()" << endl; char cacheDir[FILE_MAX] = "\0"; char cacheDirScript[FILE_MAX] = "\0"; + FluidDomainSettings *mds = mmd->domain; + BLI_path_join( - cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); + cacheDir, sizeof(cacheDir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); BLI_path_make_safe(cacheDir); /* Create 'script' subdir if it does not exist already */ BLI_dir_create_recursive(cacheDir); @@ -2045,18 +1899,18 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_LIQUID_SCRIPT, nullptr); BLI_path_make_safe(cacheDirScript); - bool mesh = mmd->domain->flags & FLUID_DOMAIN_USE_MESH; - bool drops = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY; - bool bubble = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE; - bool floater = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; - bool tracer = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER; - bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; - bool fractions = mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS; - bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; - bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; - bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; + bool mesh = mds->flags & FLUID_DOMAIN_USE_MESH; + bool drops = mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY; + bool bubble = mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE; + bool floater = mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; + bool tracer = mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER; + bool obstacle = mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; + bool fractions = mds->flags & FLUID_DOMAIN_USE_FRACTIONS; + bool guiding = mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; + bool invel = mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; + bool outflow = mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; - std::string manta_script; + string manta_script; // Libraries manta_script += header_libraries + manta_import; @@ -2126,10 +1980,10 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) manta_script += header_main + liquid_standalone + fluid_standalone; // Fill in missing variables in script - std::string final_script = MANTA::parseScript(manta_script, mmd); + string final_script = MANTA::parseScript(manta_script, mmd); // Write script - std::ofstream myfile; + ofstream myfile; myfile.open(cacheDirScript); myfile << final_script; myfile.close(); @@ -2142,14 +1996,12 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) * * Important! Return value: New reference or nullptr * Caller of this function needs to handle reference count of returned object. */ -static PyObject *callPythonFunction(std::string varName, - std::string functionName, - bool isAttribute = false) +static PyObject *callPythonFunction(string varName, string functionName, bool isAttribute = false) { if ((varName == "") || (functionName == "")) { if (MANTA::with_debug) - std::cout << "Missing Python variable name and/or function name -- name is: " << varName - << ", function name is: " << functionName << std::endl; + cout << "Missing Python variable name and/or function name -- name is: " << varName + << ", function name is: " << functionName << endl; return nullptr; } @@ -2202,8 +2054,8 @@ static void *pyObjectToPointer(PyObject *inputObject) Py_DECREF(inputObject); - std::string str(result); - std::istringstream in(str); + string str(result); + istringstream in(str); void *dataPointer = nullptr; in >> dataPointer; @@ -2250,11 +2102,11 @@ static long pyObjectToLong(PyObject *inputObject) int MANTA::getFrame() { if (with_debug) - std::cout << "MANTA::getFrame()" << std::endl; + cout << "MANTA::getFrame()" << endl; - std::string func = "frame"; - std::string id = std::to_string(mCurrentID); - std::string solver = "s" + id; + string func = "frame"; + string id = to_string(mCurrentID); + string solver = "s" + id; return pyObjectToLong(callPythonFunction(solver, func, true)); } @@ -2262,11 +2114,11 @@ int MANTA::getFrame() float MANTA::getTimestep() { if (with_debug) - std::cout << "MANTA::getTimestep()" << std::endl; + cout << "MANTA::getTimestep()" << endl; - std::string func = "timestep"; - std::string id = std::to_string(mCurrentID); - std::string solver = "s" + id; + string func = "timestep"; + string id = to_string(mCurrentID); + string solver = "s" + id; return (float)pyObjectToDouble(callPythonFunction(solver, func, true)); } @@ -2280,10 +2132,10 @@ bool MANTA::needsRealloc(FluidModifierData *mmd) void MANTA::adaptTimestep() { if (with_debug) - std::cout << "MANTA::adaptTimestep()" << std::endl; + cout << "MANTA::adaptTimestep()" << endl; - std::vector<std::string> pythonCommands; - std::ostringstream ss; + vector<string> pythonCommands; + ostringstream ss; ss << "fluid_adapt_time_step_" << mCurrentID << "()"; pythonCommands.push_back(ss.str()); @@ -2291,14 +2143,14 @@ void MANTA::adaptTimestep() runPythonString(pythonCommands); } -bool MANTA::updateMeshFromFile(std::string filename) +bool MANTA::updateMeshFromFile(string filename) { - std::string fname(filename); - std::string::size_type idx; + string fname(filename); + string::size_type idx; idx = fname.rfind('.'); - if (idx != std::string::npos) { - std::string extension = fname.substr(idx + 1); + if (idx != string::npos) { + string extension = fname.substr(idx + 1); if (extension.compare("gz") == 0) return updateMeshFromBobj(filename); @@ -2307,27 +2159,25 @@ bool MANTA::updateMeshFromFile(std::string filename) else if (extension.compare("uni") == 0) return updateMeshFromUni(filename); else - std::cerr << "Fluid Error -- updateMeshFromFile(): Invalid file extension in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromFile(): Invalid file extension in file: " << filename + << endl; } else { - std::cerr << "Fluid Error -- updateMeshFromFile(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromFile(): Unable to open file: " << filename << endl; } return false; } -bool MANTA::updateMeshFromBobj(std::string filename) +bool MANTA::updateMeshFromBobj(string filename) { if (with_debug) - std::cout << "MANTA::updateMeshFromBobj()" << std::endl; + cout << "MANTA::updateMeshFromBobj()" << endl; gzFile gzf; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to open file: " << filename << endl; return false; } @@ -2336,15 +2186,14 @@ bool MANTA::updateMeshFromBobj(std::string filename) // Num vertices readBytes = gzread(gzf, &numBuffer, sizeof(int)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh vertices from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh vertices from " + << filename << endl; gzclose(gzf); return false; } if (with_debug) - std::cout << "read mesh , num verts: " << numBuffer << " , in file: " << filename << std::endl; + cout << "read mesh , num verts: " << numBuffer << " , in file: " << filename << endl; int numChunks = (int)(ceil((float)numBuffer / NODE_CHUNK)); int readLen, readStart, readEnd, k; @@ -2365,8 +2214,8 @@ bool MANTA::updateMeshFromBobj(std::string filename) readBytes = gzread(gzf, bufferVerts, readLen * sizeof(float) * 3); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh vertices from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh vertices from " + << filename << endl; MEM_freeN(bufferVerts); gzclose(gzf); return false; @@ -2378,7 +2227,7 @@ bool MANTA::updateMeshFromBobj(std::string filename) CLAMP(readEnd, 0, numBuffer); k = 0; - for (std::vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { + for (vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { mMeshNodes->at(j).pos[0] = bufferVerts[k]; mMeshNodes->at(j).pos[1] = bufferVerts[k + 1]; mMeshNodes->at(j).pos[2] = bufferVerts[k + 2]; @@ -2391,15 +2240,14 @@ bool MANTA::updateMeshFromBobj(std::string filename) // Num normals readBytes = gzread(gzf, &numBuffer, sizeof(int)); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh normals from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh normals from " + << filename << endl; gzclose(gzf); return false; } if (with_debug) - std::cout << "read mesh , num normals : " << numBuffer << " , in file: " << filename - << std::endl; + cout << "read mesh , num normals : " << numBuffer << " , in file: " << filename << endl; if (numBuffer) { // Normals @@ -2418,8 +2266,8 @@ bool MANTA::updateMeshFromBobj(std::string filename) readBytes = gzread(gzf, bufferNormals, readLen * sizeof(float) * 3); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh normals from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh normals from " + << filename << endl; MEM_freeN(bufferNormals); gzclose(gzf); return false; @@ -2431,7 +2279,7 @@ bool MANTA::updateMeshFromBobj(std::string filename) CLAMP(readEnd, 0, numBuffer); k = 0; - for (std::vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { + for (vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { mMeshNodes->at(j).normal[0] = bufferNormals[k]; mMeshNodes->at(j).normal[1] = bufferNormals[k + 1]; mMeshNodes->at(j).normal[2] = bufferNormals[k + 2]; @@ -2444,16 +2292,15 @@ bool MANTA::updateMeshFromBobj(std::string filename) // Num triangles readBytes = gzread(gzf, &numBuffer, sizeof(int)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh triangles from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh triangles from " + << filename << endl; gzclose(gzf); return false; } if (with_debug) - std::cout << "Fluid: Read mesh , num triangles : " << numBuffer << " , in file: " << filename - << std::endl; + cout << "Fluid: Read mesh , num triangles : " << numBuffer << " , in file: " << filename + << endl; numChunks = (int)(ceil((float)numBuffer / TRIANGLE_CHUNK)); @@ -2473,8 +2320,8 @@ bool MANTA::updateMeshFromBobj(std::string filename) readBytes = gzread(gzf, bufferTriangles, readLen * sizeof(int) * 3); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh triangles from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh triangles from " + << filename << endl; MEM_freeN(bufferTriangles); gzclose(gzf); return false; @@ -2486,7 +2333,7 @@ bool MANTA::updateMeshFromBobj(std::string filename) CLAMP(readEnd, 0, numBuffer); k = 0; - for (std::vector<MANTA::Triangle>::size_type j = readStart; j < readEnd; j++, k += 3) { + for (vector<MANTA::Triangle>::size_type j = readStart; j < readEnd; j++, k += 3) { mMeshTriangles->at(j).c[0] = bufferTriangles[k]; mMeshTriangles->at(j).c[1] = bufferTriangles[k + 1]; mMeshTriangles->at(j).c[2] = bufferTriangles[k + 2]; @@ -2498,24 +2345,23 @@ bool MANTA::updateMeshFromBobj(std::string filename) return (gzclose(gzf) == Z_OK); } -bool MANTA::updateMeshFromObj(std::string filename) +bool MANTA::updateMeshFromObj(string filename) { if (with_debug) - std::cout << "MANTA::updateMeshFromObj()" << std::endl; + cout << "MANTA::updateMeshFromObj()" << endl; - std::ifstream ifs(filename); + ifstream ifs(filename); float fbuffer[3]; int ibuffer[3]; int cntVerts = 0, cntNormals = 0, cntTris = 0; if (!ifs.good()) { - std::cerr << "Fluid Error -- updateMeshFromObj(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromObj(): Unable to open file: " << filename << endl; return false; } while (ifs.good() && !ifs.eof()) { - std::string id; + string id; ifs >> id; if (id[0] == '#') { @@ -2529,8 +2375,8 @@ bool MANTA::updateMeshFromObj(std::string filename) else if (id == "vn") { // normals if (getNumVertices() != cntVerts) { - std::cerr << "Fluid Error -- updateMeshFromObj(): Invalid number of mesh nodes in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromObj(): Invalid number of mesh nodes in file: " + << filename << endl; return false; } @@ -2553,20 +2399,20 @@ bool MANTA::updateMeshFromObj(std::string filename) } else if (id == "g") { // group - std::string group; + string group; ifs >> group; } else if (id == "f") { // face - std::string face; + string face; for (int i = 0; i < 3; i++) { ifs >> face; - if (face.find('/') != std::string::npos) + if (face.find('/') != string::npos) face = face.substr(0, face.find('/')); // ignore other indices int idx = atoi(face.c_str()) - 1; if (idx < 0) { - std::cerr << "Fluid Error -- updateMeshFromObj(): Invalid face encountered in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromObj(): Invalid face encountered in file: " + << filename << endl; return false; } ibuffer[i] = idx; @@ -2588,10 +2434,10 @@ bool MANTA::updateMeshFromObj(std::string filename) return true; } -bool MANTA::updateMeshFromUni(std::string filename) +bool MANTA::updateMeshFromUni(string filename) { if (with_debug) - std::cout << "MANTA::updateMeshFromUni()" << std::endl; + cout << "MANTA::updateMeshFromUni()" << endl; gzFile gzf; float fbuffer[4]; @@ -2599,8 +2445,7 @@ bool MANTA::updateMeshFromUni(std::string filename) gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- updateMeshFromUni(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): Unable to open file: " << filename << endl; return false; } @@ -2608,13 +2453,13 @@ bool MANTA::updateMeshFromUni(std::string filename) char file_magic[5] = {0, 0, 0, 0, 0}; readBytes = gzread(gzf, file_magic, 4); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromUni(): Unable to read header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): Unable to read header in file: " << filename + << endl; gzclose(gzf); return false; } - std::vector<pVel> *velocityPointer = mMeshVelocities; + vector<pVel> *velocityPointer = mMeshVelocities; // mdata uni header const int STR_LEN_PDATA = 256; @@ -2630,19 +2475,18 @@ bool MANTA::updateMeshFromUni(std::string filename) gzread(gzf, ×tamp, sizeof(unsigned long long)); if (with_debug) - std::cout << "Fluid: Read " << ibuffer[0] << " vertices in file: " << filename << std::endl; + cout << "Fluid: Read " << ibuffer[0] << " vertices in file: " << filename << endl; // Sanity checks const int meshSize = sizeof(float) * 3 + sizeof(int); if (!(bytesPerElement == meshSize) && (elementType == 0)) { - std::cerr << "Fluid Error -- updateMeshFromUni(): Invalid header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): Invalid header in file: " << filename << endl; gzclose(gzf); return false; } if (!ibuffer[0]) { // Any vertices present? - std::cerr << "Fluid Error -- updateMeshFromUni(): No vertices present in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): No vertices present in file: " << filename + << endl; gzclose(gzf); return false; } @@ -2657,7 +2501,7 @@ bool MANTA::updateMeshFromUni(std::string filename) velocityPointer->resize(numParticles); MANTA::pVel *bufferPVel; - for (std::vector<pVel>::iterator it = velocityPointer->begin(); it != velocityPointer->end(); + for (vector<pVel>::iterator it = velocityPointer->begin(); it != velocityPointer->end(); ++it) { gzread(gzf, fbuffer, sizeof(float) * 3); bufferPVel = (MANTA::pVel *)fbuffer; @@ -2669,44 +2513,42 @@ bool MANTA::updateMeshFromUni(std::string filename) return (gzclose(gzf) == Z_OK); } -bool MANTA::updateParticlesFromFile(std::string filename, bool isSecondarySys, bool isVelData) +bool MANTA::updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData) { if (with_debug) - std::cout << "MANTA::updateParticlesFromFile()" << std::endl; + cout << "MANTA::updateParticlesFromFile()" << endl; - std::string fname(filename); - std::string::size_type idx; + string fname(filename); + string::size_type idx; idx = fname.rfind('.'); - if (idx != std::string::npos) { - std::string extension = fname.substr(idx + 1); + if (idx != string::npos) { + string extension = fname.substr(idx + 1); if (extension.compare("uni") == 0) return updateParticlesFromUni(filename, isSecondarySys, isVelData); else - std::cerr << "Fluid Error -- updateParticlesFromFile(): Invalid file extension in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromFile(): Invalid file extension in file: " + << filename << endl; return false; } else { - std::cerr << "Fluid Error -- updateParticlesFromFile(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateParticlesFromFile(): Unable to open file: " << filename << endl; return false; } } -bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bool isVelData) +bool MANTA::updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData) { if (with_debug) - std::cout << "MANTA::updateParticlesFromUni()" << std::endl; + cout << "MANTA::updateParticlesFromUni()" << endl; gzFile gzf; int ibuffer[4]; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to open file: " << filename << endl; return false; } @@ -2714,24 +2556,24 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo char file_magic[5] = {0, 0, 0, 0, 0}; readBytes = gzread(gzf, file_magic, 4); if (!readBytes) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read header in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read header in file: " << filename + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "PB01")) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Particle uni file format v01 not " - "supported anymore." - << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Particle uni file format v01 not " + "supported anymore." + << endl; gzclose(gzf); return false; } // Pointer to FLIP system or to secondary particle system - std::vector<pData> *dataPointer = nullptr; - std::vector<pVel> *velocityPointer = nullptr; - std::vector<float> *lifePointer = nullptr; + vector<pData> *dataPointer = nullptr; + vector<pVel> *velocityPointer = nullptr; + vector<float> *lifePointer = nullptr; if (isSecondarySys) { dataPointer = mSndParticleData; @@ -2757,19 +2599,19 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo gzread(gzf, ×tamp, sizeof(unsigned long long)); if (with_debug) - std::cout << "Fluid: Read " << ibuffer[0] << " particles in file: " << filename << std::endl; + cout << "Fluid: Read " << ibuffer[0] << " particles in file: " << filename << endl; // Sanity checks const int partSysSize = sizeof(float) * 3 + sizeof(int); if (!(bytesPerElement == partSysSize) && (elementType == 0)) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Invalid header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Invalid header in file: " << filename + << endl; gzclose(gzf); return false; } if (!ibuffer[0]) { // Any particles present? if (with_debug) - std::cout << "Fluid: No particles present in file: " << filename << std::endl; + cout << "Fluid: No particles present in file: " << filename << endl; gzclose(gzf); return true; // return true since having no particles in a cache file is valid } @@ -2797,9 +2639,8 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo readBytes = gzread(gzf, bufferPData, readLen * sizeof(pData)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateParticlesFromUni(): Unable to read particle data in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle data in file: " + << filename << endl; MEM_freeN(bufferPData); gzclose(gzf); return false; @@ -2811,7 +2652,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo CLAMP(readEnd, 0, numParticles); int k = 0; - for (std::vector<MANTA::pData>::size_type j = readStart; j < readEnd; j++, k++) { + for (vector<MANTA::pData>::size_type j = readStart; j < readEnd; j++, k++) { dataPointer->at(j).pos[0] = bufferPData[k].pos[0]; dataPointer->at(j).pos[1] = bufferPData[k].pos[1]; dataPointer->at(j).pos[2] = bufferPData[k].pos[2]; @@ -2838,9 +2679,9 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo readBytes = gzread(gzf, bufferPVel, readLen * sizeof(pVel)); if (!readBytes) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle velocities " - "in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle velocities " + "in file: " + << filename << endl; MEM_freeN(bufferPVel); gzclose(gzf); return false; @@ -2852,7 +2693,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo CLAMP(readEnd, 0, numParticles); int k = 0; - for (std::vector<MANTA::pVel>::size_type j = readStart; j < readEnd; j++, k++) { + for (vector<MANTA::pVel>::size_type j = readStart; j < readEnd; j++, k++) { velocityPointer->at(j).pos[0] = bufferPVel[k].pos[0]; velocityPointer->at(j).pos[1] = bufferPVel[k].pos[1]; velocityPointer->at(j).pos[2] = bufferPVel[k].pos[2]; @@ -2877,9 +2718,8 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo readBytes = gzread(gzf, bufferPLife, readLen * sizeof(float)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateParticlesFromUni(): Unable to read particle life in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle life in file: " + << filename << endl; MEM_freeN(bufferPLife); gzclose(gzf); return false; @@ -2891,7 +2731,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo CLAMP(readEnd, 0, numParticles); int k = 0; - for (std::vector<float>::size_type j = readStart; j < readEnd; j++, k++) { + for (vector<float>::size_type j = readStart; j < readEnd; j++, k++) { lifePointer->at(j) = bufferPLife[k]; } todoParticles -= readLen; @@ -2901,24 +2741,24 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo return (gzclose(gzf) == Z_OK); } -bool MANTA::updateGridFromFile(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromFile(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromFile()" << std::endl; + cout << "MANTA::updateGridFromFile()" << endl; if (!grid) { - std::cerr << "Fluid Error -- updateGridFromFile(): Cannot read into uninitialized grid (grid " - "is null)." - << std::endl; + cerr << "Fluid Error -- updateGridFromFile(): Cannot read into uninitialized grid (grid " + "is null)." + << endl; return false; } - std::string fname(filename); - std::string::size_type idx; + string fname(filename); + string::size_type idx; idx = fname.rfind('.'); - if (idx != std::string::npos) { - std::string extension = fname.substr(idx + 1); + if (idx != string::npos) { + string extension = fname.substr(idx + 1); if (extension.compare("uni") == 0) return updateGridFromUni(filename, grid, isNoise); @@ -2929,29 +2769,27 @@ bool MANTA::updateGridFromFile(std::string filename, float *grid, bool isNoise) else if (extension.compare("raw") == 0) return updateGridFromRaw(filename, grid, isNoise); else - std::cerr << "Fluid Error -- updateGridFromFile(): Invalid file extension in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateGridFromFile(): Invalid file extension in file: " << filename + << endl; return false; } else { - std::cerr << "Fluid Error -- updateGridFromFile(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromFile(): Unable to open file: " << filename << endl; return false; } } -bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromUni(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromUni()" << std::endl; + cout << "MANTA::updateGridFromUni()" << endl; gzFile gzf; int ibuffer[4]; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); if (!gzf) { - std::cerr << "Fluid Error -- updateGridFromUni(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Unable to open file: " << filename << endl; return false; } @@ -2959,32 +2797,29 @@ bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) char file_magic[5] = {0, 0, 0, 0, 0}; readBytes = gzread(gzf, file_magic, 4); if (!readBytes) { - std::cerr << "Fluid Error -- updateGridFromUni(): Unable to read header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Unable to read header in file: " << filename + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "DDF2")) { - std::cerr - << "Fluid Error -- updateGridFromUni(): Grid uni file format DDF2 not supported anymore." - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Grid uni file format DDF2 not supported anymore." + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "MNT1")) { - std::cerr - << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT1 not supported anymore." - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT1 not supported anymore." + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "MNT2")) { - std::cerr - << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT2 not supported anymore." - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT2 not supported anymore." + << endl; gzclose(gzf); return false; } @@ -3009,13 +2844,12 @@ bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) int resZ = (isNoise) ? mResZNoise : mResZ; if (with_debug) - std::cout << "Fluid: Read " << ibuffer[3] << " grid type in file: " << filename << std::endl; + cout << "Fluid: Read " << ibuffer[3] << " grid type in file: " << filename << endl; // Sanity checks if (ibuffer[0] != resX || ibuffer[1] != resY || ibuffer[2] != resZ) { - std::cout << "Fluid: Grid dim doesn't match, read: (" << ibuffer[0] << ", " << ibuffer[1] - << ", " << ibuffer[2] << ") vs setup: (" << resX << ", " << resY << ", " << resZ - << ")" << std::endl; + cout << "Fluid: Grid dim doesn't match, read: (" << ibuffer[0] << ", " << ibuffer[1] << ", " + << ibuffer[2] << ") vs setup: (" << resX << ", " << resY << ", " << resZ << ")" << endl; gzclose(gzf); return false; } @@ -3026,16 +2860,16 @@ bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) } if (with_debug) - std::cout << "Fluid: Read successfully: " << filename << std::endl; + cout << "Fluid: Read successfully: " << filename << endl; return (gzclose(gzf) == Z_OK); } #if OPENVDB == 1 -bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromVDB(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromVDB()" << std::endl; + cout << "MANTA::updateGridFromVDB()" << endl; openvdb::initialize(); openvdb::io::File file(filename); @@ -3043,8 +2877,8 @@ bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise) file.open(); } catch (const openvdb::IoError &) { - std::cerr << "Fluid Error -- updateGridFromVDB(): IOError, invalid OpenVDB file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromVDB(): IOError, invalid OpenVDB file: " << filename + << endl; return false; } @@ -3076,17 +2910,17 @@ bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise) } #endif -bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromRaw(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromRaw()" << std::endl; + cout << "MANTA::updateGridFromRaw()" << endl; gzFile gzf; int expectedBytes, readBytes; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb"); if (!gzf) { - std::cout << "MANTA::updateGridFromRaw(): unable to open file" << std::endl; + cout << "MANTA::updateGridFromRaw(): unable to open file" << endl; return false; } @@ -3097,8 +2931,7 @@ bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise) expectedBytes = sizeof(float) * resX * resY * resZ; readBytes = gzread(gzf, grid, expectedBytes); if (!readBytes) { - std::cerr << "Fluid Error -- updateGridFromRaw(): Unable to read raw file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromRaw(): Unable to read raw file: " << filename << endl; gzclose(gzf); return false; } @@ -3111,25 +2944,25 @@ bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise) void MANTA::updatePointers() { if (with_debug) - std::cout << "MANTA::updatePointers()" << std::endl; - - std::string func = "getDataPointer"; - std::string funcNodes = "getNodesDataPointer"; - std::string funcTris = "getTrisDataPointer"; - - std::string id = std::to_string(mCurrentID); - std::string solver = "s" + id; - std::string parts = "pp" + id; - std::string snd = "sp" + id; - std::string mesh = "sm" + id; - std::string mesh2 = "mesh" + id; - std::string noise = "sn" + id; - std::string solver_ext = "_" + solver; - std::string parts_ext = "_" + parts; - std::string snd_ext = "_" + snd; - std::string mesh_ext = "_" + mesh; - std::string mesh_ext2 = "_" + mesh2; - std::string noise_ext = "_" + noise; + cout << "MANTA::updatePointers()" << endl; + + string func = "getDataPointer"; + string funcNodes = "getNodesDataPointer"; + string funcTris = "getTrisDataPointer"; + + string id = to_string(mCurrentID); + string solver = "s" + id; + string parts = "pp" + id; + string snd = "sp" + id; + string mesh = "sm" + id; + string mesh2 = "mesh" + id; + string noise = "sn" + id; + string solver_ext = "_" + solver; + string parts_ext = "_" + parts; + string snd_ext = "_" + snd; + string mesh_ext = "_" + mesh; + string mesh_ext2 = "_" + mesh2; + string noise_ext = "_" + noise; mFlags = (int *)pyObjectToPointer(callPythonFunction("flags" + solver_ext, func)); mPhiIn = (float *)pyObjectToPointer(callPythonFunction("phiIn" + solver_ext, func)); @@ -3216,27 +3049,27 @@ void MANTA::updatePointers() } if (mUsingLiquid) { mPhi = (float *)pyObjectToPointer(callPythonFunction("phi" + solver_ext, func)); - mFlipParticleData = (std::vector<pData> *)pyObjectToPointer( + mFlipParticleData = (vector<pData> *)pyObjectToPointer( callPythonFunction("pp" + solver_ext, func)); - mFlipParticleVelocity = (std::vector<pVel> *)pyObjectToPointer( + mFlipParticleVelocity = (vector<pVel> *)pyObjectToPointer( callPythonFunction("pVel" + parts_ext, func)); } if (mUsingLiquid && mUsingMesh) { - mMeshNodes = (std::vector<Node> *)pyObjectToPointer( + mMeshNodes = (vector<Node> *)pyObjectToPointer( callPythonFunction("mesh" + mesh_ext, funcNodes)); - mMeshTriangles = (std::vector<Triangle> *)pyObjectToPointer( + mMeshTriangles = (vector<Triangle> *)pyObjectToPointer( callPythonFunction("mesh" + mesh_ext, funcTris)); } if (mUsingLiquid && mUsingMVel) { - mMeshVelocities = (std::vector<pVel> *)pyObjectToPointer( + mMeshVelocities = (vector<pVel> *)pyObjectToPointer( callPythonFunction("mVel" + mesh_ext2, func)); } if (mUsingLiquid && (mUsingDrops | mUsingBubbles | mUsingFloats | mUsingTracers)) { - mSndParticleData = (std::vector<pData> *)pyObjectToPointer( + mSndParticleData = (vector<pData> *)pyObjectToPointer( callPythonFunction("ppSnd" + snd_ext, func)); - mSndParticleVelocity = (std::vector<pVel> *)pyObjectToPointer( + mSndParticleVelocity = (vector<pVel> *)pyObjectToPointer( callPythonFunction("pVelSnd" + parts_ext, func)); - mSndParticleLife = (std::vector<float> *)pyObjectToPointer( + mSndParticleLife = (vector<float> *)pyObjectToPointer( callPythonFunction("pLifeSnd" + parts_ext, func)); } @@ -3249,21 +3082,21 @@ void MANTA::updatePointers() bool MANTA::hasConfig(FluidModifierData *mmd, int framenr) { - std::string extension = FLUID_DOMAIN_EXTENSION_UNI; + string extension = FLUID_DOMAIN_EXTENSION_UNI; return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, extension, framenr).c_str()); } bool MANTA::hasData(FluidModifierData *mmd, int framenr) { - std::string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PP; - std::string extension = getCacheFileEnding(mmd->domain->cache_data_format); + string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PP; + string extension = getCacheFileEnding(mmd->domain->cache_data_format); return BLI_exists(getFile(mmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str()); } bool MANTA::hasNoise(FluidModifierData *mmd, int framenr) { - std::string extension = getCacheFileEnding(mmd->domain->cache_noise_format); + string extension = getCacheFileEnding(mmd->domain->cache_noise_format); return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_DENSITYNOISE, extension, framenr) .c_str()); @@ -3271,14 +3104,14 @@ bool MANTA::hasNoise(FluidModifierData *mmd, int framenr) bool MANTA::hasMesh(FluidModifierData *mmd, int framenr) { - std::string extension = getCacheFileEnding(mmd->domain->cache_mesh_format); + string extension = getCacheFileEnding(mmd->domain->cache_mesh_format); return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, extension, framenr).c_str()); } bool MANTA::hasParticles(FluidModifierData *mmd, int framenr) { - std::string extension = getCacheFileEnding(mmd->domain->cache_particle_format); + string extension = getCacheFileEnding(mmd->domain->cache_particle_format); return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PPSND, extension, framenr) .c_str()); @@ -3286,13 +3119,13 @@ bool MANTA::hasParticles(FluidModifierData *mmd, int framenr) bool MANTA::hasGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) { - std::string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE; - std::string filename = (sourceDomain) ? FLUID_DOMAIN_FILE_VEL : FLUID_DOMAIN_FILE_GUIDEVEL; - std::string extension = getCacheFileEnding(mmd->domain->cache_data_format); + string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE; + string filename = (sourceDomain) ? FLUID_DOMAIN_FILE_VEL : FLUID_DOMAIN_FILE_GUIDEVEL; + string extension = getCacheFileEnding(mmd->domain->cache_data_format); return BLI_exists(getFile(mmd, subdirectory, filename, extension, framenr).c_str()); } -std::string MANTA::getDirectory(FluidModifierData *mmd, std::string subdirectory) +string MANTA::getDirectory(FluidModifierData *mmd, string subdirectory) { char directory[FILE_MAX]; BLI_path_join( @@ -3301,15 +3134,12 @@ std::string MANTA::getDirectory(FluidModifierData *mmd, std::string subdirectory return directory; } -std::string MANTA::getFile(FluidModifierData *mmd, - std::string subdirectory, - std::string fname, - std::string extension, - int framenr) +string MANTA::getFile( + FluidModifierData *mmd, string subdirectory, string fname, string extension, int framenr) { char targetFile[FILE_MAX]; - std::string path = getDirectory(mmd, subdirectory); - std::string filename = fname + extension; + string path = getDirectory(mmd, subdirectory); + string filename = fname + extension; BLI_join_dirfile(targetFile, sizeof(targetFile), path.c_str(), filename.c_str()); BLI_path_frame(targetFile, framenr, 0); return targetFile; diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h index 21946431f28..9b3fd6aa141 100644 --- a/intern/mantaflow/intern/MANTA_main.h +++ b/intern/mantaflow/intern/MANTA_main.h @@ -27,8 +27,14 @@ #include <atomic> #include <cassert> #include <string> +#include <unordered_map> #include <vector> +using std::atomic; +using std::string; +using std::unordered_map; +using std::vector; + struct MANTA { public: MANTA(int *res, struct FluidModifierData *mmd); @@ -58,20 +64,20 @@ struct MANTA { void step(struct FluidModifierData *mmd, int startFrame); // Grid initialization functions - void initHeat(struct FluidModifierData *mmd); - void initFire(struct FluidModifierData *mmd); - void initColors(struct FluidModifierData *mmd); - void initFireHigh(struct FluidModifierData *mmd); - void initColorsHigh(struct FluidModifierData *mmd); - void initLiquid(FluidModifierData *mmd); - void initLiquidMesh(FluidModifierData *mmd); - void initObstacle(FluidModifierData *mmd); - void initGuiding(FluidModifierData *mmd); - void initFractions(FluidModifierData *mmd); - void initInVelocity(FluidModifierData *mmd); - void initOutflow(FluidModifierData *mmd); - void initSndParts(FluidModifierData *mmd); - void initLiquidSndParts(FluidModifierData *mmd); + void initHeat(struct FluidModifierData *mmd = NULL); + void initFire(struct FluidModifierData *mmd = NULL); + void initColors(struct FluidModifierData *mmd = NULL); + void initFireHigh(struct FluidModifierData *mmd = NULL); + void initColorsHigh(struct FluidModifierData *mmd = NULL); + void initLiquid(FluidModifierData *mmd = NULL); + void initLiquidMesh(FluidModifierData *mmd = NULL); + void initObstacle(FluidModifierData *mmd = NULL); + void initGuiding(FluidModifierData *mmd = NULL); + void initFractions(FluidModifierData *mmd = NULL); + void initInVelocity(FluidModifierData *mmd = NULL); + void initOutflow(FluidModifierData *mmd = NULL); + void initSndParts(FluidModifierData *mmd = NULL); + void initLiquidSndParts(FluidModifierData *mmd = NULL); // Pointer transfer: Mantaflow -> Blender void updatePointers(); @@ -414,7 +420,7 @@ struct MANTA { return mPhi; } - static std::atomic<int> solverID; + static atomic<int> solverID; static int with_debug; // on or off (1 or 0), also sets manta debug level // Mesh getters @@ -741,6 +747,8 @@ struct MANTA { size_t mTotalCellsMesh; size_t mTotalCellsParticles; + unordered_map<string, string> mRNAMap; + int mCurrentID; bool mUsingHeat; @@ -852,45 +860,46 @@ struct MANTA { float *mPhi; // Mesh fields - std::vector<Node> *mMeshNodes; - std::vector<Triangle> *mMeshTriangles; - std::vector<pVel> *mMeshVelocities; + vector<Node> *mMeshNodes; + vector<Triangle> *mMeshTriangles; + vector<pVel> *mMeshVelocities; // Particle fields - std::vector<pData> *mFlipParticleData; - std::vector<pVel> *mFlipParticleVelocity; - - std::vector<pData> *mSndParticleData; - std::vector<pVel> *mSndParticleVelocity; - std::vector<float> *mSndParticleLife; - - void initDomain(struct FluidModifierData *mmd); - void initNoise(struct FluidModifierData *mmd); - void initMesh(struct FluidModifierData *mmd); - void initSmoke(struct FluidModifierData *mmd); - void initSmokeNoise(struct FluidModifierData *mmd); + vector<pData> *mFlipParticleData; + vector<pVel> *mFlipParticleVelocity; + + vector<pData> *mSndParticleData; + vector<pVel> *mSndParticleVelocity; + vector<float> *mSndParticleLife; + + void initializeRNAMap(struct FluidModifierData *mmd = NULL); + void initDomain(struct FluidModifierData *mmd = NULL); + void initNoise(struct FluidModifierData *mmd = NULL); + void initMesh(struct FluidModifierData *mmd = NULL); + void initSmoke(struct FluidModifierData *mmd = NULL); + void initSmokeNoise(struct FluidModifierData *mmd = NULL); void initializeMantaflow(); void terminateMantaflow(); - bool runPythonString(std::vector<std::string> commands); - std::string getRealValue(const std::string &varName, FluidModifierData *mmd); - std::string parseLine(const std::string &line, FluidModifierData *mmd); - std::string parseScript(const std::string &setup_string, FluidModifierData *mmd = NULL); - bool updateMeshFromBobj(std::string filename); - bool updateMeshFromObj(std::string filename); - bool updateMeshFromUni(std::string filename); - bool updateParticlesFromUni(std::string filename, bool isSecondarySys, bool isVelData); - bool updateGridFromUni(std::string filename, float *grid, bool isNoise); - bool updateGridFromVDB(std::string filename, float *grid, bool isNoise); - bool updateGridFromRaw(std::string filename, float *grid, bool isNoise); - bool updateMeshFromFile(std::string filename); - bool updateParticlesFromFile(std::string filename, bool isSecondarySys, bool isVelData); - bool updateGridFromFile(std::string filename, float *grid, bool isNoise); - std::string getDirectory(struct FluidModifierData *mmd, std::string subdirectory); - std::string getFile(struct FluidModifierData *mmd, - std::string subdirectory, - std::string fname, - std::string extension, - int framenr); + bool runPythonString(vector<string> commands); + string getRealValue(const string &varName); + string parseLine(const string &line); + string parseScript(const string &setup_string, FluidModifierData *mmd = NULL); + bool updateMeshFromBobj(string filename); + bool updateMeshFromObj(string filename); + bool updateMeshFromUni(string filename); + bool updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData); + bool updateGridFromUni(string filename, float *grid, bool isNoise); + bool updateGridFromVDB(string filename, float *grid, bool isNoise); + bool updateGridFromRaw(string filename, float *grid, bool isNoise); + bool updateMeshFromFile(string filename); + bool updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData); + bool updateGridFromFile(string filename, float *grid, bool isNoise); + string getDirectory(struct FluidModifierData *mmd, string subdirectory); + string getFile(struct FluidModifierData *mmd, + string subdirectory, + string fname, + string extension, + int framenr); }; #endif diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h index dd2111db7d7..922e591c001 100644 --- a/intern/mantaflow/intern/strings/fluid_script.h +++ b/intern/mantaflow/intern/strings/fluid_script.h @@ -92,7 +92,7 @@ const std::string fluid_variables = mantaMsg('Fluid variables')\n\ dim_s$ID$ = $SOLVER_DIM$\n\ res_s$ID$ = $RES$\n\ -gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$)\n\ +gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$) # in SI unit (e.g. m/s^2)\n\ gs_s$ID$ = vec3($RESX$, $RESY$, $RESZ$)\n\ maxVel_s$ID$ = 0\n\ \n\ @@ -115,9 +115,16 @@ using_speedvectors_s$ID$ = $USING_SPEEDVECTORS$\n\ using_diffusion_s$ID$ = $USING_DIFFUSION$\n\ \n\ # Fluid time params\n\ +timeScale_s$ID$ = $TIME_SCALE$\n\ timeTotal_s$ID$ = $TIME_TOTAL$\n\ timePerFrame_s$ID$ = $TIME_PER_FRAME$\n\ -frameLength_s$ID$ = $FRAME_LENGTH$\n\ +\n\ +# In Blender fluid.c: frame_length = DT_DEFAULT * (25.0 / fps) * time_scale\n\ +# with DT_DEFAULT = 0.1\n\ +frameLength_s$ID$ = $FRAME_LENGTH$\n\ +frameLengthUnscaled_s$ID$ = frameLength_s$ID$ / timeScale_s$ID$\n\ +frameLengthRaw_s$ID$ = 0.1 * 25 # dt = 0.1 at 25 fps\n\ +\n\ dt0_s$ID$ = $DT$\n\ cflCond_s$ID$ = $CFL$\n\ timestepsMin_s$ID$ = $TIMESTEPS_MIN$\n\ @@ -132,8 +139,29 @@ end_frame_s$ID$ = $END_FRAME$\n\ domainSize_s$ID$ = $FLUID_DOMAIN_SIZE$ # longest domain side in meters\n\ viscosity_s$ID$ = $FLUID_VISCOSITY$ / (domainSize_s$ID$*domainSize_s$ID$) # kinematic viscosity in m^2/s\n\ \n\ -# Factor to convert blender velocities to manta velocities\n\ -toMantaUnitsFac_s$ID$ = (1.0 / (1.0 / res_s$ID$))\n # = dt/dx * 1/dt "; +# Factors to convert Blender units to Manta units\n\ +ratioMetersToRes_s$ID$ = float(domainSize_s$ID$) / float(res_s$ID$) # [meters / cells]\n\ +mantaMsg('1 Mantaflow cell is ' + str(ratioMetersToRes_s$ID$) + ' Blender length units long.')\n\ +\n\ +ratioResToBLength_s$ID$ = float(res_s$ID$) / float(domainSize_s$ID$) # [cells / blength] (blength: cm, m, or km, ... )\n\ +mantaMsg('1 Blender length unit is ' + str(ratioResToBLength_s$ID$) + ' Mantaflow cells long.')\n\ +\n\ +ratioBTimeToTimstep_s$ID$ = float(1) / float(frameLengthRaw_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\ +mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimstep_s$ID$) + ' Mantaflow time units long.')\n\ +\n\ +ratioFrameToFramelength_s$ID$ = float(1) / float(frameLengthUnscaled_s$ID$ ) # the time within 1 frame\n\ +mantaMsg('frame / frameLength is ' + str(ratioFrameToFramelength_s$ID$) + ' Mantaflow time units long.')\n\ +\n\ +scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimstep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\ +mantaMsg('scaleAcceleration is ' + str(scaleAcceleration_s$ID$))\n\ +\n\ +scaleSpeedFrames_s$ID$ = ratioResToBLength_s$ID$ * ratioFrameToFramelength_s$ID$ # [blength/frame] to [cells/frameLength]\n\ +mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\ +\n\ +scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimstep_s$ID$ # [blength/btime] to [cells/frameLength]\n\ +mantaMsg('scaleSpeedTime is ' + str(scaleSpeedTime_s$ID$))\n\ +\n\ +gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n"; const std::string fluid_variables_noise = "\n\ @@ -342,17 +370,16 @@ def fluid_pre_step_$ID$():\n\ y_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\ z_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\ \n\ - x_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - y_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - z_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - \n\ + x_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + y_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + z_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ copyRealToVec3(sourceX=x_obvel_s$ID$, sourceY=y_obvel_s$ID$, sourceZ=z_obvel_s$ID$, target=obvelC_s$ID$)\n\ \n\ # translate invels (world space) to grid space\n\ if using_invel_s$ID$:\n\ - x_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - y_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - z_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ + x_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\ + y_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\ + z_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\ copyRealToVec3(sourceX=x_invel_s$ID$, sourceY=y_invel_s$ID$, sourceZ=z_invel_s$ID$, target=invelC_s$ID$)\n\ \n\ if using_guiding_s$ID$:\n\ @@ -362,9 +389,9 @@ def fluid_pre_step_$ID$():\n\ velT_s$ID$.multConst(vec3(gamma_sg$ID$))\n\ \n\ # translate external forces (world space) to grid space\n\ - x_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - y_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - z_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ + x_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + y_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + z_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ copyRealToVec3(sourceX=x_force_s$ID$, sourceY=y_force_s$ID$, sourceZ=z_force_s$ID$, target=forces_s$ID$)\n\ \n\ # If obstacle has velocity, i.e. is a moving obstacle, switch to dynamic preconditioner\n\ @@ -531,7 +558,7 @@ def bake_noise_process_$ID$(framenr, format_data, format_noise, path_data, path_ \n\ sn$ID$.frame = framenr\n\ sn$ID$.frameLength = frameLength_s$ID$\n\ - sn$ID$.timeTotal = abs(framenr - start_frame_s$ID$) * frameLength_s$ID$\n\ + sn$ID$.timeTotal = timeTotal_s$ID$\n\ sn$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for noise\n\ \n\ smoke_step_noise_$ID$(framenr)\n\ @@ -549,7 +576,7 @@ def bake_mesh_process_$ID$(framenr, format_data, format_mesh, format_particles, \n\ sm$ID$.frame = framenr\n\ sm$ID$.frameLength = frameLength_s$ID$\n\ - sm$ID$.timeTotal = abs(framenr - start_frame_s$ID$) * frameLength_s$ID$\n\ + sm$ID$.timeTotal = timeTotal_s$ID$\n\ sm$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for mesh\n\ \n\ #if using_smoke_s$ID$:\n\ @@ -573,7 +600,7 @@ def bake_particles_process_$ID$(framenr, format_data, format_particles, path_dat \n\ sp$ID$.frame = framenr\n\ sp$ID$.frameLength = frameLength_s$ID$\n\ - sp$ID$.timeTotal = abs(framenr - start_frame_s$ID$) * frameLength_s$ID$\n\ + sp$ID$.timeTotal = timeTotal_s$ID$\n\ sp$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for particles\n\ \n\ #if using_smoke_s$ID$:\n\ @@ -598,10 +625,9 @@ def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable): y_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\ z_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\ \n\ - x_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\ - y_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\ - z_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\ - \n\ + x_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + y_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + z_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ copyRealToVec3(sourceX=x_guidevel_s$ID$, sourceY=y_guidevel_s$ID$, sourceZ=z_guidevel_s$ID$, target=guidevelC_s$ID$)\n\ \n\ mantaMsg('Extrapolating guiding velocity')\n\ diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h index f20b218427c..cdacea16953 100644 --- a/intern/mantaflow/intern/strings/liquid_script.h +++ b/intern/mantaflow/intern/strings/liquid_script.h @@ -68,7 +68,7 @@ c_s_sp$ID$ = 0.4 # classification constant for snd parts\n\ c_b_sp$ID$ = 0.77 # classification constant for snd parts\n\ pot_radius_sp$ID$ = $SNDPARTICLE_POTENTIAL_RADIUS$\n\ update_radius_sp$ID$ = $SNDPARTICLE_UPDATE_RADIUS$\n\ -scaleFromManta_sp$ID$ = $FLUID_DOMAIN_SIZE$ / float(res_s$ID$) # resize factor for snd parts\n"; +using_snd_pushout_sp$ID$ = $SNDPARTICLE_BOUNDARY_PUSHOUT$\n"; ////////////////////////////////////////////////////////////////////// // GRIDS & MESH & PARTICLESYSTEM @@ -263,7 +263,7 @@ def liquid_step_$ID$():\n\ velOld_s$ID$.copyFrom(vel_s$ID$)\n\ \n\ # forces & pressure solve\n\ - addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$)\n\ + addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, scale=False)\n\ \n\ mantaMsg('Adding external forces')\n\ addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\ @@ -371,10 +371,10 @@ def liquid_step_particles_$ID$():\n\ flags_sp$ID$.updateFromLevelset(levelset=phi_sp$ID$)\n\ \n\ # Actual secondary particle simulation\n\ - flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=scaleFromManta_sp$ID$)\n\ - flipSampleSecondaryParticles(mode='single', flags=flags_sp$ID$, v=vel_sp$ID$, pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, lMin=lMin_sp$ID$, lMax=lMax_sp$ID$, potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, k_ta=k_ta_sp$ID$, k_wc=k_wc_sp$ID$, dt=sp$ID$.timestep)\n\ - flipUpdateSecondaryParticles(mode='linear', pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, f_sec=pForceSnd_pp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, neighborRatio=neighborRatio_sp$ID$, radius=update_radius_sp$ID$, gravity=gravity_s$ID$, k_b=k_b_sp$ID$, k_d=k_d_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, dt=sp$ID$.timestep)\n\ - if $SNDPARTICLE_BOUNDARY_PUSHOUT$:\n\ + flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=ratioMetersToRes_s$ID$)\n\ + flipSampleSecondaryParticles(mode='single', flags=flags_sp$ID$, v=vel_sp$ID$, pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, lMin=lMin_sp$ID$, lMax=lMax_sp$ID$, potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, k_ta=k_ta_sp$ID$, k_wc=k_wc_sp$ID$)\n\ + flipUpdateSecondaryParticles(mode='linear', pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, f_sec=pForceSnd_pp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, neighborRatio=neighborRatio_sp$ID$, radius=update_radius_sp$ID$, gravity=gravity_s$ID$, scale=False, k_b=k_b_sp$ID$, k_d=k_d_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$)\n\ + if using_snd_pushout_sp$ID$:\n\ pushOutofObs(parts=ppSnd_sp$ID$, flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, shift=1.0)\n\ flipDeleteParticlesInObstacle(pts=ppSnd_sp$ID$, flags=flags_sp$ID$) # delete particles inside obstacle and outflow cells\n\ \n\ diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h index fdb58543cec..ea2b1e9d848 100644 --- a/intern/mantaflow/intern/strings/smoke_script.h +++ b/intern/mantaflow/intern/strings/smoke_script.h @@ -376,9 +376,9 @@ def smoke_step_$ID$():\n\ \n\ if using_heat_s$ID$:\n\ mantaMsg('Adding heat buoyancy')\n\ - addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$)\n\ + addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$, scale=False)\n\ mantaMsg('Adding buoyancy')\n\ - addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$)\n\ + addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$, scale=False)\n\ \n\ mantaMsg('Adding forces')\n\ addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\ diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h index 690763a14f0..2bbbfb75555 100644 --- a/intern/memutil/MEM_CacheLimiterC-Api.h +++ b/intern/memutil/MEM_CacheLimiterC-Api.h @@ -56,8 +56,8 @@ bool MEM_CacheLimiter_is_disabled(void); * Create new MEM_CacheLimiter object * managed objects are destructed with the data_destructor * - * \param data_destructor - * \return A new MEM_CacheLimter object + * \param data_destructor: TODO. + * \return A new #MEM_CacheLimter object. */ MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_destructor, @@ -68,7 +68,7 @@ MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_dest * * Frees the memory of the CacheLimiter but does not touch managed objects! * - * \param This "This" pointer + * \param This: "This" pointer. */ void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This); @@ -76,7 +76,7 @@ void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This); /** * Manage object * - * \param This "This" pointer, data data object to manage + * \param This: "This" pointer, data data object to manage. * \return CacheLimiterHandle to ref, unref, touch the managed object */ @@ -85,7 +85,7 @@ MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void * /** * Free objects until memory constraints are satisfied * - * \param This "This" pointer + * \param This: "This" pointer. */ void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This); @@ -94,7 +94,7 @@ void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This); * Unmanage object previously inserted object. * Does _not_ delete managed object! * - * \param handle of object + * \param handle: of object. */ void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle); @@ -102,7 +102,7 @@ void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle); /** * Raise priority of object (put it at the tail of the deletion chain) * - * \param handle of object + * \param handle: of object. */ void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle); @@ -111,7 +111,7 @@ void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle); * Increment reference counter. Objects with reference counter != 0 are _not_ * deleted. * - * \param handle of object + * \param handle: of object. */ void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle); @@ -120,7 +120,7 @@ void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle); * Decrement reference counter. Objects with reference counter != 0 are _not_ * deleted. * - * \param handle of object + * \param handle: of object. */ void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle); @@ -128,7 +128,7 @@ void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle); /** * Get reference counter. * - * \param handle of object + * \param handle: of object. */ int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle); @@ -136,7 +136,7 @@ int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle); /** * Get pointer to managed object * - * \param handle of object + * \param handle: of object. */ void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle); diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp index a928aaca049..a8bf1420523 100644 --- a/intern/rigidbody/rb_bullet_api.cpp +++ b/intern/rigidbody/rb_bullet_api.cpp @@ -218,8 +218,8 @@ void RB_dworld_step_simulation(rbDynamicsWorld *world, * Exports entire dynamics world to Bullet's "*.bullet" binary format * which is similar to Blender's SDNA system. * - * \param world Dynamics world to write to file - * \param filename Assumed to be a valid filename, with .bullet extension + * \param world: Dynamics world to write to file + * \param filename: Assumed to be a valid filename, with .bullet extension */ void RB_dworld_export(rbDynamicsWorld *world, const char *filename) { diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h deleted file mode 100644 index 97b23345f91..00000000000 --- a/intern/string/STR_String.h +++ /dev/null @@ -1,366 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - */ - -/** \file - * \ingroup string - */ - -#ifndef __STR_STRING_H__ -#define __STR_STRING_H__ - -#ifndef STR_NO_ASSERTD -# undef assertd -# define assertd(exp) ((void)NULL) -#endif - -#include <limits.h> -#include <vector> - -#include <cstdlib> -#include <cstring> - -#ifdef WITH_CXX_GUARDEDALLOC -# include "MEM_guardedalloc.h" -#endif - -#ifdef _WIN32 -# define stricmp _stricmp -#endif - -class STR_String; - -typedef unsigned long dword; -typedef const STR_String &rcSTR_String; -typedef unsigned char byte; - -/** - * Smart String Value class. Is used by parser when an expression tree is build containing string. - */ - -class STR_String { - public: - // Initialization - STR_String(); - STR_String(char c); - STR_String(char c, int len); - STR_String(const char *str); - STR_String(const char *str, int len); - STR_String(const STR_String &str); - STR_String(const STR_String &str, int len); - STR_String(const char *src1, int src1_len, const char *src2, int src2_len); - explicit STR_String(int val); - explicit STR_String(dword val); - explicit STR_String(float val); - explicit STR_String(double val); - inline ~STR_String() - { - delete[] this->m_data; - } - - // Operations - STR_String &Format(const char *fmt, ...) // Set formatted text to string -#ifdef __GNUC__ - __attribute__((format(printf, 2, 3))) -#endif - ; - STR_String &FormatAdd(const char *fmt, ...) // Add formatted text to string -#ifdef __GNUC__ - __attribute__((format(printf, 2, 3))) -#endif - ; - inline void Clear() - { - this->m_len = this->m_data[0] = 0; - } - inline const STR_String &Reverse() - { - for (int i1 = 0, i2 = this->m_len - 1; i1 < i2; i1++, i2--) { - std::swap(this->m_data[i1], this->m_data[i2]); - } - return *this; - } - - // Properties - bool IsUpper() const; - bool IsLower() const; - inline bool IsEmpty() const - { - return this->m_len == 0; - } - inline int Length() const - { - return this->m_len; - } - - // Data access - inline STR_String &SetLength(int len) - { - AllocBuffer(len, true); - this->m_len = len; - this->m_data[len] = 0; - return *this; - } - inline char GetAt(int pos) const - { - assertd(pos < this->m_len); - return this->m_data[pos]; - } - inline void SetAt(int pos, char c) - { - assertd(pos < this->m_len); - this->m_data[pos] = c; - } - inline void SetAt(int pos, rcSTR_String str); - inline void SetAt(int pos, int num, rcSTR_String str); - void Replace(int pos, rcSTR_String str); - void Replace(int pos, int num, rcSTR_String str); - - // Substrings - inline STR_String Left(int num) const - { - num = (num < this->m_len ? num : this->m_len); - return STR_String(this->m_data, num); - } - inline STR_String Right(int num) const - { - num = (num < this->m_len ? num : this->m_len); - return STR_String(this->m_data + this->m_len - num, num); - } - inline STR_String Mid(int pos, int num = INT_MAX) const - { - pos = (pos < this->m_len ? pos : this->m_len); - num = (num < (this->m_len - pos) ? num : (this->m_len - pos)); - return STR_String(this->m_data + pos, num); - } - - // Comparison - int Compare(rcSTR_String rhs) const; - int CompareNoCase(rcSTR_String rhs) const; - inline bool IsEqual(rcSTR_String rhs) const - { - return (Compare(rhs) == 0); - } - inline bool IsEqualNoCase(rcSTR_String rhs) const - { - return (CompareNoCase(rhs) == 0); - } - - // Search/replace - int Find(char c, int pos = 0) const; - int Find(const char *str, int pos = 0) const; - int Find(rcSTR_String str, int pos = 0) const; - int RFind(char c) const; - int FindOneOf(const char *set, int pos = 0) const; - int RFindOneOf(const char *set, int pos = 0) const; - - std::vector<STR_String> Explode(char c) const; - - // Formatting - STR_String &Upper(); - STR_String &Lower(); - STR_String &Capitalize(); - STR_String &TrimLeft(); - STR_String &TrimLeft(char *set); - STR_String &TrimRight(); - STR_String &TrimRight(char *set); - STR_String &Trim(); - STR_String &Trim(char *set); - STR_String &TrimQuotes(); - - // Conversions - // inline operator char*() { return this->m_data; } - inline operator const char *() const - { - return this->m_data; - } - inline char *Ptr() - { - return this->m_data; - } - inline const char *ReadPtr() const - { - return this->m_data; - } - inline float ToFloat() const - { - float x = (float)(atof(this->m_data)); - return x; - } - inline int ToInt() const - { - return atoi(this->m_data); - } - - // Operators - inline rcSTR_String operator=(const byte *rhs) - { - return Copy((const char *)rhs, strlen((const char *)rhs)); - } - inline rcSTR_String operator=(rcSTR_String rhs) - { - return Copy(rhs.ReadPtr(), rhs.Length()); - } - inline rcSTR_String operator=(char rhs) - { - return Copy(&rhs, 1); - } - inline rcSTR_String operator=(const char *rhs) - { - return Copy(rhs, strlen(rhs)); - } - - inline rcSTR_String operator+=(const char *rhs) - { - return Concat(rhs, strlen(rhs)); - } - inline rcSTR_String operator+=(rcSTR_String rhs) - { - return Concat(rhs.ReadPtr(), rhs.Length()); - } - inline rcSTR_String operator+=(char rhs) - { - return Concat(&rhs, 1); - } - - inline friend bool operator<(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) < 0); - } - inline friend bool operator<(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) < 0); - } - inline friend bool operator<(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) < 0); - } - inline friend bool operator>(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) > 0); - } - inline friend bool operator>(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) > 0); - } - inline friend bool operator>(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) > 0); - } - inline friend bool operator<=(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) <= 0); - } - inline friend bool operator<=(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) <= 0); - } - inline friend bool operator<=(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) <= 0); - } - inline friend bool operator>=(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) >= 0); - } - inline friend bool operator>=(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) >= 0); - } - inline friend bool operator>=(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) >= 0); - } - inline friend bool operator==(rcSTR_String lhs, rcSTR_String rhs) - { - return ((lhs.Length() == rhs.Length()) && (memcmp(lhs, rhs, lhs.Length()) == 0)); - } - inline friend bool operator==(rcSTR_String lhs, const char *rhs) - { - return (strncmp(lhs, rhs, lhs.Length() + 1) == 0); - } - inline friend bool operator==(const char *lhs, rcSTR_String rhs) - { - return (strncmp(lhs, rhs, rhs.Length() + 1) == 0); - } - inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs) - { - return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length()) != 0)); - } - inline friend bool operator!=(rcSTR_String lhs, const char *rhs) - { - return (strncmp(lhs, rhs, lhs.Length() + 1) != 0); - } - inline friend bool operator!=(const char *lhs, rcSTR_String rhs) - { - return (strncmp(lhs, rhs, rhs.Length() + 1) != 0); - } - - // serializing - // int Serialize(pCStream stream); - - protected: - // Implementation - void AllocBuffer(int len, bool keep_contents); - rcSTR_String Copy(const char *src, int len); - rcSTR_String Concat(const char *data, int len); - - static bool isLower(char c) - { - return !isUpper(c); - } - static bool isUpper(char c) - { - return (c >= 'A') && (c <= 'Z'); - } - static bool isSpace(char c) - { - return (c == ' ') || (c == '\t'); - } - - char *m_data; // -> STR_String data - int m_len; // z Data length - int m_max; // Space in data buffer - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("CXX:STR_String") -#endif -}; - -inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) -{ - return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); -} -inline STR_String operator+(rcSTR_String lhs, char rhs) -{ - return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); -} -inline STR_String operator+(char lhs, rcSTR_String rhs) -{ - return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); -} -inline STR_String operator+(rcSTR_String lhs, const char *rhs) -{ - return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); -} -inline STR_String operator+(const char *lhs, rcSTR_String rhs) -{ - return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); -} - -#endif //__STR_STRING_H__ diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp deleted file mode 100644 index 306e786969b..00000000000 --- a/intern/string/intern/STR_String.cpp +++ /dev/null @@ -1,637 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - */ - -/** \file - * \ingroup string - * - * Copyright (C) 2001 NaN Technologies B.V. - * This file was formerly known as: GEN_StdString.cpp. - */ - -#include "STR_String.h" -#include <ctype.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/*------------------------------------------------------------------------------------------------- - Construction / destruction --------------------------------------------------------------------------------------------------*/ - -#define STR_STRING_SIZE_DEFAULT_WORD 32 /* default size for a new word */ -#define STR_STRING_SIZE_DEFAULT_CHAR 9 /* default size for a new char */ - -// -// Construct an empty string -// -STR_String::STR_String() - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_len(0), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - this->m_data[0] = 0; -} - -// -// Construct a string of one character -// -STR_String::STR_String(char c) - : m_data(new char[STR_STRING_SIZE_DEFAULT_CHAR]), m_len(1), m_max(STR_STRING_SIZE_DEFAULT_CHAR) -{ - this->m_data[0] = c; - this->m_data[1] = 0; -} - -// -// Construct a string of multiple repeating characters -// -STR_String::STR_String(char c, int len) : m_data(new char[len + 8]), m_len(len), m_max(len + 8) -{ - assertd(this->m_data != NULL); - memset(this->m_data, c, len); - this->m_data[len] = 0; -} - -// -// Construct a string from a pointer-to-ASCIIZ-string -// -// MAART: Changed to test for null strings -STR_String::STR_String(const char *str) -{ - if (str) { - this->m_len = ::strlen(str); - this->m_max = this->m_len + 8; - this->m_data = new char[this->m_max]; - assertd(this->m_data != NULL); - ::memcpy(this->m_data, str, this->m_len); - this->m_data[this->m_len] = 0; - } - else { - this->m_data = NULL; - this->m_len = 0; - this->m_max = 8; - } -} - -// -// Construct a string from a pointer-to-ASCII-string and a length -// -STR_String::STR_String(const char *str, int len) - : m_data(new char[len + 8]), m_len(len), m_max(len + 8) -{ - assertd(this->m_data != NULL); - memcpy(this->m_data, str, len); - this->m_data[len] = 0; -} - -// -// Construct a string from another string -// -STR_String::STR_String(rcSTR_String str) - : m_data(new char[str.Length() + 8]), m_len(str.Length()), m_max(str.Length() + 8) -{ - assertd(this->m_data != NULL); - assertd(str.this->m_data != NULL); - memcpy(this->m_data, str.ReadPtr(), str.Length()); - this->m_data[str.Length()] = 0; -} - -// -// Construct a string from the first number of characters in another string -// -STR_String::STR_String(rcSTR_String str, int len) - : m_data(new char[len + 8]), m_len(len), m_max(len + 8) -{ - assertd(this->m_data != NULL); - assertd(str.this->m_data != NULL); - memcpy(this->m_data, str.ReadPtr(), str.Length()); - this->m_data[str.Length()] = 0; -} - -// -// Create a string by concatenating two sources -// -STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) - : m_data(new char[len1 + len2 + 8]), m_len(len1 + len2), m_max(len1 + len2 + 8) -{ - assertd(this->m_data != NULL); - memcpy(this->m_data, src1, len1); - memcpy(this->m_data + len1, src2, len2); - this->m_data[len1 + len2] = 0; -} - -// -// Create a string with an integer value -// -STR_String::STR_String(int val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%d", val); -} - -// -// Create a string with a dword value -// -STR_String::STR_String(dword val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%lu", val); -} - -// -// Create a string with a floating point value -// -STR_String::STR_String(float val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%g", val); -} - -// -// Create a string with a double value -// -STR_String::STR_String(double val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%g", val); -} - -/*------------------------------------------------------------------------------------------------- - Buffer management --------------------------------------------------------------------------------------------------*/ - -// -// Make sure that the allocated buffer is at least <len> in size -// -void STR_String::AllocBuffer(int len, bool keep_contents) -{ - // Check if we have enough space - if (len + 1 <= this->m_max) - return; - - // Reallocate string - char *new_data = new char[len + 8]; - if (keep_contents) { - memcpy(new_data, this->m_data, this->m_len); - } - delete[] this->m_data; - - // Accept new data - this->m_max = len + 8; - this->m_data = new_data; - assertd(this->m_data != NULL); -} - -/*------------------------------------------------------------------------------------------------- - Basic string operations --------------------------------------------------------------------------------------------------*/ - -// -// Format string (as does sprintf) -// -STR_String &STR_String::Format(const char *fmt, ...) -{ - AllocBuffer(2048, false); - - assertd(this->m_data != NULL); - // Expand arguments and format to string - va_list args; - va_start(args, fmt); - this->m_len = vsprintf(this->m_data, fmt, args); - assertd(this->m_len <= 2048); - va_end(args); - - return *this; -} - -// -// Format string (as does sprintf) -// -STR_String &STR_String::FormatAdd(const char *fmt, ...) -{ - AllocBuffer(2048, false); - - assertd(this->m_data != NULL); - // Expand arguments and format to string - va_list args; - va_start(args, fmt); - this->m_len += vsprintf(this->m_data + this->m_len, fmt, args); - assertd(this->m_len <= 2048); - va_end(args); - - return *this; -} - -/*------------------------------------------------------------------------------------------------- - Properties --------------------------------------------------------------------------------------------------*/ - -// -// Check if string is entirely in UPPERCase -// -bool STR_String::IsUpper() const -{ - for (int i = 0; i < this->m_len; i++) - if (isLower(this->m_data[i])) - return false; - - return true; -} - -// -// Check if string is entirely in lowerCase -// -bool STR_String::IsLower() const -{ - for (int i = 0; i < this->m_len; i++) - if (isUpper(this->m_data[i])) - return false; - - return true; -} - -/*------------------------------------------------------------------------------------------------- - Search/Replace --------------------------------------------------------------------------------------------------*/ - -// -// Find the first orccurence of <c> in the string -// -int STR_String::Find(char c, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strchr(this->m_data + pos, c); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Find the first occurrence of <str> in the string -// -int STR_String::Find(const char *str, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strstr(this->m_data + pos, str); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Find the first occurrence of <str> in the string -// -int STR_String::Find(rcSTR_String str, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strstr(this->m_data + pos, str.ReadPtr()); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Find the last occurrence of <c> in the string -// -int STR_String::RFind(char c) const -{ - assertd(this->m_data != NULL); - char *pos = strrchr(this->m_data, c); - return (pos) ? (pos - this->m_data) : -1; -} - -// -// Find the first occurrence of any character in character set <set> in the string -// -int STR_String::FindOneOf(const char *set, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strpbrk(this->m_data + pos, set); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Replace a character in this string with another string -// -void STR_String::Replace(int pos, rcSTR_String str) -{ - // bounds(pos, 0, Length()-1); - - if (str.Length() < 1) { - // Remove one character from the string - memcpy(this->m_data + pos, this->m_data + pos + 1, this->m_len - pos); - } - else { - // Insert zero or more characters into the string - AllocBuffer(this->m_len + str.Length() - 1, true); - if (str.Length() != 1) - memcpy(this->m_data + pos + str.Length(), this->m_data + pos + 1, Length() - pos); - memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); - } - - this->m_len += str.Length() - 1; -} - -// -// Replace a substring of this string with another string -// -void STR_String::Replace(int pos, int num, rcSTR_String str) -{ - // bounds(pos, 0, Length()-1); - // bounds(pos+num, 0, Length()); - assertd(num >= 1); - - if (str.Length() < num) { - // Remove some data from the string by replacement - memcpy( - this->m_data + pos + str.Length(), this->m_data + pos + num, this->m_len - pos - num + 1); - memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); - } - else { - // Insert zero or more characters into the string - AllocBuffer(this->m_len + str.Length() - num, true); - if (str.Length() != num) - memcpy( - this->m_data + pos + str.Length(), this->m_data + pos + num, Length() - pos - num + 1); - memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); - } - - this->m_len += str.Length() - num; -} - -/*------------------------------------------------------------------------------------------------- - Comparison --------------------------------------------------------------------------------------------------*/ - -// -// Compare two strings and return the result, -// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs -// -int STR_String::Compare(rcSTR_String rhs) const -{ - return strcmp(this->ReadPtr(), rhs.ReadPtr()); -} - -// -// Compare two strings without respecting case and return the result, -// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs -// -int STR_String::CompareNoCase(rcSTR_String rhs) const -{ -#ifdef WIN32 - return stricmp(this->ReadPtr(), rhs.ReadPtr()); -#else - return strcasecmp(this->ReadPtr(), rhs.ReadPtr()); -#endif -} - -/*------------------------------------------------------------------------------------------------- - Formatting --------------------------------------------------------------------------------------------------*/ - -// -// Capitalize string, "heLLo" -> "HELLO" -// -STR_String &STR_String::Upper() -{ - assertd(this->m_data != NULL); -#ifdef WIN32 - _strupr(this->m_data); -#else - for (int i = 0; i < this->m_len; i++) - this->m_data[i] = (this->m_data[i] >= 'a' && this->m_data[i] <= 'z') ? - this->m_data[i] + 'A' - 'a' : - this->m_data[i]; -#endif - return *this; -} - -// -// Lower string, "heLLo" -> "hello" -// -STR_String &STR_String::Lower() -{ - assertd(this->m_data != NULL); -#ifdef WIN32 - _strlwr(this->m_data); -#else - for (int i = 0; i < this->m_len; i++) - this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ? - this->m_data[i] + 'a' - 'A' : - this->m_data[i]; -#endif - return *this; -} - -// -// Capitalize string, "heLLo" -> "Hello" -// -STR_String &STR_String::Capitalize() -{ - assertd(this->m_data != NULL); -#ifdef WIN32 - if (this->m_len > 0) - this->m_data[0] = toupper(this->m_data[0]); - if (this->m_len > 1) - _strlwr(this->m_data + 1); -#else - if (this->m_len > 0) - this->m_data[0] = (this->m_data[0] >= 'a' && this->m_data[0] <= 'z') ? - this->m_data[0] + 'A' - 'a' : - this->m_data[0]; - for (int i = 1; i < this->m_len; i++) - this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ? - this->m_data[i] + 'a' - 'A' : - this->m_data[i]; -#endif - return *this; -} - -// -// Trim whitespace from the left side of the string -// -STR_String &STR_String::TrimLeft() -{ - int skip; - assertd(this->m_data != NULL); - for (skip = 0; isSpace(this->m_data[skip]); skip++, this->m_len--) { - /* pass */ - } - memmove(this->m_data, this->m_data + skip, this->m_len + 1); - return *this; -} - -// -// Trim whitespaces from the right side of the string -// -STR_String &STR_String::TrimRight() -{ - assertd(this->m_data != NULL); - while (this->m_len && isSpace(this->m_data[this->m_len - 1])) - this->m_len--; - this->m_data[this->m_len] = 0; - return *this; -} - -// -// Trim spaces from both sides of the character set -// -STR_String &STR_String::Trim() -{ - TrimRight(); - TrimLeft(); - return *this; -} - -// -// Trim characters from the character set <set> from the left side of the string -// -STR_String &STR_String::TrimLeft(char *set) -{ - int skip; - assertd(this->m_data != NULL); - for (skip = 0; this->m_len && strchr(set, this->m_data[skip]); skip++, this->m_len--) { - /* pass */ - } - memmove(this->m_data, this->m_data + skip, this->m_len + 1); - return *this; -} - -// -// Trim characters from the character set <set> from the right side of the string -// -STR_String &STR_String::TrimRight(char *set) -{ - assertd(this->m_data != NULL); - while (this->m_len && strchr(set, this->m_data[this->m_len - 1])) - this->m_len--; - this->m_data[this->m_len] = 0; - return *this; -} - -// -// Trim characters from the character set <set> from both sides of the character set -// -STR_String &STR_String::Trim(char *set) -{ - TrimRight(set); - TrimLeft(set); - return *this; -} - -// -// Trim quotes from both sides of the string -// -STR_String &STR_String::TrimQuotes() -{ - // Trim quotes if they are on both sides of the string - assertd(this->m_data != NULL); - if ((this->m_len >= 2) && (this->m_data[0] == '\"') && (this->m_data[this->m_len - 1] == '\"')) { - memmove(this->m_data, this->m_data + 1, this->m_len - 2 + 1); - this->m_len -= 2; - } - return *this; -} - -/*------------------------------------------------------------------------------------------------- - Assignment/Concatenation --------------------------------------------------------------------------------------------------*/ - -// -// Set the string's conents to a copy of <src> with length <len> -// -rcSTR_String STR_String::Copy(const char *src, int len) -{ - assertd(len >= 0); - assertd(src); - assertd(this->m_data != NULL); - - AllocBuffer(len, false); - this->m_len = len; - memcpy(this->m_data, src, len); - this->m_data[this->m_len] = 0; - - return *this; -} - -// -// Concate a number of bytes to the current string -// -rcSTR_String STR_String::Concat(const char *data, int len) -{ - assertd(this->m_len >= 0); - assertd(len >= 0); - assertd(data); - assertd(this->m_data != NULL); - - AllocBuffer(this->m_len + len, true); - memcpy(this->m_data + this->m_len, data, len); - this->m_len += len; - this->m_data[this->m_len] = 0; - - return *this; -} - -std::vector<STR_String> STR_String::Explode(char c) const -{ - STR_String lcv = *this; - std::vector<STR_String> uc; - - while (lcv.Length()) { - int pos = lcv.Find(c); - if (pos < 0) { - uc.push_back(lcv); - lcv.Clear(); - } - else { - uc.push_back(lcv.Left(pos)); - lcv = lcv.Mid(pos + 1); - } - } - - // uc. -= STR_String(""); - - return uc; -} - -#if 0 - -int STR_String::Serialize(pCStream stream) -{ - if (stream->GetAccess() == CStream::Access_Read) { - int ln; - stream->Read(&ln, sizeof(ln)); - AllocBuffer(ln, false); - stream->Read(this->m_data, ln); - this->m_data[ln] = '\0'; - this->m_len = ln; - } - else { - stream->Write(&this->m_len, sizeof(this->m_len)); - stream->Write(this->m_data, this->m_len); - } - - return this->m_len + sizeof(this->m_len); -} -#endif diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index 9771530ff18..aee532f1c2d 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -19,10 +19,10 @@ /* For constants. */ #include "BLI_math_base.h" -#include "DNA_userdef_types.h" +#include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_space_types.h" -#include "DNA_anim_types.h" +#include "DNA_userdef_types.h" #include "BLI_math_rotation.h" @@ -227,6 +227,8 @@ const UserDef U_default = { .sequencer_disk_cache_size_limit = 100, .sequencer_disk_cache_flag = 0, + .collection_instance_empty_size = 1.0f, + .runtime = { .is_dirty = 0, diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c index de3583db2bb..4d48bb8eaac 100644 --- a/release/datafiles/userdef/userdef_default_theme.c +++ b/release/datafiles/userdef/userdef_default_theme.c @@ -279,8 +279,8 @@ const bTheme U_theme_default = { .button_text_hi = RGBA(0xffffffff), .navigation_bar = RGBA(0x232323ff), .panelcolors = { - .header = RGBA(0x42424200), - .back = RGBA(0x00000028), + .header = RGBA(0x424242ff), + .back = RGBA(0x383838ff), .sub_back = RGBA(0x00000024), }, .vertex_size = 3, @@ -697,7 +697,7 @@ const bTheme U_theme_default = { .vertex_size = 3, .outline_width = 1, .facedot_size = 3, - .editmesh_active = RGBA(0xffffff80), + .editmesh_active = RGBA(0xffffff40), .handle_vertex_select = RGBA(0xffff00ff), .handle_vertex_size = 5, .gp_vertex_size = 3, diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index c233681dc41..e522ec3fcf9 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -28,6 +28,7 @@ import json import os import sys +import types import bpy @@ -556,6 +557,10 @@ def _gen_get_set_path(ref, name): return _get, _set +def _check_valid_data(uid, val): + return not uid.startswith("_") and type(val) not in tuple(types.__dict__.values()) + (type,) + + class I18nSettings: """ Class allowing persistence of our settings! @@ -567,20 +572,32 @@ class I18nSettings: # Addon preferences are singleton by definition, so is this class! if not I18nSettings._settings: cls._settings = super(I18nSettings, cls).__new__(cls) - cls._settings.__dict__ = {uid: data for uid, data in globals().items() if not uid.startswith("_")} + cls._settings.__dict__ = {uid: val for uid, val in globals().items() if _check_valid_data(uid, val)} return I18nSettings._settings - def from_json(self, string): - data = dict(json.loads(string)) + def __getstate__(self): + return self.to_dict() + + def __setstate__(self, mapping): + return self.from_dict(mapping) + + def from_dict(self, mapping): # Special case... :/ - if "INTERN_PY_SYS_PATHS" in data: - self.PY_SYS_PATHS = data["INTERN_PY_SYS_PATHS"] - self.__dict__.update(data) + if "INTERN_PY_SYS_PATHS" in mapping: + self.PY_SYS_PATHS = mapping["INTERN_PY_SYS_PATHS"] + self.__dict__.update(mapping) + + def to_dict(self): + glob = globals() + return {uid: val for uid, val in self.__dict__.items() if _check_valid_data(uid, val) and uid in glob} + + def from_json(self, string): + self.from_dict(dict(json.loads(string))) def to_json(self): # Only save the diff from default i18n_settings! glob = globals() - export_dict = {uid: val for uid, val in self.__dict__.items() if glob.get(uid) != val} + export_dict = {uid: val for uid, val in self.__dict__.items() if _check_valid_data(uid, val) and glob.get(uid) != val} return json.dumps(export_dict) def load(self, fname, reset=False): diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py index 493afc53267..61837cc0956 100644 --- a/release/scripts/modules/bl_i18n_utils/utils.py +++ b/release/scripts/modules/bl_i18n_utils/utils.py @@ -21,7 +21,6 @@ # Some misc utilities... import collections -import concurrent.futures import copy import hashlib import os @@ -238,6 +237,12 @@ class I18nMessage: self.is_fuzzy = is_fuzzy self.is_commented = is_commented + # ~ def __getstate__(self): + # ~ return {key: getattr(self, key) for key in self.__slots__} + + # ~ def __getstate__(self): + # ~ return {key: getattr(self, key) for key in self.__slots__} + def _get_msgctxt(self): return "".join(self.msgctxt_lines) @@ -426,6 +431,14 @@ class I18nMessages: self._reverse_cache = None + def __getstate__(self): + return (self.settings, self.uid, self.msgs, self.parsing_errors) + + def __setstate__(self, data): + self.__init__() + self.settings, self.uid, self.msgs, self.parsing_errors = data + self.update_info() + @staticmethod def _new_messages(): return getattr(collections, 'OrderedDict', dict)() @@ -566,24 +579,23 @@ class I18nMessages: # Next process new keys. if use_similar > 0.0: - with concurrent.futures.ProcessPoolExecutor() as exctr: - for key, msgid in exctr.map(get_best_similar, - tuple((nk, use_similar, tuple(similar_pool.keys())) for nk in new_keys)): - if msgid: - # Try to get the same context, else just get one... - skey = (key[0], msgid) - if skey not in similar_pool[msgid]: - skey = tuple(similar_pool[msgid])[0] - # We keep org translation and comments, and mark message as fuzzy. - msg, refmsg = self.msgs[skey].copy(), ref.msgs[key] - msg.msgctxt = refmsg.msgctxt - msg.msgid = refmsg.msgid - msg.sources = refmsg.sources - msg.is_fuzzy = True - msg.is_commented = refmsg.is_commented - msgs[key] = msg - else: - msgs[key] = ref.msgs[key] + for key, msgid in map(get_best_similar, + tuple((nk, use_similar, tuple(similar_pool.keys())) for nk in new_keys)): + if msgid: + # Try to get the same context, else just get one... + skey = (key[0], msgid) + if skey not in similar_pool[msgid]: + skey = tuple(similar_pool[msgid])[0] + # We keep org translation and comments, and mark message as fuzzy. + msg, refmsg = self.msgs[skey].copy(), ref.msgs[key] + msg.msgctxt = refmsg.msgctxt + msg.msgid = refmsg.msgid + msg.sources = refmsg.sources + msg.is_fuzzy = True + msg.is_commented = refmsg.is_commented + msgs[key] = msg + else: + msgs[key] = ref.msgs[key] else: for key in new_keys: msgs[key] = ref.msgs[key] @@ -1075,9 +1087,7 @@ class I18nMessages: "-o", fname, ) - print("Running ", " ".join(cmd)) ret = subprocess.call(cmd) - print("Finished.") return # XXX Code below is currently broken (generates corrupted mo files it seems :( )! # Using http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html notation. diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py index 22be5186186..844daded570 100644 --- a/release/scripts/modules/rna_keymap_ui.py +++ b/release/scripts/modules/rna_keymap_ui.py @@ -161,7 +161,12 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level): if (not kmi.is_user_defined) and kmi.is_user_modified: row.operator("preferences.keyitem_restore", text="", icon='BACK').item_id = kmi.id else: - row.operator("preferences.keyitem_remove", text="", icon='X').item_id = kmi.id + row.operator( + "preferences.keyitem_remove", + text="", + # Abusing the tracking icon, but it works pretty well here. + icon=('TRACKING_CLEAR_BACKWARDS' if kmi.is_user_defined else 'X') + ).item_id = kmi.id # Expanded, additional event settings if kmi.show_expanded: diff --git a/release/scripts/presets/interface_theme/blender_light.xml b/release/scripts/presets/interface_theme/blender_light.xml index f4ec8233df3..48ad0a8367e 100644 --- a/release/scripts/presets/interface_theme/blender_light.xml +++ b/release/scripts/presets/interface_theme/blender_light.xml @@ -724,7 +724,7 @@ freestyle_face_mark="#7fff7f33" face_back="#00000000" face_front="#00000000" - editmesh_active="#ffffff80" + editmesh_active="#ffffff40" wire_edit="#c0c0c0" edge_select="#ff8500" scope_back="#727272ff" diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index f2c3a9f1ee5..614a76c3994 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -798,8 +798,8 @@ def km_outliner(params): ("outliner.drivers_add_selected", {"type": 'D', "value": 'PRESS', "ctrl": True}, None), ("outliner.drivers_delete_selected", {"type": 'D', "value": 'PRESS', "ctrl": True, "alt": True}, None), ("outliner.collection_new", {"type": 'C', "value": 'PRESS'}, None), - ("outliner.collection_delete", {"type": 'X', "value": 'PRESS'}, None), - ("outliner.collection_delete", {"type": 'DEL', "value": 'PRESS'}, None), + ("outliner.delete", {"type": 'X', "value": 'PRESS'}, None), + ("outliner.delete", {"type": 'DEL', "value": 'PRESS'}, None), ("object.move_to_collection", {"type": 'M', "value": 'PRESS'}, None), ("object.link_to_collection", {"type": 'M', "value": 'PRESS', "shift": True}, None), ("outliner.collection_exclude_set", {"type": 'E', "value": 'PRESS'}, None), @@ -1391,7 +1391,6 @@ def km_time_scrub(_params): items.extend([ ("anim.change_frame", {"type": "LEFTMOUSE", "value": 'PRESS'}, None), - ("graph.cursor_set", {"type": "LEFTMOUSE", "value": 'PRESS'}, None), ]) return keymap @@ -3028,6 +3027,8 @@ def km_grease_pencil(_params): # Draw ("gpencil.annotate", {"type": 'LEFTMOUSE', "value": 'PRESS', "key_modifier": 'D'}, {"properties": [("mode", 'DRAW'), ("wait_for_input", False)]}), + ("gpencil.annotate", {"type": 'LEFTMOUSE', "value": 'PRESS', "key_modifier": 'D', "shift": True}, + {"properties": [("mode", 'DRAW'), ("wait_for_input", False)]}), # Draw - straight lines ("gpencil.annotate", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True, "key_modifier": 'D'}, {"properties": [("mode", 'DRAW_STRAIGHT'), ("wait_for_input", False)]}), @@ -3226,6 +3227,8 @@ def km_grease_pencil_stroke_paint_mode(params): {"properties": [("unselected", True)]}), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Active material + op_menu("GPENCIL_MT_material_active", {"type": 'U', "value": 'PRESS'}), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), # Draw context menu @@ -5873,6 +5876,23 @@ def km_3d_view_tool_edit_mesh_extrude_region(params): ]}, ) +def km_3d_view_tool_edit_mesh_extrude_dissolve_and_intersect(params): + return ( + "3D View Tool: Edit Mesh, Extrude Dissolve and Intersect", + {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, + {"items": [ + ("mesh.extrude_region_dissolve_move_intersect", {"type": params.tool_tweak, "value": 'ANY'}, + {"properties": [ + ("MESH_OT_extrude_region", [("use_dissolve_ortho_edges", True)]), + ("TRANSFORM_OT_translate", [ + ("release_confirm", True), + ("use_automerge_and_split", True), + ("constraint_axis", (False, False, True)), + ("orient_type", 'NORMAL'), + ]), + ]}), + ]}, + ) def km_3d_view_tool_edit_mesh_extrude_along_normals(params): return ( @@ -6723,6 +6743,7 @@ def generate_keymaps(params=None): km_3d_view_tool_edit_armature_extrude_to_cursor(params), km_3d_view_tool_edit_mesh_add_cube(params), km_3d_view_tool_edit_mesh_extrude_region(params), + km_3d_view_tool_edit_mesh_extrude_dissolve_and_intersect(params), km_3d_view_tool_edit_mesh_extrude_along_normals(params), km_3d_view_tool_edit_mesh_extrude_individual(params), km_3d_view_tool_edit_mesh_extrude_to_cursor(params), 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 0005e7dd3d2..842a12ed249 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -520,10 +520,8 @@ def km_outliner(params): ("anim.keyframe_delete", {"type": 'S', "value": 'PRESS', "alt": True}, None), ("outliner.drivers_add_selected", {"type": 'D', "value": 'PRESS', "ctrl": True}, None), ("outliner.drivers_delete_selected", {"type": 'D', "value": 'PRESS', "ctrl": True, "alt": True}, None), - ("outliner.collection_delete", {"type": 'BACK_SPACE', "value": 'PRESS'}, None), - ("outliner.collection_delete", {"type": 'DEL', "value": 'PRESS'}, None), - ("outliner.object_operation", {"type": 'BACK_SPACE', "value": 'PRESS'}, {"properties": [("type", 'DELETE')]}), - ("outliner.object_operation", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("type", 'DELETE')]}), + ("outliner.delete", {"type": 'BACK_SPACE', "value": 'PRESS'}, None), + ("outliner.delete", {"type": 'DEL', "value": 'PRESS'}, None), ("object.move_to_collection", {"type": 'G', "value": 'PRESS', "ctrl": True}, None), ("object.link_to_collection", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), ("outliner.collection_exclude_set", {"type": 'E', "value": 'PRESS'}, None), @@ -2376,7 +2374,7 @@ def km_grease_pencil_stroke_paint_mode(params): op_tool_cycle("builtin.cutter", {"type": 'K', "value": 'PRESS'}), op_tool_cycle("builtin.cursor", {"type": 'C', "value": 'PRESS'}), # Active layer - op_menu("GPENCIL_MT_layer_active", {"type": 'M', "value": 'PRESS'}), + op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), ]) @@ -3377,6 +3375,10 @@ def km_sculpt(params): # Remesh ("object.voxel_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None), ("object.quadriflow_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True, "alt": True}, None), + # Remesh + ("object.voxel_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None), + ("object.voxel_size_edit", {"type": 'R', "value": 'PRESS', "shift": True}, None), + ("object.quadriflow_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True, "alt": True}, None), # Brush properties ("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS'}, {"properties": [("scalar", 0.9)]}), diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py index 5af2bd22222..d7df29f1769 100644 --- a/release/scripts/startup/bl_operators/__init__.py +++ b/release/scripts/startup/bl_operators/__init__.py @@ -42,6 +42,7 @@ _modules = [ "rigidbody", "screen_play_rendered_anim", "sequencer", + "simulation", "userpref", "uvcalc_follow_active", "uvcalc_lightmap", diff --git a/release/scripts/startup/bl_operators/simulation.py b/release/scripts/startup/bl_operators/simulation.py new file mode 100644 index 00000000000..5d9c9476318 --- /dev/null +++ b/release/scripts/startup/bl_operators/simulation.py @@ -0,0 +1,39 @@ +# ##### 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 ##### + +import bpy + +class NewSimulation(bpy.types.Operator): + """Create a new simulation data block and edit it in the opened simulation editor""" + + bl_idname = "simulation.new" + bl_label = "New Simulation" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + return context.area.type == 'NODE_EDITOR' and context.space_data.tree_type == 'SimulationNodeTree' + + def execute(self, context): + simulation = bpy.data.simulations.new("Simulation") + context.space_data.simulation = simulation + return {'FINISHED'} + +classes = ( + NewSimulation, +) diff --git a/release/scripts/startup/bl_operators/userpref.py b/release/scripts/startup/bl_operators/userpref.py index f78ee026927..2e14df1920f 100644 --- a/release/scripts/startup/bl_operators/userpref.py +++ b/release/scripts/startup/bl_operators/userpref.py @@ -110,20 +110,30 @@ class PREFERENCES_OT_copy_prev(Operator): bl_idname = "preferences.copy_prev" bl_label = "Copy Previous Settings" - @staticmethod - def previous_version(): - ver = bpy.app.version - ver_old = ((ver[0] * 100) + ver[1]) - 1 - return ver_old // 100, ver_old % 100 + @classmethod + def _old_version_path(cls, version): + return bpy.utils.resource_path('USER', version[0], version[1]) - @staticmethod - def _old_path(): - ver = bpy.app.version - ver_old = ((ver[0] * 100) + ver[1]) - 1 - return bpy.utils.resource_path('USER', ver_old // 100, ver_old % 100) + @classmethod + def previous_version(cls): + # Find config folder from previous version. + import os + version = bpy.app.version + version_old = ((version[0] * 100) + version[1]) - 1 + while version_old % 10 > 0: + version_split = version_old // 100, version_old % 100 + if os.path.isdir(cls._old_version_path(version_split)): + return version_split + version_old = version_old - 1 + return None - @staticmethod - def _new_path(): + @classmethod + def _old_path(cls): + version_old = cls.previous_version() + return cls._old_version_path(version_old) if version_old else None + + @classmethod + def _new_path(cls): return bpy.utils.resource_path('USER') @classmethod @@ -132,6 +142,8 @@ class PREFERENCES_OT_copy_prev(Operator): old = cls._old_path() new = cls._new_path() + if not old: + return False # Disable operator in case config path is overridden with environment # variable. That case has no automatic per-version configuration. @@ -972,6 +984,7 @@ class PREFERENCES_OT_studiolight_install(Operator): options={'HIDDEN'}, ) type: EnumProperty( + name="Type", items=( ('MATCAP', "MatCap", ""), ('WORLD', "World", ""), diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py index fcabee94a89..88fa06a913f 100644 --- a/release/scripts/startup/bl_operators/view3d.py +++ b/release/scripts/startup/bl_operators/view3d.py @@ -72,13 +72,19 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator): bl_label = "Extrude and Move on Normals" bl_idname = "view3d.edit_mesh_extrude_move_normal" + dissolve_and_intersect: BoolProperty( + name="dissolve_and_intersect", + default=False, + description="Dissolves adjacent faces and intersects new geometry" + ) + @classmethod def poll(cls, context): obj = context.active_object return (obj is not None and obj.mode == 'EDIT') @staticmethod - def extrude_region(context, use_vert_normals): + def extrude_region(context, use_vert_normals, dissolve_and_intersect): mesh = context.object.data totface = mesh.total_face_sel @@ -91,6 +97,17 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator): 'INVOKE_REGION_WIN', TRANSFORM_OT_shrink_fatten={}, ) + elif dissolve_and_intersect: + bpy.ops.mesh.extrude_region_dissolve_move_intersect( + 'INVOKE_REGION_WIN', + MESH_OT_extrude_region={ + "use_dissolve_ortho_edges": True, + }, + TRANSFORM_OT_translate={ + "orient_type": 'NORMAL', + "constraint_axis": (False, False, True), + }, + ) else: bpy.ops.mesh.extrude_region_move( 'INVOKE_REGION_WIN', @@ -119,7 +136,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator): return {'FINISHED'} def execute(self, context): - return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, False) + return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, False, self.dissolve_and_intersect) def invoke(self, context, _event): return self.execute(context) @@ -136,7 +153,7 @@ class VIEW3D_OT_edit_mesh_extrude_shrink_fatten(Operator): return (obj is not None and obj.mode == 'EDIT') def execute(self, context): - return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, True) + return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, True, False) def invoke(self, context, _event): return self.execute(context) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 70d958b9bc8..9e2ce8b83ad 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -2485,8 +2485,8 @@ class WM_MT_splash(Menu): row = layout.row() sub = row.row() - if bpy.types.PREFERENCES_OT_copy_prev.poll(context): - old_version = bpy.types.PREFERENCES_OT_copy_prev.previous_version() + old_version = bpy.types.PREFERENCES_OT_copy_prev.previous_version() + if bpy.types.PREFERENCES_OT_copy_prev.poll(context) and old_version: sub.operator("preferences.copy_prev", text="Load %d.%d Settings" % old_version) sub.operator("wm.save_userpref", text="Save New Settings") else: diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index d44af702d46..05abfa02500 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -84,17 +84,12 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel): layout.prop(arm, "display_type", text="Display As") - flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True) - col = flow.column() + col = layout.column(heading="Show") col.prop(arm, "show_names", text="Names") - col = flow.column() col.prop(arm, "show_axes", text="Axes") - col = flow.column() col.prop(arm, "show_bone_custom_shapes", text="Shapes") - col = flow.column() col.prop(arm, "show_group_colors", text="Group Colors") if ob: - col = flow.column() col.prop(ob, "show_in_front", text="In Front") diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index aee909e3a6c..62dffa3b6ba 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -360,8 +360,9 @@ class DATA_PT_camera_background_image(CameraButtonsPanel, Panel): col.prop(bg, "rotation") col.prop(bg, "scale") - col.prop(bg, "use_flip_x") - col.prop(bg, "use_flip_y") + col = box.column(heading="Flip") + col.prop(bg, "use_flip_x", text="X") + col.prop(bg, "use_flip_y", text="Y") class DATA_PT_camera_display(CameraButtonsPanel, Panel): @@ -377,21 +378,12 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel): col = layout.column(align=True) - col.separator() - col.prop(cam, "display_size", text="Size") - col.separator() - - flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False) - - col = flow.column() + col = layout.column(heading="Show") col.prop(cam, "show_limits", text="Limits") - col = flow.column() col.prop(cam, "show_mist", text="Mist") - col = flow.column() col.prop(cam, "show_sensor", text="Sensor") - col = flow.column() col.prop(cam, "show_name", text="Name") @@ -407,24 +399,20 @@ class DATA_PT_camera_display_composition_guides(CameraButtonsPanel, Panel): cam = context.camera - flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False) + layout.prop(cam, "show_composition_thirds") - col = flow.column() + col = layout.column(heading="Center", align=True) col.prop(cam, "show_composition_center") - col = flow.column() - col.prop(cam, "show_composition_center_diagonal") - col = flow.column() - col.prop(cam, "show_composition_thirds") - col = flow.column() - col.prop(cam, "show_composition_golden") - col = flow.column() - col.prop(cam, "show_composition_golden_tria_a") - col = flow.column() - col.prop(cam, "show_composition_golden_tria_b") - col = flow.column() - col.prop(cam, "show_composition_harmony_tri_a") - col = flow.column() - col.prop(cam, "show_composition_harmony_tri_b") + col.prop(cam, "show_composition_center_diagonal", text="Diagonal") + + col = layout.column(heading="Golden", align=True) + col.prop(cam, "show_composition_golden", text="Ratio") + col.prop(cam, "show_composition_golden_tria_a", text="Triangle A") + col.prop(cam, "show_composition_golden_tria_b", text="Triangle B") + + col = layout.column(heading="Harmony", align=True) + col.prop(cam, "show_composition_harmony_tri_a", text="Triangle A") + col.prop(cam, "show_composition_harmony_tri_b", text="Triangle B") class DATA_PT_camera_display_passepartout(CameraButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index b694062dfc5..7e7488f4cf1 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -276,23 +276,23 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel): col.prop(act_spline, "use_smooth") else: - sub = col.column(align=True) - sub.prop(act_spline, "use_cyclic_u") + sub = col.column(heading="Cyclic", align=True) + sub.prop(act_spline, "use_cyclic_u", text="U") if is_surf: sub.prop(act_spline, "use_cyclic_v", text="V") if act_spline.type == 'NURBS': - sub = col.column(align=True) + sub = col.column(heading="Bezier", align=True) # sub.active = (not act_spline.use_cyclic_u) - sub.prop(act_spline, "use_bezier_u", text="Bezier U") + sub.prop(act_spline, "use_bezier_u", text="U") if is_surf: subsub = sub.column() subsub.active = (not act_spline.use_cyclic_v) subsub.prop(act_spline, "use_bezier_v", text="V") - sub = col.column(align=True) - sub.prop(act_spline, "use_endpoint_u", text="Endpoint U") + sub = col.column(heading="Endpoint", align=True) + sub.prop(act_spline, "use_endpoint_u", text="U") if is_surf: subsub = sub.column() diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py index 898ab2e4359..1523f69536f 100644 --- a/release/scripts/startup/bl_ui/properties_data_empty.py +++ b/release/scripts/startup/bl_ui/properties_data_empty.py @@ -53,9 +53,11 @@ class DATA_PT_empty(DataButtonsPanel, Panel): depth_row.enabled = not ob.show_in_front depth_row.prop(ob, "empty_image_depth", text="Depth", expand=True) col.row().prop(ob, "empty_image_side", text="Side", expand=True) - col.prop(ob, "show_empty_image_orthographic", text="Display Orthographic") - col.prop(ob, "show_empty_image_perspective", text="Display Perspective") - col.prop(ob, "show_empty_image_only_axis_aligned") + + col = layout.column(heading="Show in", align=True) + col.prop(ob, "show_empty_image_orthographic", text="Orthographic") + col.prop(ob, "show_empty_image_perspective", text="Perspective") + col.prop(ob, "show_empty_image_only_axis_aligned", text="Only Axis Aligned") class DATA_PT_empty_alpha(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 d91b2ceb7f7..425c94dfdcd 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -190,27 +190,20 @@ class DATA_PT_normals(MeshButtonsPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} def draw(self, context): - pass - - -class DATA_PT_normals_auto_smooth(MeshButtonsPanel, Panel): - bl_label = "Auto Smooth" - bl_parent_id = "DATA_PT_normals" - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} - - def draw_header(self, context): - mesh = context.mesh - - self.layout.prop(mesh, "use_auto_smooth", text="") - - def draw(self, context): layout = self.layout layout.use_property_split = True mesh = context.mesh - layout.active = mesh.use_auto_smooth and not mesh.has_custom_normals - layout.prop(mesh, "auto_smooth_angle", text="Angle") + col = layout.column(align=False, heading="Auto Smooth") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(mesh, "use_auto_smooth", text="") + sub = sub.row(align=True) + sub.active = mesh.use_auto_smooth and not mesh.has_custom_normals + sub.prop(mesh, "auto_smooth_angle", text="") + row.prop_decorator(mesh, "auto_smooth_angle") class DATA_PT_texture_space(MeshButtonsPanel, Panel): @@ -485,9 +478,11 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel): col.prop(mesh, "remesh_voxel_adaptivity") col.prop(mesh, "use_remesh_fix_poles") col.prop(mesh, "use_remesh_smooth_normals") - col.prop(mesh, "use_remesh_preserve_volume") - col.prop(mesh, "use_remesh_preserve_paint_mask") - col.prop(mesh, "use_remesh_preserve_sculpt_face_sets") + + col = layout.column(heading="Preserve") + col.prop(mesh, "use_remesh_preserve_volume", text="Volume") + col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask") + col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets") col.operator("object.voxel_remesh", text="Voxel Remesh") else: col.operator("object.quadriflow_remesh", text="QuadriFlow Remesh") @@ -515,12 +510,12 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel): else: col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') - col = layout.column() + col = layout.column(heading="Store") col.enabled = obj is not None and obj.mode != 'EDIT' - col.prop(me, "use_customdata_vertex_bevel") - col.prop(me, "use_customdata_edge_bevel") - col.prop(me, "use_customdata_edge_crease") + col.prop(me, "use_customdata_vertex_bevel", text="Vertex Bevel Weight") + col.prop(me, "use_customdata_edge_bevel", text="Edge Bevel Weight") + col.prop(me, "use_customdata_edge_crease", text="Edge Crease") class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel): @@ -544,7 +539,6 @@ classes = ( DATA_PT_vertex_colors, DATA_PT_face_maps, DATA_PT_normals, - DATA_PT_normals_auto_smooth, DATA_PT_texture_space, DATA_PT_remesh, DATA_PT_customdata, diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 8f1337b156d..a2c477bd6f1 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -688,8 +688,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): split = layout.split() col = split.column() col.prop(md, "levels", text="Preview") - # TODO(sergey): Expose it again after T58473 is solved. - # col.prop(md, "sculpt_levels", text="Sculpt") + col.prop(md, "sculpt_levels", text="Sculpt") col.prop(md, "render_levels", text="Render") row = col.row() @@ -699,10 +698,20 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = split.column() col.enabled = ob.mode != 'EDIT' - col.operator("object.multires_subdivide", text="Subdivide") + op = col.operator("object.multires_subdivide", text="Subdivide") + op.mode = 'CATMULL_CLARK' + + op = col.operator("object.multires_subdivide", text="Subdivide Simple") + op.mode = 'SIMPLE' + + op = col.operator("object.multires_subdivide", text="Subdivide Linear") + op.mode = 'LINEAR' + col.operator("object.multires_higher_levels_delete", text="Delete Higher") + col.operator("object.multires_unsubdivide", text="Unsubdivide") col.operator("object.multires_reshape", text="Reshape") col.operator("object.multires_base_apply", text="Apply Base") + col.operator("object.multires_rebuild_subdiv", text="Rebuild Subdivisions") col.prop(md, "uv_smooth", text="") col.prop(md, "show_only_control_edges") col.prop(md, "use_creases") @@ -1343,7 +1352,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): if md.mode == 'VOXEL': layout.prop(md, "voxel_size") layout.prop(md, "adaptivity") - else: + else: row.prop(md, "octree_depth") row.prop(md, "scale") @@ -1875,7 +1884,15 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel): split = col2.split(factor=0.6) row = split.row(align=True) - row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE') + + valid = md.material in (slot.material for slot in ob.material_slots) or md.material is None + if valid: + icon = 'SHADING_TEXTURE' + else: + icon = 'ERROR' + + row.alert = not valid + row.prop_search(md, "material", gpd, "materials", text="", icon=icon) row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT') row = split.row(align=True) @@ -1978,6 +1995,27 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel): self.gpencil_masking(layout, ob, md, True, True) + def GP_TEXTURE(self, layout, ob, md): + col = layout.column() + + col.prop(md, "mode") + if md.mode in {'STROKE', 'STROKE_AND_FILL'}: + col.label(text="Stroke Texture:") + col.prop(md, "fit_method") + col.prop(md, "uv_offset") + col.prop(md, "uv_scale") + + if md.mode == 'STROKE_AND_FILL': + col.separator() + + if md.mode in {'FILL', 'STROKE_AND_FILL'}: + col.label(text="Fill Texture:") + col.prop(md, "fill_rotation", text="Rotation") + col.prop(md, "fill_offset", text="Location") + col.prop(md, "fill_scale", text="Scale") + + self.gpencil_masking(layout, ob, md, True) + def GP_TINT(self, layout, ob, md): layout.row().prop(md, "tint_type", expand=True) @@ -2152,6 +2190,11 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel): sub.prop(md, "frame_start", text="Start") sub.prop(md, "frame_end", text="End") + col.prop(md, "use_percentage") + sub = col.column(align=True) + sub.active = md.use_percentage + sub.prop(md, "percentage_factor") + layout.label(text="Influence Filters:") split = layout.split(factor=0.25) 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 8b02f858b65..64eda42c87a 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -44,38 +44,6 @@ def gpencil_stroke_placement_settings(context, layout): row.prop_enum(tool_settings, propname, 'CURSOR', text="Cursor") -def gpencil_active_brush_settings_simple(context, layout): - tool_settings = context.tool_settings - brush = tool_settings.gpencil_paint.brush - if brush is None: - layout.label(text="No Active Brush") - return - - col = layout.column() - col.label(text="Active Brush: ") - - row = col.row(align=True) - row.operator_context = 'EXEC_REGION_WIN' - row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA') - row.prop(brush, "name", text="") - - col.prop(brush, "size", slider=True) - row = col.row(align=True) - row.prop(brush, "use_random_pressure", text="", icon='RNDCURVE') - row.prop(brush, "pen_sensitivity_factor", slider=True) - row.prop(brush, "use_pressure", text="", icon='STYLUS_PRESSURE') - row = col.row(align=True) - row.prop(brush, "use_random_strength", text="", icon='RNDCURVE') - row.prop(brush, "strength", slider=True) - row.prop(brush, "use_strength_pressure", text="", icon='STYLUS_PRESSURE') - row = col.row(align=True) - row.prop(brush, "jitter", slider=True) - row.prop(brush, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE') - row = col.row() - row.prop(brush, "angle", slider=True) - row.prop(brush, "angle_factor", text="Factor", slider=True) - - # XXX: To be replaced with active tools class AnnotationDrawingToolsPanel: # subclass must set @@ -361,6 +329,35 @@ class GPENCIL_MT_layer_active(Menu): layout.operator("gpencil.layer_add", text="New Layer", icon='ADD') +class GPENCIL_MT_material_active(Menu): + bl_label = "Change Active Material" + + @classmethod + def poll(cls, context): + ob = context.active_object + tool_settings = context.scene.tool_settings + mode = tool_settings.gpencil_paint.color_mode + if mode != 'MATERIAL': + return False + + if ob is None or len(ob.material_slots) == 0: + return False + + return True + + def draw(self, context): + layout = self.layout + layout.operator_context = 'INVOKE_REGION_WIN' + ob = context.active_object + mat_active = ob.active_material + + for slot in ob.material_slots: + mat = slot.material + if mat: + icon = mat.id_data.preview.icon_id + layout.operator("gpencil.material_set", text=mat.name, icon_value=icon).slot = mat.name + + class GPENCIL_MT_gpencil_draw_delete(Menu): bl_label = "Delete" @@ -520,7 +517,7 @@ class AnnotationOnionSkin: if gpl is None: return False - return True + return True def draw_header(self, context): gpl = context.active_annotation_layer @@ -548,30 +545,6 @@ class AnnotationOnionSkin: sub.prop(gpl, "annotation_onion_after_range", text="After") -class GreasePencilToolsPanel: - # For use in "2D" Editors without their own toolbar - # subclass must set - # bl_space_type = 'IMAGE_EDITOR' - bl_label = "Grease Pencil Settings" - bl_region_type = 'UI' - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, _context): - # XXX - disabled in 2.8 branch. - # return (context.gpencil_data is not None) - return False - - def draw(self, context): - layout = self.layout - - gpencil_active_brush_settings_simple(context, layout) - - layout.separator() - - gpencil_stroke_placement_settings(context, layout) - - class GreasePencilMaterialsPanel: # Mix-in, use for properties editor and top-bar. def draw(self, context): @@ -632,8 +605,8 @@ class GreasePencilMaterialsPanel: if ob.data.use_stroke_edit_mode: row = layout.row(align=True) row.operator("gpencil.stroke_change_color", text="Assign") - row.operator("gpencil.select_material", text="Select").deselect = False - row.operator("gpencil.select_material", text="Deselect").deselect = True + row.operator("gpencil.material_select", text="Select").deselect = False + row.operator("gpencil.material_select", text="Deselect").deselect = True # stroke color ma = None if is_view3d and brush is not None: @@ -931,6 +904,7 @@ classes = ( GPENCIL_MT_cleanup, GPENCIL_MT_move_to_layer, GPENCIL_MT_layer_active, + GPENCIL_MT_material_active, GPENCIL_MT_gpencil_draw_delete, GPENCIL_MT_layer_mask_menu, diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index ab70c4c25c0..6aaec9940e8 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -172,10 +172,11 @@ class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel): layout.prop(mat, "use_nodes", icon='NODETREE') layout.separator() + layout.use_property_split = True + if mat.use_nodes: panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Surface") else: - layout.use_property_split = True layout.prop(mat, "diffuse_color", text="Base Color") layout.prop(mat, "metallic") layout.prop(mat, "specular_intensity", text="Specular") @@ -197,6 +198,8 @@ class EEVEE_MATERIAL_PT_volume(MaterialButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + mat = context.material panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Volume") diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index a805b965af2..8ce53ed30eb 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -212,7 +212,6 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) obj = context.object obj_type = obj.type @@ -222,35 +221,22 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel): is_dupli = (obj.instance_type != 'NONE') is_gpencil = (obj_type == 'GPENCIL') - col = flow.column() + col = layout.column(heading="Show") col.prop(obj, "show_name", text="Name") - - col = flow.column() col.prop(obj, "show_axis", text="Axis") # Makes no sense for cameras, armatures, etc.! # but these settings do apply to dupli instances if is_geometry or is_dupli: - col = flow.column() col.prop(obj, "show_wire", text="Wireframe") if obj_type == 'MESH' or is_dupli: - col = flow.column() col.prop(obj, "show_all_edges", text="All Edges") - - col = flow.column() if is_geometry: col.prop(obj, "show_texture_space", text="Texture Space") - col = flow.column() col.prop(obj.display, "show_shadows", text="Shadow") - - col = flow.column() col.prop(obj, "show_in_front", text="In Front") # if obj_type == 'MESH' or is_empty_image: # col.prop(obj, "show_transparent", text="Transparency") - - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() if is_wire: # wire objects only use the max. display type for duplis col.active = is_dupli @@ -258,28 +244,17 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel): if is_geometry or is_dupli or is_empty_image or is_gpencil: # Only useful with object having faces/materials... - col = flow.column() col.prop(obj, "color") - -class OBJECT_PT_display_bounds(ObjectButtonsPanel, Panel): - bl_label = "Bounds" - bl_parent_id = "OBJECT_PT_display" - bl_options = {'DEFAULT_CLOSED'} - - def draw_header(self, context): - - obj = context.object - - self.layout.prop(obj, "show_bounds", text="") - - def draw(self, context): - layout = self.layout - obj = context.object - layout.use_property_split = True - - layout.active = obj.show_bounds or (obj.display_type == 'BOUNDS') - layout.prop(obj, "display_bounds_type", text="Shape") + col = layout.column(align=False, heading="Bounds") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(obj, "show_bounds", text="") + sub = sub.row(align=True) + sub.active = obj.show_bounds or (obj.display_type == 'BOUNDS') + sub.prop(obj, "display_bounds_type", text="") + row.prop_decorator(obj, "display_bounds_type") class OBJECT_PT_instancing(ObjectButtonsPanel, Panel): @@ -295,7 +270,6 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel): row.prop(ob, "instance_type", expand=True) layout.use_property_split = True - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) if ob.instance_type == 'VERTS': layout.prop(ob, "use_instance_vertices_rotation", text="Align to Vertex Normal") @@ -305,9 +279,9 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel): col.prop(ob, "instance_collection", text="Collection") if ob.instance_type != 'NONE' or ob.particle_systems: - col = flow.column(align=True) - col.prop(ob, "show_instancer_for_viewport") - col.prop(ob, "show_instancer_for_render") + col = layout.column(heading="Show Instancer", align=True) + col.prop(ob, "show_instancer_for_viewport", text="Viewport") + col.prop(ob, "show_instancer_for_render", text="Render") class OBJECT_PT_instancing_size(ObjectButtonsPanel, Panel): @@ -385,19 +359,17 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) layout = self.layout ob = context.object - col = flow.column() - col.prop(ob, "hide_viewport", text="Show in Viewports", toggle=False, invert_checkbox=True) - col = flow.column() - col.prop(ob, "hide_render", text="Show in Renders", toggle=False, invert_checkbox=True) - col = flow.column() - col.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True) + layout.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True) + + col = layout.column(heading="Show in") + col.prop(ob, "hide_viewport", text="Viewports", toggle=False, invert_checkbox=True) + col.prop(ob, "hide_render", text="Renders", toggle=False, invert_checkbox=True) if context.object.type == 'GPENCIL': - col = flow.column() + col = layout.column(heading="Grease Pencil") col.prop(ob, "use_grease_pencil_lights", toggle=False) @@ -419,7 +391,6 @@ classes = ( OBJECT_PT_motion_paths, OBJECT_PT_motion_paths_display, OBJECT_PT_display, - OBJECT_PT_display_bounds, OBJECT_PT_visibility, OBJECT_PT_custom_props, ) diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py index 748961bb40f..e859798c085 100644 --- a/release/scripts/startup/bl_ui/properties_output.py +++ b/release/scripts/startup/bl_ui/properties_output.py @@ -94,14 +94,14 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel): return args @staticmethod - def draw_framerate(layout, sub, rd): + def draw_framerate(layout, rd): if RENDER_PT_dimensions._preset_class is None: RENDER_PT_dimensions._preset_class = bpy.types.RENDER_MT_framerate_presets args = rd.fps, rd.fps_base, RENDER_PT_dimensions._preset_class.bl_label fps_label_text, show_framerate = RENDER_PT_dimensions._draw_framerate_label(*args) - sub.menu("RENDER_MT_framerate_presets", text=fps_label_text) + layout.menu("RENDER_MT_framerate_presets", text=fps_label_text) if show_framerate: col = layout.column(align=True) @@ -136,10 +136,8 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel): col.prop(scene, "frame_end", text="End") col.prop(scene, "frame_step", text="Step") - col = layout.split() - col.alignment = 'RIGHT' - col.label(text="Frame Rate") - self.draw_framerate(layout, col, rd) + col = layout.column(heading="Frame Rate") + self.draw_framerate(col, rd) class RENDER_PT_frame_remapping(RenderOutputButtonsPanel, Panel): @@ -171,10 +169,8 @@ class RENDER_PT_post_processing(RenderOutputButtonsPanel, Panel): rd = context.scene.render - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - col = flow.column() + col = layout.column(heading="Pipeline") col.prop(rd, "use_compositing") - col = flow.column() col.prop(rd, "use_sequencer") layout.prop(rd, "dither_intensity", text="Dither", slider=True) @@ -192,44 +188,23 @@ class RENDER_PT_stamp(RenderOutputButtonsPanel, Panel): rd = context.scene.render - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) + if rd.use_sequencer: + layout.prop(rd, "metadata_input") - col = flow.column() + col = layout.column(heading="Include") col.prop(rd, "use_stamp_date", text="Date") - col = flow.column() col.prop(rd, "use_stamp_time", text="Time") - - col = flow.column() col.prop(rd, "use_stamp_render_time", text="Render Time") - col = flow.column() col.prop(rd, "use_stamp_frame", text="Frame") - col = flow.column() col.prop(rd, "use_stamp_frame_range", text="Frame Range") - col = flow.column() col.prop(rd, "use_stamp_memory", text="Memory") - col = flow.column() col.prop(rd, "use_stamp_hostname", text="Hostname") - - col = flow.column() col.prop(rd, "use_stamp_camera", text="Camera") - col = flow.column() col.prop(rd, "use_stamp_lens", text="Lens") - - col = flow.column() col.prop(rd, "use_stamp_scene", text="Scene") - col = flow.column() col.prop(rd, "use_stamp_marker", text="Marker") - - col = flow.column() col.prop(rd, "use_stamp_filename", text="Filename") - col = flow.column() - col.prop(rd, "use_stamp_sequencer_strip", text="Strip Name") - - if rd.use_sequencer: - col = flow.column() - col.prop(rd, "use_stamp_strip_meta", text="Use Strip Metadata") - class RENDER_PT_stamp_note(RenderOutputButtonsPanel, Panel): bl_label = "Note" @@ -293,21 +268,17 @@ class RENDER_PT_output(RenderOutputButtonsPanel, Panel): layout.use_property_split = True - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() - col.active = not rd.is_movie_format - col.prop(rd, "use_overwrite") - col = flow.column() - col.active = not rd.is_movie_format - col.prop(rd, "use_placeholder") - col = flow.column() + col = layout.column(heading="Saving") col.prop(rd, "use_file_extension") - col = flow.column() col.prop(rd, "use_render_cache") layout.template_image_settings(image_settings, color_management=False) + if not rd.is_movie_format: + col = layout.column(heading="Image Sequence") + col.prop(rd, "use_overwrite") + col.prop(rd, "use_placeholder") + class RENDER_PT_output_views(RenderOutputButtonsPanel, Panel): bl_label = "Views" diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 6be1aa40bf2..dfaf574f1d0 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -587,10 +587,12 @@ def brush_settings(layout, context, brush, popover=False): slider=True, ) - layout.prop(brush, "use_plane_trim", text="Plane Trim") - row = layout.row() - row.active = brush.use_plane_trim - row.prop(brush, "plane_trim", slider=True, text="Distance") + row = layout.row(heading="Plane Trim") + row.prop(brush, "use_plane_trim", text="") + sub = row.row() + sub.active = brush.use_plane_trim + sub.prop(brush, "plane_trim", slider=True, text="") + layout.separator() # height @@ -808,23 +810,27 @@ def brush_settings_advanced(layout, context, brush, popover=False): use_accumulate = capabilities.has_accumulate use_frontface = True + col = layout.column(heading="Auto-Masking", align=True) + # topology automasking - layout.prop(brush, "use_automasking_topology") + col.prop(brush, "use_automasking_topology", text="Topology") # face masks automasking - layout.prop(brush, "use_automasking_face_sets") - + col.prop(brush, "use_automasking_face_sets", text="Face Sets") + # boundary edges/face sets automasking - layout.prop(brush, "use_automasking_boundary_edges") - layout.prop(brush, "use_automasking_boundary_face_sets") - layout.prop(brush, "automasking_boundary_edges_propagation_steps") + col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary") + col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets") + col.prop(brush, "automasking_boundary_edges_propagation_steps") + layout.separator() # sculpt plane settings if capabilities.has_sculpt_plane: layout.prop(brush, "sculpt_plane") - layout.prop(brush, "use_original_normal") - layout.prop(brush, "use_original_plane") + col = layout.column(heading="Use Original", align=True) + col.prop(brush, "use_original_normal", text="Normal") + col.prop(brush, "use_original_plane", text="Plane") layout.separator() # 3D and 2D Texture Paint. @@ -1070,9 +1076,21 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False) row = layout.row(align=True) row.prop(brush, "size", text="Radius") row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE') + + if gp_settings.use_pressure and context.area.type == 'PROPERTIES': + col = layout.column() + col.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True, + use_negative_slope=True) + row = layout.row(align=True) row.prop(gp_settings, "pen_strength", slider=True) row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE') + + if gp_settings.use_strength_pressure and context.area.type == 'PROPERTIES': + col = layout.column() + col.template_curve_mapping(gp_settings, "curve_strength", brush=True, + use_negative_slope=True) + if brush.gpencil_tool == 'TINT': row = layout.row(align=True) row.prop(gp_settings, "vertex_mode", text="Mode") diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index 479782f1e3b..0cd99efcca9 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -310,8 +310,10 @@ def basic_force_field_settings_ui(self, field): else: col.prop(field, "flow") - col.prop(field, "apply_to_location", text="Affect Location") - col.prop(field, "apply_to_rotation", text="Affect Rotation") + sub = col.column(heading="Affect") + + sub.prop(field, "apply_to_location", text="Location") + sub.prop(field, "apply_to_rotation", text="Rotation") col = flow.column() sub = col.column(align=True) @@ -336,26 +338,29 @@ def basic_force_field_falloff_ui(self, field): if not field or field.type == 'NONE': return - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) - - col = flow.column() + col = layout.column() col.prop(field, "z_direction") col.prop(field, "falloff_power", text="Power") - col = flow.column() - col.prop(field, "use_min_distance", text="Use Minimum") - - sub = col.column(align=True) + col = layout.column(align=False, heading="Min Distance") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(field, "use_min_distance", text="") + sub = sub.row(align=True) sub.active = field.use_min_distance - sub.prop(field, "distance_min", text="Min Distance") - - col = flow.column() - col.prop(field, "use_max_distance", text="Use Maximum") - - sub = col.column(align=True) + sub.prop(field, "distance_min", text="") + row.prop_decorator(field, "distance_min") + + col = layout.column(align=False, heading="Max Distance") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(field, "use_max_distance", text="") + sub = sub.row(align=True) sub.active = field.use_max_distance - sub.prop(field, "distance_max", text="Max Distance") - + sub.prop(field, "distance_max", text="") + row.prop_decorator(field, "distance_max") classes = ( PHYSICS_PT_add, diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 30094da20c8..b1ae6290ae7 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -475,33 +475,21 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel): scene = context.scene rd = scene.render + props = scene.eevee col = layout.column() col.prop(rd, "filter_size") col.prop(rd, "film_transparent", text="Transparent") - -class RENDER_PT_eevee_film_overscan(RenderButtonsPanel, Panel): - bl_label = "Overscan" - bl_parent_id = "RENDER_PT_eevee_film" - bl_options = {'DEFAULT_CLOSED'} - COMPAT_ENGINES = {'BLENDER_EEVEE'} - - def draw_header(self, context): - - scene = context.scene - props = scene.eevee - - self.layout.prop(props, "use_overscan", text="") - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - scene = context.scene - props = scene.eevee - - layout.active = props.use_overscan - layout.prop(props, "overscan_size", text="Size") + col = layout.column(align=False, heading="Overscan") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(props, "use_overscan", text="") + sub = sub.row(align=True) + sub.active = props.use_overscan + sub.prop(props, "overscan_size", text="") + row.prop_decorator(props, "overscan_size") class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel): @@ -717,7 +705,7 @@ classes = ( RENDER_PT_eevee_indirect_lighting, RENDER_PT_eevee_indirect_lighting_display, RENDER_PT_eevee_film, - RENDER_PT_eevee_film_overscan, + RENDER_PT_gpencil, RENDER_PT_opengl_sampling, RENDER_PT_opengl_lighting, diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index 40a630ff834..5af8bc2aaa7 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -163,6 +163,8 @@ class TEXTURE_PT_node(TextureButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + node = context.texture_node ntree = node.id_data layout.template_node_view(ntree, node, None) diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py index 5fe06ebbb6e..3645f0dc2f2 100644 --- a/release/scripts/startup/bl_ui/properties_view_layer.py +++ b/release/scripts/startup/bl_ui/properties_view_layer.py @@ -40,17 +40,12 @@ class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel): layout.use_property_split = True - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - layout.use_property_split = True - scene = context.scene rd = scene.render layer = context.view_layer - col = flow.column() + col = layout.column() col.prop(layer, "use", text="Use for Rendering") - col = flow.column() col.prop(rd, "use_single_layer", text="Render Single Layer") @@ -77,14 +72,10 @@ class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel): rd = scene.render view_layer = context.view_layer - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - col = flow.column() + col = layout.column() col.prop(view_layer, "use_pass_combined") - col = flow.column() col.prop(view_layer, "use_pass_z") - col = flow.column() col.prop(view_layer, "use_pass_mist") - col = flow.column() col.prop(view_layer, "use_pass_normal") @@ -104,29 +95,19 @@ class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel): scene = context.scene scene_eevee = scene.eevee - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Diffuse") - row = split.row(align=True) - row.prop(view_layer, "use_pass_diffuse_direct", text="Light", toggle=True) - row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Specular") - row = split.row(align=True) - row.prop(view_layer, "use_pass_glossy_direct", text="Light", toggle=True) - row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Volume") - row = split.row(align=True) - row.prop(view_layer_eevee, "use_pass_volume_transmittance", text="Transmittance", toggle=True) - row.prop(view_layer_eevee, "use_pass_volume_scatter", text="Scatter", toggle=True) - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = layout.column(align=True) + col = layout.column(heading="Diffuse", align=True) + col.prop(view_layer, "use_pass_diffuse_direct", text="Light") + col.prop(view_layer, "use_pass_diffuse_color", text="Color") + + col = layout.column(heading="Specular", align=True) + col.prop(view_layer, "use_pass_glossy_direct", text="Light") + col.prop(view_layer, "use_pass_glossy_color", text="Color") + + col = layout.column(heading="Volume", align=True) + col.prop(view_layer_eevee, "use_pass_volume_transmittance", text="Transmittance") + col.prop(view_layer_eevee, "use_pass_volume_scatter", text="Scatter") + + col = layout.column(heading="Other", align=True) col.prop(view_layer, "use_pass_emit", text="Emission") col.prop(view_layer, "use_pass_environment") col.prop(view_layer, "use_pass_shadow") @@ -146,14 +127,12 @@ class VIEWLAYER_PT_eevee_layer_passes_effects(ViewLayerButtonsPanel, Panel): layout.use_property_split = True layout.use_property_decorate = False - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - view_layer = context.view_layer view_layer_eevee = view_layer.eevee scene = context.scene scene_eevee = scene.eevee - col = flow.column() + col = layout.column() col.prop(view_layer_eevee, "use_pass_bloom", text="Bloom") col.active = scene_eevee.use_bloom diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py index 705be66ecc1..6f00e521e58 100644 --- a/release/scripts/startup/bl_ui/properties_world.py +++ b/release/scripts/startup/bl_ui/properties_world.py @@ -105,6 +105,8 @@ class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel): layout.prop(world, "use_nodes", icon='NODETREE') layout.separator() + layout.use_property_split = True + if world.use_nodes: ntree = world.node_tree node = ntree.get_output_node('EEVEE') @@ -139,6 +141,8 @@ class EEVEE_WORLD_PT_volume(WorldButtonsPanel, Panel): ntree = world.node_tree node = ntree.get_output_node('EEVEE') + layout.use_property_split = True + if node: input = find_node_input(node, 'Volume') if input: diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index f93629a4f03..5b6cc6609e0 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -918,6 +918,10 @@ class CLIP_PT_tracking_lens(Panel): col = layout.column(align=True) col.prop(camera, "division_k1") col.prop(camera, "division_k2") + elif camera.distortion_model == 'NUKE': + col = layout.column(align=True) + col.prop(camera, "nuke_k1") + col.prop(camera, "nuke_k2") class CLIP_PT_marker(CLIP_PT_tracking_panel, Panel): diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 3bf5bbf7b46..9a39d840149 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -20,6 +20,7 @@ from bpy.types import Header, Panel, Menu, UIList + class FILEBROWSER_HT_header(Header): bl_space_type = 'FILE_BROWSER' @@ -31,8 +32,7 @@ class FILEBROWSER_HT_header(Header): if st.active_operator is None: layout.template_header() - layout.menu("FILEBROWSER_MT_view") - layout.menu("FILEBROWSER_MT_select") + FILEBROWSER_MT_editor_menus.draw_collapsible(context, layout) # can be None when save/reload with a file selector open @@ -66,8 +66,9 @@ class FILEBROWSER_PT_display(Panel): if params.display_type == 'THUMBNAIL': layout.prop(params, "display_size", text="Size") else: - layout.prop(params, "show_details_size", text="Size") - layout.prop(params, "show_details_datetime", text="Date") + col = layout.column(heading="Columns", align=True) + col.prop(params, "show_details_size", text="Size") + col.prop(params, "show_details_datetime", text="Date") layout.prop(params, "recursion_level", text="Recursions") @@ -410,6 +411,17 @@ class FILEBROWSER_PT_directory_path(Panel): ).region_type = 'TOOL_PROPS' +class FILEBROWSER_MT_editor_menus(Menu): + bl_idname = "FILEBROWSER_MT_editor_menus" + bl_label = "" + + def draw(self, _context): + layout = self.layout + + layout.menu("FILEBROWSER_MT_view") + layout.menu("FILEBROWSER_MT_select") + + class FILEBROWSER_MT_view(Menu): bl_label = "View" @@ -501,6 +513,7 @@ classes = ( FILEBROWSER_PT_bookmarks_recents, FILEBROWSER_PT_advanced_filter, FILEBROWSER_PT_directory_path, + FILEBROWSER_MT_editor_menus, FILEBROWSER_MT_view, FILEBROWSER_MT_select, FILEBROWSER_MT_context_menu, diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 4506307067e..bc4665209aa 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -116,7 +116,7 @@ class IMAGE_MT_view(Menu): if show_uvedit: layout.operator("image.view_selected", text="Frame Selected") - layout.operator("image.view_all", text="Frame All") + layout.operator("image.view_all") layout.operator("image.view_all", text="Frame All Fit").fit_view = True layout.operator("image.view_center_cursor", text="Center View to Cursor") @@ -384,6 +384,10 @@ class IMAGE_MT_uvs(Menu): layout.separator() + layout.operator("uv.reset") + + layout.separator() + class IMAGE_MT_uvs_select_mode(Menu): bl_label = "UV Select Mode" @@ -955,6 +959,7 @@ class IMAGE_PT_view_display_uv_edit_overlays(Panel): col = layout.column() col.prop(uvedit, "show_smooth_edges", text="Smooth") col.prop(uvedit, "show_modified_edges", text="Modified") + col.prop(uvedit, "uv_opacity") class IMAGE_PT_view_display_uv_edit_overlays_stretch(Panel): diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index bdda0ebbe9a..b5926692324 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -151,6 +151,14 @@ class NODE_HT_header(Header): if snode_id: layout.prop(snode_id, "use_nodes") + elif snode.tree_type == 'SimulationNodeTree': + row = layout.row(align=True) + row.prop(snode, "simulation", text="") + row.operator("simulation.new", text="", icon='ADD') + simulation = snode.simulation + if simulation: + row.prop(snode.simulation, "use_fake_user", text="") + else: # Custom node tree is edited as independent ID block NODE_MT_editor_menus.draw_collapsible(context, layout) diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index a74d9cc9547..ee8015df273 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -212,8 +212,8 @@ class OUTLINER_MT_collection(Menu): layout.separator() - layout.operator("outliner.collection_delete", text="Delete", icon='X').hierarchy = False - layout.operator("outliner.collection_delete", text="Delete Hierarchy").hierarchy = True + layout.operator("outliner.delete", text="Delete", icon='X') + layout.operator("outliner.collection_hierarchy_delete") layout.separator() @@ -278,7 +278,7 @@ class OUTLINER_MT_object(Menu): layout.separator() - layout.operator("outliner.object_operation", text="Delete", icon='X').type = 'DELETE' + layout.operator("outliner.delete", text="Delete", icon='X') if space.display_mode == 'VIEW_LAYER' and not space.use_filter_collection: layout.operator("outliner.object_operation", text="Delete Hierarchy").type = 'DELETE_HIERARCHY' diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 4784d0cb08b..b908e61b9e1 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -29,6 +29,7 @@ from bpy.app.translations import ( ) from bl_ui.properties_grease_pencil_common import ( AnnotationDataPanel, + AnnotationOnionSkin, ) from bl_ui.space_toolsystem_common import ( ToolActivePanelHelper, @@ -275,7 +276,7 @@ class SEQUENCER_MT_view(Menu): if is_sequencer_view: layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("sequencer.view_selected", text="Frame Selected") - layout.operator("sequencer.view_all", text="Frame All") + layout.operator("sequencer.view_all") layout.operator("view2d.zoom_border", text="Zoom") if is_preview: @@ -1138,6 +1139,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): col = layout.column(align=True) if strip_type == 'SPEED': col.prop(strip, "multiply_speed") + col.prop(strip, "frame_interpolation_mode") + elif strip_type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}: col.prop(strip, "use_default_fade", text="Default fade") if not strip.use_default_fade: @@ -1687,18 +1690,15 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel): layout = self.layout strip = act_strip(context) - layout.active = not strip.mute - - split = layout.split() + layout.use_property_split = True + layout.use_property_decorate = False - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Mirror") + layout.active = not strip.mute - col = split.column() - row = col.row(align=True) - row.prop(strip, "use_flip_x", text="X", toggle=True) - row.prop(strip, "use_flip_y", text="Y", toggle=True) + row = layout.row(heading="Mirror") + sub = row.row(align=True) + sub.prop(strip, "use_flip_x", text="X", toggle=True) + sub.prop(strip, "use_flip_y", text="Y", toggle=True) class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel): @@ -1802,12 +1802,12 @@ class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel): ed = context.scene.sequence_editor - col = layout.column() + col = layout.column(heading="Cache", align=True) - col.prop(ed, "use_cache_raw") - col.prop(ed, "use_cache_preprocessed") - col.prop(ed, "use_cache_composite") - col.prop(ed, "use_cache_final") + col.prop(ed, "use_cache_raw", text="Raw") + col.prop(ed, "use_cache_preprocessed", text="Pre-Processed") + col.prop(ed, "use_cache_composite", text="Composite") + col.prop(ed, "use_cache_final", text="Final") col.separator() col.prop(ed, "recycle_max_cost") @@ -1871,21 +1871,19 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): flow = layout.column_flow() if ed.proxy_storage == 'PER_STRIP': - flow.prop(proxy, "use_proxy_custom_directory") - flow.prop(proxy, "use_proxy_custom_file") - + col = layout.column(heading="Custom Proxy") + col.prop(proxy, "use_proxy_custom_directory", text="Directory") if proxy.use_proxy_custom_directory and not proxy.use_proxy_custom_file: - flow.prop(proxy, "directory") + col.prop(proxy, "directory") + col.prop(proxy, "use_proxy_custom_file", text="File") if proxy.use_proxy_custom_file: - flow.prop(proxy, "filepath") + col.prop(proxy, "filepath") - box = layout.box() - row = box.row(align=True) - row.prop(strip.proxy, "build_25") - row.prop(strip.proxy, "build_75") - row = box.row(align=True) - row.prop(strip.proxy, "build_50") - row.prop(strip.proxy, "build_100") + row = layout.row(heading="Resolutions", align=True) + row.prop(strip.proxy, "build_25", toggle=True) + row.prop(strip.proxy, "build_75", toggle=True) + row.prop(strip.proxy, "build_50", toggle=True) + row.prop(strip.proxy, "build_100", toggle=True) layout.use_property_split = True layout.use_property_decorate = False @@ -1926,10 +1924,10 @@ class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel): strip = act_strip(context) layout.active = strip.override_cache_settings - col = layout.column() - col.prop(strip, "use_cache_raw") - col.prop(strip, "use_cache_preprocessed") - col.prop(strip, "use_cache_composite") + col = layout.column(heading="Cache") + col.prop(strip, "use_cache_raw", text="Raw") + col.prop(strip, "use_cache_preprocessed", text="Pre-Processed") + col.prop(strip, "use_cache_composite", text="Composite") class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel): @@ -2095,10 +2093,12 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): box = layout.box() row = box.row() + row.use_property_decorate = False row.prop(mod, "show_expanded", text="", emboss=False) row.prop(mod, "name", text="") row.prop(mod, "mute", text="") + row.use_property_decorate = True sub = row.row(align=True) props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_UP') @@ -2170,6 +2170,33 @@ class SEQUENCER_PT_annotation(AnnotationDataPanel, SequencerButtonsPanel_Output, # But, it should only show up when there are images in the preview region +class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_Output, Panel): + bl_space_type = 'SEQUENCE_EDITOR' + bl_region_type = 'UI' + bl_category = "View" + + @staticmethod + def has_preview(context): + st = context.space_data + return st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'} + + @classmethod + def poll(cls, context): + if context.annotation_data_owner is None: + return False + elif type(context.annotation_data_owner) is bpy.types.Object: + return False + else: + gpl = context.active_annotation_layer + if gpl is None: + return False + + return cls.has_preview(context) + + # NOTE: this is just a wrapper around the generic GP Panel + # But, it should only show up when there are images in the preview region + + class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} _context_path = "scene.sequence_editor.active_strip" @@ -2243,6 +2270,7 @@ classes = ( SEQUENCER_PT_view_safe_areas_center_cut, SEQUENCER_PT_annotation, + SEQUENCER_PT_annotation_onion, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index b7c5dcd5437..f6f22ad464f 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -129,18 +129,21 @@ class TEXT_PT_properties(Panel): layout.use_property_decorate = False st = context.space_data - flow = layout.column_flow() if not st.text: - flow.active = False - row = flow.row(align=True) + layout.active = False + st = context.space_data - row.prop(st, "show_margin", text="Margin") - rowsub = row.row() - rowsub.active = st.show_margin - rowsub.prop(st, "margin_column", text="") - flow.prop(st, "font_size") - flow.prop(st, "tab_width") + col = layout.column(align=False, heading="Margin") + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(st, "show_margin", text="") + sub = sub.row(align=True) + sub.active = st.show_margin + sub.prop(st, "margin_column", text="") + + layout.prop(st, "font_size") + layout.prop(st, "tab_width") text = st.text if text: diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 3c9355d0017..e64a7c9731b 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -148,6 +148,8 @@ class _defs_annotate: def draw_settings_common(context, layout, tool): gpd = context.annotation_data + region_type = context.region.type + if gpd is not None: if gpd.layers.active_note is not None: text = gpd.layers.active_note @@ -160,17 +162,24 @@ class _defs_annotate: gpl = context.active_annotation_layer if gpl is not None: layout.label(text="Annotation:") - sub = layout.row(align=True) - sub.ui_units_x = 8 - - sub.prop(gpl, "color", text="") - sub.popover( - panel="TOPBAR_PT_annotation_layers", - text=text, - ) + if context.space_data.type == 'VIEW_3D': + if region_type == 'TOOL_HEADER': + sub = layout.split(align=True, factor=0.5) + sub.ui_units_x = 6.5 + sub.prop(gpl, "color", text="") + else: + sub = layout.row(align=True) + sub.prop(gpl, "color", text="") + sub.popover( + panel="TOPBAR_PT_annotation_layers", + text=text, + ) + else: + layout.prop(gpl, "color", text="") - tool_settings = context.tool_settings space_type = tool.space_type + tool_settings = context.tool_settings + if space_type == 'VIEW_3D': layout.separator() @@ -181,6 +190,29 @@ class _defs_annotate: elif tool_settings.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}: row.prop(tool_settings, "use_gpencil_stroke_endpoints") + if tool.idname == "builtin.annotate_line": + layout.separator() + + props = tool.operator_properties("gpencil.annotate") + if region_type == 'TOOL_HEADER': + row = layout.row() + row.ui_units_x = 15 + row.prop(props, "arrowstyle_start", text="Start") + row.separator() + row.prop(props, "arrowstyle_end", text="End") + else: + col = layout.row().column(align=True) + col.prop(props, "arrowstyle_start", text="Style Start") + col.prop(props, "arrowstyle_end", text="End") + elif tool.idname == "builtin.annotate" and region_type != 'TOOL_HEADER': + layout.separator() + props = tool.operator_properties("gpencil.annotate") + layout.prop(props, "use_stabilizer", text="Stabilize Stroke") + col = layout.column(align=False) + col.active = props.use_stabilizer + col.prop(props, "stabilizer_radius", text="Radius", slider=True) + col.prop(props, "stabilizer_factor", text="Factor", slider=True) + @ToolDef.from_fn.with_args(draw_settings=draw_settings_common) def scribble(*, draw_settings): return dict( @@ -628,9 +660,10 @@ class _defs_edit_mesh: layout.prop(props, "vertex_only") layout.prop(props, "clamp_overlap") layout.prop(props, "loop_slide") - layout.prop(props, "mark_seam") - layout.prop(props, "mark_sharp") layout.prop(props, "harden_normals") + col = layout.column(heading="Mark") + col.prop(props, "mark_seam", text="Seam") + col.prop(props, "mark_sharp", text="Sharp") layout.prop(props, "material") @@ -671,6 +704,19 @@ class _defs_edit_mesh: ) @ToolDef.from_fn + def extrude_dissolve_and_intersect(): + return dict( + idname="builtin.extrude_dissolve_and_intersect", + label="Extrude Dissolve and Intersect", + description=( + "Extrude, dissolves edges whose faces form a flat surface and intersect new edges" + ), + icon="none", + widget="VIEW3D_GGT_tool_generic_handle_normal", + keymap=(), + ) + + @ToolDef.from_fn def extrude_normals(): def draw_settings(_context, layout, tool): props = tool.operator_properties("mesh.extrude_region_shrink_fatten") @@ -845,23 +891,61 @@ class _defs_edit_curve: @ToolDef.from_fn def draw(): - def draw_settings(context, layout, _tool): + def draw_settings(context, layout, tool, *, extra=False): # Tool settings initialize operator options. tool_settings = context.tool_settings cps = tool_settings.curve_paint_settings + region_type = context.region.type - col = layout.column() + if region_type == 'TOOL_HEADER': + if not extra: + layout.prop(cps, "curve_type", text="") + layout.prop(cps, "depth_mode", expand=True) + layout.popover("TOPBAR_PT_tool_settings_extra", text="...") + return - col.prop(cps, "curve_type") + layout.use_property_split = True + layout.use_property_decorate = False + if region_type != 'TOOL_HEADER': + layout.prop(cps, "curve_type") + layout.separator() if cps.curve_type == 'BEZIER': - col.prop(cps, "error_threshold") - col.prop(cps, "fit_method") - col.prop(cps, "use_corners_detect") + layout.prop(cps, "fit_method") + layout.prop(cps, "error_threshold") + if region_type != 'TOOL_HEADER': + row = layout.row(heading="Detect Corners", align=True) + else: + row = layout.row(heading="Corners", align=True) + row.prop(cps, "use_corners_detect", text="") + sub = row.row(align=True) + sub.active = cps.use_corners_detect + sub.prop(cps, "corner_angle", text="") + layout.separator() + + + col = layout.column(align=True) + col.prop(cps, "radius_taper_start", text="Taper Start", slider=True) + col.prop(cps, "radius_taper_end", text="End", slider=True) + col = layout.column(align=True) + col.prop(cps, "radius_min", text="Radius Min") + col.prop(cps, "radius_max", text="Max") + col.prop(cps, "use_pressure_radius") + + layout.separator() + + if region_type != 'TOOL_HEADER': + row = layout.row() + row.prop(cps, "depth_mode", expand=True) + if cps.depth_mode == 'SURFACE': + col = layout.column() + col.prop(cps, "surface_offset") + col.prop(cps, "use_offset_absolute") + col.prop(cps, "use_stroke_endpoints") + if cps.use_stroke_endpoints: + colsub = layout.column(align=True) + colsub.prop(cps, "surface_plane") - col = layout.row() - col.active = cps.use_corners_detect - col.prop(cps, "corner_angle") return dict( idname="builtin.draw", @@ -2114,6 +2198,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): None, ( _defs_edit_mesh.extrude, + _defs_edit_mesh.extrude_dissolve_and_intersect, _defs_edit_mesh.extrude_normals, _defs_edit_mesh.extrude_individual, _defs_edit_mesh.extrude_cursor, diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 1e6f03c2b0c..7a23eb9282c 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -580,6 +580,8 @@ class TOPBAR_MT_edit(Menu): def draw(self, context): layout = self.layout + show_developer = context.preferences.view.show_developer_ui + layout.operator("ed.undo") layout.operator("ed.redo") @@ -598,8 +600,9 @@ class TOPBAR_MT_edit(Menu): layout.separator() - layout.operator("wm.search_menu", - text="Operator Search...", icon='VIEWZOOM') + layout.operator("wm.search_menu", text="Menu Search...", icon='VIEWZOOM') + if show_developer: + layout.operator("wm.search_operator", text="Operator Search...", icon='VIEWZOOM') layout.separator() diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 3d579053a97..153533dbde6 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -200,19 +200,16 @@ class USERPREF_PT_interface_display(InterfacePanel, CenterAlignMixIn, Panel): prefs = context.preferences view = prefs.view - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(view, "ui_scale", text="Resolution Scale") - flow.prop(view, "ui_line_width", text="Line Width") - - layout.separator() + col = layout.column() - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col.prop(view, "ui_scale", text="Resolution Scale") + col.prop(view, "ui_line_width", text="Line Width") + col.prop(view, "show_splash", text="Splash Screen") + col.prop(view, "show_developer_ui") - flow.prop(view, "show_splash", text="Splash Screen") - flow.prop(view, "show_tooltips") - flow.prop(view, "show_tooltips_python") - flow.prop(view, "show_developer_ui") + col = layout.column(heading="Tooltips") + col.prop(view, "show_tooltips") + col.prop(view, "show_tooltips_python") class USERPREF_PT_interface_text(InterfacePanel, CenterAlignMixIn, Panel): @@ -248,12 +245,11 @@ class USERPREF_PT_interface_translation(InterfacePanel, CenterAlignMixIn, Panel) layout.prop(view, "language") - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - flow.active = (bpy.app.translations.locale != 'en_US') - - flow.prop(view, "use_translate_tooltips", text="Tooltips") - flow.prop(view, "use_translate_interface", text="Interface") - flow.prop(view, "use_translate_new_dataname", text="New Data") + col = layout.column(heading="Affect") + col.active = (bpy.app.translations.locale != 'en_US') + col.prop(view, "use_translate_tooltips", text="Tooltips") + col.prop(view, "use_translate_interface", text="Interface") + col.prop(view, "use_translate_new_dataname", text="New Data") class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel): @@ -264,14 +260,13 @@ class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel): view = prefs.view system = prefs.system - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(system, "use_region_overlap") - flow.prop(view, "show_layout_ui", text="Corner Splitting") - flow.prop(view, "show_navigate_ui") - flow.prop(view, "color_picker_type") - flow.row().prop(view, "header_align") - flow.prop(view, "factor_display_type") + col = layout.column() + col.prop(system, "use_region_overlap") + col.prop(view, "show_layout_ui", text="Corner Splitting") + col.prop(view, "show_navigate_ui") + col.prop(view, "color_picker_type") + col.row().prop(view, "header_align") + col.prop(view, "factor_display_type") class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn, Panel): @@ -283,10 +278,9 @@ class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn, prefs = context.preferences view = prefs.view - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(view, "render_display_type", text="Render in") - flow.prop(view, "filebrowser_display_type", text="File Browser") + col = layout.column() + col.prop(view, "render_display_type", text="Render in") + col.prop(view, "filebrowser_display_type", text="File Browser") class USERPREF_PT_interface_menus(InterfacePanel, Panel): @@ -366,6 +360,7 @@ class USERPREF_PT_edit_objects_new(EditingPanel, CenterAlignMixIn, Panel): flow.prop(edit, "material_link", text="Link Materials to") flow.prop(edit, "object_align", text="Align to") flow.prop(edit, "use_enter_edit_mode", text="Enter Edit Mode") + flow.prop(edit, "collection_instance_empty_size", text="Instance Empty Size") class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Panel): @@ -376,6 +371,8 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa prefs = context.preferences edit = prefs.edit + layout.use_property_split = False + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) col = flow.column() @@ -409,10 +406,9 @@ class USERPREF_PT_edit_cursor(EditingPanel, CenterAlignMixIn, Panel): prefs = context.preferences edit = prefs.edit - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(edit, "use_mouse_depth_cursor") - flow.prop(edit, "use_cursor_lock_adjust") + col = layout.column() + col.prop(edit, "use_mouse_depth_cursor") + col.prop(edit, "use_cursor_lock_adjust") class USERPREF_PT_edit_gpencil(EditingPanel, CenterAlignMixIn, Panel): @@ -423,10 +419,9 @@ class USERPREF_PT_edit_gpencil(EditingPanel, CenterAlignMixIn, Panel): prefs = context.preferences edit = prefs.edit - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance") - flow.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance") + col = layout.column(heading="Distance") + col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan") + col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean") class USERPREF_PT_edit_annotations(EditingPanel, CenterAlignMixIn, Panel): @@ -436,10 +431,9 @@ class USERPREF_PT_edit_annotations(EditingPanel, CenterAlignMixIn, Panel): prefs = context.preferences edit = prefs.edit - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(edit, "grease_pencil_default_color", text="Default Color") - flow.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius") + col = layout.column() + col.prop(edit, "grease_pencil_default_color", text="Default Color") + col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius") class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel): @@ -450,6 +444,8 @@ class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel): prefs = context.preferences view = prefs.view + layout.use_property_split = False + layout.prop(view, "use_weight_color_range", text="Use Custom Colors") col = layout.column() @@ -465,10 +461,9 @@ class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel): prefs = context.preferences edit = prefs.edit - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color") - flow.prop(edit, "node_margin", text="Node Auto-offset Margin") + col = layout.column() + col.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color") + col.prop(edit, "node_margin", text="Node Auto-offset Margin") # ----------------------------------------------------------------------------- @@ -488,20 +483,16 @@ class USERPREF_PT_animation_timeline(AnimationPanel, CenterAlignMixIn, Panel): view = prefs.view edit = prefs.edit - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - flow.prop(edit, "use_negative_frames") - - layout.separator() - - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col = layout.column() + col.prop(edit, "use_negative_frames") - flow.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing") - flow.prop(view, "timecode_style") - flow.prop(view, "view_frame_type") + col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing") + col.prop(view, "timecode_style") + col.prop(view, "view_frame_type") if view.view_frame_type == 'SECONDS': - flow.prop(view, "view_frame_seconds") + col.prop(view, "view_frame_seconds") elif view.view_frame_type == 'KEYFRAMES': - flow.prop(view, "view_frame_keyframes") + col.prop(view, "view_frame_keyframes") class USERPREF_PT_animation_keyframes(AnimationPanel, CenterAlignMixIn, Panel): @@ -511,25 +502,14 @@ class USERPREF_PT_animation_keyframes(AnimationPanel, CenterAlignMixIn, Panel): prefs = context.preferences edit = prefs.edit - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(edit, "use_visual_keying") - flow.prop(edit, "use_keyframe_insert_needed", text="Only Insert Needed") - - -class USERPREF_PT_animation_autokey(AnimationPanel, CenterAlignMixIn, Panel): - bl_label = "Auto-Keyframing" - bl_parent_id = "USERPREF_PT_animation_keyframes" - - def draw_centered(self, context, layout): - prefs = context.preferences - edit = prefs.edit - - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col = layout.column() + col.prop(edit, "use_visual_keying") + col.prop(edit, "use_keyframe_insert_needed", text="Only Insert Needed") - flow.prop(edit, "use_auto_keying_warning", text="Show Warning") - flow.prop(edit, "use_keyframe_insert_available", text="Only Insert Available") - flow.prop(edit, "use_auto_keying", text="Enable in New Scenes") + col = layout.column(heading="Auto-Keyframing") + col.prop(edit, "use_auto_keying_warning", text="Show Warning") + col.prop(edit, "use_keyframe_insert_available", text="Only Insert Available") + col.prop(edit, "use_auto_keying", text="Enable in New Scenes") class USERPREF_PT_animation_fcurves(AnimationPanel, CenterAlignMixIn, Panel): @@ -605,23 +585,27 @@ class USERPREF_PT_system_memory(SystemPanel, CenterAlignMixIn, Panel): system = prefs.system edit = prefs.edit - layout.prop(edit, "undo_steps", text="Undo Steps") - layout.prop(edit, "undo_memory_limit", text="Undo Memory Limit") - layout.prop(edit, "use_global_undo") + col = layout.column() + col.prop(edit, "undo_steps", text="Undo Steps") + col.prop(edit, "undo_memory_limit", text="Undo Memory Limit") + col.prop(edit, "use_global_undo") layout.separator() - layout.prop(system, "texture_time_out", text="Texture Time Out") - layout.prop(system, "texture_collection_rate", text="Garbage Collection Rate") + col = layout.column() + col.prop(system, "scrollback", text="Console Scrollback Lines") layout.separator() - layout.prop(system, "vbo_time_out", text="Vbo Time Out") - layout.prop(system, "vbo_collection_rate", text="Garbage Collection Rate") + col = layout.column() + col.prop(system, "texture_time_out", text="Texture Time Out") + col.prop(system, "texture_collection_rate", text="Garbage Collection Rate") layout.separator() - layout.prop(system, "scrollback", text="Console Scrollback Lines") + col = layout.column() + col.prop(system, "vbo_time_out", text="Vbo Time Out") + col.prop(system, "vbo_collection_rate", text="Garbage Collection Rate") class USERPREF_PT_system_video_sequencer(SystemPanel, CenterAlignMixIn, Panel): @@ -660,23 +644,19 @@ class USERPREF_PT_viewport_display(ViewportPanel, CenterAlignMixIn, Panel): prefs = context.preferences view = prefs.view - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(view, "show_object_info", text="Object Info") - flow.prop(view, "show_view_name", text="View Name") - flow.prop(view, "show_playback_fps", text="Playback FPS") + col = layout.column(heading="Show") + col.prop(view, "show_object_info", text="Object Info") + col.prop(view, "show_view_name", text="View Name") + col.prop(view, "show_playback_fps", text="Playback FPS") layout.separator() - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() + col = layout.column() col.prop(view, "gizmo_size") col.prop(view, "lookdev_sphere_size") - flow.separator() + col.separator() - col = flow.column() col.prop(view, "mini_axis_type", text="3D Viewport Axis") if view.mini_axis_type == 'MINIMAL': @@ -691,11 +671,12 @@ class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel): prefs = context.preferences system = prefs.system - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col = layout.column() + col.prop(system, "viewport_aa") - flow.prop(system, "viewport_aa") - flow.prop(system, "use_overlay_smooth_wire") - flow.prop(system, "use_edit_mode_smooth_wire") + col = layout.column(heading="Smooth Wires") + col.prop(system, "use_overlay_smooth_wire", text="Overlay") + col.prop(system, "use_edit_mode_smooth_wire", text="Edit Mode") class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel): @@ -705,12 +686,11 @@ class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel): prefs = context.preferences system = prefs.system - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(system, "gl_texture_limit", text="Limit Size") - flow.prop(system, "anisotropic_filter") - flow.prop(system, "gl_clip_alpha", slider=True) - flow.prop(system, "image_draw_method", text="Image Display Method") + col = layout.column() + col.prop(system, "gl_texture_limit", text="Limit Size") + col.prop(system, "anisotropic_filter") + col.prop(system, "gl_clip_alpha", slider=True) + col.prop(system, "image_draw_method", text="Image Display Method") class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel): @@ -721,9 +701,7 @@ class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel): prefs = context.preferences system = prefs.system - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(system, "use_select_pick_depth") + layout.prop(system, "use_select_pick_depth") # ----------------------------------------------------------------------------- @@ -1331,37 +1309,40 @@ class USERPREF_PT_saveload_blend(SaveLoadPanel, CenterAlignMixIn, Panel): paths = prefs.filepaths view = prefs.view - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(paths, "use_relative_paths") - flow.prop(paths, "use_file_compression") - flow.prop(paths, "use_load_ui") - flow.prop(paths, "use_save_preview_images") - flow.prop(paths, "use_tabs_as_spaces") - flow.prop(view, "use_save_prompt") + col = layout.column(heading="Save") + col.prop(view, "use_save_prompt") + col.prop(paths, "use_save_preview_images") - layout.separator() + col = layout.column(heading="Default to") + col.prop(paths, "use_relative_paths") + col.prop(paths, "use_file_compression") + col.prop(paths, "use_load_ui") - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col = layout.column(heading="Text Files") + col.prop(paths, "use_tabs_as_spaces") - flow.prop(paths, "save_version") - flow.prop(paths, "recent_files") + col = layout.column() + col.prop(paths, "save_version") + col.prop(paths, "recent_files") class USERPREF_PT_saveload_blend_autosave(SaveLoadPanel, CenterAlignMixIn, Panel): bl_label = "Auto Save" bl_parent_id = "USERPREF_PT_saveload_blend" - def draw_centered(self, context, layout): + def draw_header(self, context): prefs = context.preferences paths = prefs.filepaths - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + self.layout.prop(paths, "use_auto_save_temporary_files", text="") - flow.prop(paths, "use_auto_save_temporary_files") - sub = flow.column() - sub.active = paths.use_auto_save_temporary_files - sub.prop(paths, "auto_save_time", text="Timer (mins)") + def draw_centered(self, context, layout): + prefs = context.preferences + paths = prefs.filepaths + + col = layout.column() + col.active = paths.use_auto_save_temporary_files + col.prop(paths, "auto_save_time", text="Timer (mins)") class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel): @@ -1371,12 +1352,13 @@ class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel): prefs = context.preferences paths = prefs.filepaths - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col = layout.column() + col.prop(paths, "use_filter_files") - flow.prop(paths, "use_filter_files") - flow.prop(paths, "show_hidden_files_datablocks") - flow.prop(paths, "hide_recent_locations") - flow.prop(paths, "hide_system_bookmarks") + col = layout.column(heading="Hide") + col.prop(paths, "show_hidden_files_datablocks", text="Dot File & Datablocks") + col.prop(paths, "hide_recent_locations", text="Recent Locations") + col.prop(paths, "hide_system_bookmarks", text="System Bookmarks") # ----------------------------------------------------------------------------- @@ -1435,10 +1417,9 @@ class USERPREF_PT_input_tablet(InputPanel, CenterAlignMixIn, Panel): layout.prop(inputs, "tablet_api") layout.separator() - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(inputs, "pressure_threshold_max") - flow.prop(inputs, "pressure_softness") + col = layout.column() + col.prop(inputs, "pressure_threshold_max") + col.prop(inputs, "pressure_softness") class USERPREF_PT_input_ndof(InputPanel, CenterAlignMixIn, Panel): @@ -1485,24 +1466,27 @@ class USERPREF_PT_navigation_orbit(NavigationPanel, CenterAlignMixIn, Panel): inputs = prefs.inputs view = prefs.view - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col = layout.column() - flow.row().prop(inputs, "view_rotate_method", expand=True) + col.row().prop(inputs, "view_rotate_method", expand=True) if inputs.view_rotate_method == 'TURNTABLE': - flow.prop(inputs, "view_rotate_sensitivity_turntable") + col.prop(inputs, "view_rotate_sensitivity_turntable") else: - flow.prop(inputs, "view_rotate_sensitivity_trackball") + col.prop(inputs, "view_rotate_sensitivity_trackball") + col.prop(inputs, "use_rotate_around_active") + + col.separator() - flow.prop(inputs, "use_rotate_around_active") - flow.prop(inputs, "use_auto_perspective") - flow.prop(inputs, "use_mouse_depth_navigate") if sys.platform == "darwin": - flow.prop(inputs, "use_trackpad_natural", text="Natural Trackpad Direction") + col.prop(inputs, "use_trackpad_natural", text="Natural Trackpad Direction") - flow.separator() + col = layout.column(heading="Auto") + col.prop(inputs, "use_auto_perspective", text="Perspective") + col.prop(inputs, "use_mouse_depth_navigate", text="Depth") - flow.prop(view, "smooth_view") - flow.prop(view, "rotation_angle") + col = layout.column() + col.prop(view, "smooth_view") + col.prop(view, "rotation_angle") class USERPREF_PT_navigation_zoom(NavigationPanel, CenterAlignMixIn, Panel): @@ -1512,16 +1496,20 @@ class USERPREF_PT_navigation_zoom(NavigationPanel, CenterAlignMixIn, Panel): prefs = context.preferences inputs = prefs.inputs - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + col = layout.column() - flow.row().prop(inputs, "view_zoom_method", text="Zoom Method") + col.row().prop(inputs, "view_zoom_method", text="Zoom Method") if inputs.view_zoom_method in {'DOLLY', 'CONTINUE'}: - flow.row().prop(inputs, "view_zoom_axis") - flow.prop(inputs, "invert_mouse_zoom", text="Invert Mouse Zoom Direction") + col.row().prop(inputs, "view_zoom_axis") + col.prop(inputs, "use_zoom_to_mouse") + col = layout.column(heading="Invert Zoom Direction", align=True) + col.prop(inputs, "invert_mouse_zoom", text="Mouse") + col.prop(inputs, "invert_zoom_wheel", text="Wheel") + else: + col.prop(inputs, "use_zoom_to_mouse") + col.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction") - flow.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction") # sub.prop(view, "wheel_scroll_lines", text="Scroll Lines") - flow.prop(inputs, "use_zoom_to_mouse") class USERPREF_PT_navigation_fly_walk(NavigationPanel, CenterAlignMixIn, Panel): @@ -1552,15 +1540,14 @@ class USERPREF_PT_navigation_fly_walk_navigation(NavigationPanel, CenterAlignMix inputs = prefs.inputs walk = inputs.walk_navigation - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(walk, "use_mouse_reverse") - flow.prop(walk, "mouse_speed") - flow.prop(walk, "teleport_time") + col = layout.column() + col.prop(walk, "use_mouse_reverse") + col.prop(walk, "mouse_speed") + col.prop(walk, "teleport_time") - sub = flow.column(align=True) - sub.prop(walk, "walk_speed") - sub.prop(walk, "walk_speed_factor") + col = layout.column(align=True) + col.prop(walk, "walk_speed") + col.prop(walk, "walk_speed_factor") class USERPREF_PT_navigation_fly_walk_gravity(NavigationPanel, CenterAlignMixIn, Panel): @@ -1587,10 +1574,9 @@ class USERPREF_PT_navigation_fly_walk_gravity(NavigationPanel, CenterAlignMixIn, layout.active = walk.use_gravity - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - - flow.prop(walk, "view_height") - flow.prop(walk, "jump_height") + col = layout.column() + col.prop(walk, "view_height") + col.prop(walk, "jump_height") # Special case, this is only exposed as a popover. @@ -2135,7 +2121,7 @@ class ExperimentalPanel: experimental = prefs.experimental layout = self.layout - layout.use_property_split = True + layout.use_property_split = False layout.use_property_decorate = False for prop_keywords, task in items: @@ -2161,16 +2147,6 @@ class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel): ) """ -class USERPREF_PT_experimental_ui(ExperimentalPanel, Panel): - bl_label = "UI" - - def draw(self, context): - self._draw_items( - context, ( - ({"property": "use_menu_search"}, "T74157"), - ), - ) - class USERPREF_PT_experimental_system(ExperimentalPanel, Panel): bl_label = "System" @@ -2223,7 +2199,6 @@ classes = ( USERPREF_PT_animation_timeline, USERPREF_PT_animation_keyframes, - USERPREF_PT_animation_autokey, USERPREF_PT_animation_fcurves, USERPREF_PT_system_cycles_devices, @@ -2274,7 +2249,6 @@ classes = ( # Popovers. USERPREF_PT_ndof_settings, - USERPREF_PT_experimental_ui, USERPREF_PT_experimental_system, # Add dynamically generated editor theme panels last, diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index fca4cb4c321..ebc3263f9cc 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -125,7 +125,6 @@ class VIEW3D_HT_tool_header(Header): if brush.gpencil_tool not in {'FILL', 'TINT'}: layout.popover("VIEW3D_PT_tools_grease_pencil_brush_stroke") - layout.popover("VIEW3D_PT_tools_grease_pencil_brushcurves") layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance") elif tool_mode == 'SCULPT_GPENCIL': @@ -830,18 +829,17 @@ class VIEW3D_HT_header(Header): # While exposing 'shading.show_xray(_wireframe)' is correct. # this hides the key shortcut from users: T70433. + if has_pose_mode: + draw_depressed = overlay.show_xray_bone + elif shading.type == 'WIREFRAME': + draw_depressed = shading.show_xray_wireframe + else: + draw_depressed = shading.show_xray row.operator( "view3d.toggle_xray", text="", icon='XRAY', - depress=( - overlay.show_xray_bone if has_pose_mode else - getattr( - shading, - "show_xray_wireframe" if shading.type == 'WIREFRAME' else - "show_xray" - ) - ), + depress=draw_depressed, ) row = layout.row(align=True) @@ -1165,7 +1163,7 @@ class VIEW3D_MT_view(Menu): if view.region_quadviews: layout.operator("view3d.view_selected", text="Frame Selected (Quad View)").use_all_regions = True - layout.operator("view3d.view_all", text="Frame All").center = False + layout.operator("view3d.view_all").center = False layout.operator("view3d.view_persportho", text="Perspective/Orthographic") layout.menu("VIEW3D_MT_view_local") @@ -1296,7 +1294,7 @@ class VIEW3D_MT_view_align(Menu): layout.separator() - layout.operator("view3d.view_all", text="Center Cursor and View All").center = True + layout.operator("view3d.view_all", text="Center Cursor and Frame All").center = True layout.operator("view3d.view_center_cursor") layout.separator() @@ -3764,11 +3762,6 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu): col.separator() - col.operator("mesh.mark_seam").clear = False - col.operator("mesh.mark_seam", text="Clear Seam").clear = True - - col.separator() - col.operator("mesh.mark_sharp") col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True @@ -4014,11 +4007,6 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.separator() - layout.operator("mesh.mark_seam").clear = False - layout.operator("mesh.mark_seam", text="Clear Seam").clear = True - - layout.separator() - layout.operator("mesh.mark_sharp") layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True @@ -5302,6 +5290,7 @@ class VIEW3D_MT_sculpt_mask_edit_pie(Menu): op.auto_iteration_count = False class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu): + bl_label = "Face Sets Edit" def draw(self, _context): @@ -5397,8 +5386,8 @@ class VIEW3D_PT_view3d_properties(Panel): layout.use_property_split = True layout.use_property_decorate = False # No animation. - flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True) - col = flow.column() + + col = layout.column() subcol = col.column() subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews) @@ -5408,20 +5397,22 @@ class VIEW3D_PT_view3d_properties(Panel): subcol.prop(view, "clip_start", text="Clip Start") subcol.prop(view, "clip_end", text="End") - subcol.separator() - - col = flow.column() + layout.separator() - subcol = col.column() - subcol.prop(view, "use_local_camera") + col = layout.column(align=False, heading="Local Camera") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(view, "use_local_camera", text="") + sub = sub.row(align=True) + sub.enabled = view.use_local_camera + sub.prop(view, "camera", text="") - subcol = col.column() - subcol.enabled = view.use_local_camera - subcol.prop(view, "camera", text="Local Camera") + layout.separator() - subcol = col.column(align=True) - subcol.prop(view, "use_render_border") - subcol.active = view.region_3d.view_perspective != 'CAMERA' + col = layout.column(align=True) + col.prop(view, "use_render_border") + col.active = view.region_3d.view_perspective != 'CAMERA' class VIEW3D_PT_view3d_lock(Panel): @@ -5440,23 +5431,24 @@ class VIEW3D_PT_view3d_lock(Panel): view = context.space_data col = layout.column(align=True) - subcol = col.column() - subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews) + sub = col.column() + sub.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews) - subcol.prop(view, "lock_object") + sub.prop(view, "lock_object") lock_object = view.lock_object if lock_object: if lock_object.type == 'ARMATURE': - subcol.prop_search( + sub.prop_search( view, "lock_bone", lock_object.data, "edit_bones" if lock_object.mode == 'EDIT' else "bones", text="", ) else: - subcol.prop(view, "lock_cursor", text="Lock to 3D Cursor") + subcol = sub.column(heading="Lock") + subcol.prop(view, "lock_cursor", text="To 3D Cursor") - col.prop(view, "lock_camera") + col.prop(view, "lock_camera", text="Camera to View") class VIEW3D_PT_view3d_cursor(Panel): @@ -6046,16 +6038,17 @@ class VIEW3D_PT_overlay_guides(Panel): split = col.split() sub = split.column() sub.prop(overlay, "show_text", text="Text Info") + sub.prop(overlay, "show_stats", text="Statistics") + sub = split.column() sub.prop(overlay, "show_cursor", text="3D Cursor") + sub.prop(overlay, "show_annotation", text="Annotations") if shading.type == 'MATERIAL': row = col.row() row.active = shading.render_pass == 'COMBINED' row.prop(overlay, "show_look_dev") - col.prop(overlay, "show_annotation", text="Annotations") - class VIEW3D_PT_overlay_object(Panel): bl_space_type = 'VIEW_3D' @@ -7056,6 +7049,18 @@ def draw_gpencil_layer_active(context, layout): row.operator("gpencil.layer_remove", text="", icon='X') +def draw_gpencil_material_active(context, layout): + ob = context.active_object + if ob and len(ob.material_slots) > 0 and ob.active_material_index >= 0: + ma = ob.material_slots[ob.active_material_index].material + if ma: + layout.label(text="Active Material") + row = layout.row(align=True) + row.operator_context = 'EXEC_REGION_WIN' + row.operator_menu_enum("gpencil.material_set", "slot", text="", icon='MATERIAL') + row.prop(ma, "name", text="") + + class VIEW3D_PT_gpencil_sculpt_context_menu(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'WINDOW' @@ -7129,6 +7134,9 @@ class VIEW3D_PT_gpencil_draw_context_menu(Panel): # Layers draw_gpencil_layer_active(context, layout) + # Material + if not is_vertex: + draw_gpencil_material_active(context, layout) class VIEW3D_PT_gpencil_vertex_context_menu(Panel): diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 6aaeec3f3cf..b81f48bec5e 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -125,21 +125,15 @@ class View3DPanel: # Used by vertex & weight paint def draw_vpaint_symmetry(layout, vpaint): - split = layout.split() - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Mirror") + col = layout.column() + col.use_property_split = True + col.use_property_decorate = False - col = split.column() - row = col.row(align=True) + row = col.row(heading="Mirror", align=True) row.prop(vpaint, "use_symmetry_x", text="X", toggle=True) row.prop(vpaint, "use_symmetry_y", text="Y", toggle=True) row.prop(vpaint, "use_symmetry_z", text="Z", toggle=True) - col = layout.column() - col.use_property_split = True - col.use_property_decorate = False col.prop(vpaint, "radial_symmetry", text="Radial") @@ -179,10 +173,10 @@ class VIEW3D_PT_tools_object_options_transform(View3DPanel, Panel): tool_settings = context.tool_settings - layout.label(text="Affect Only") - layout.prop(tool_settings, "use_transform_data_origin", text="Origins") - layout.prop(tool_settings, "use_transform_pivot_point_align", text="Locations") - layout.prop(tool_settings, "use_transform_skip_children", text="Parents") + col = layout.column(heading="Affect Only", align=True) + col.prop(tool_settings, "use_transform_data_origin", text="Origins") + col.prop(tool_settings, "use_transform_pivot_point_align", text="Locations") + col.prop(tool_settings, "use_transform_skip_children", text="Parents") # ********** default tools for editmode_mesh **************** @@ -209,16 +203,11 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel): split = layout.split() - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Mirror") - - col = split.column() - - row = col.row(align=True) - row.prop(mesh, "use_mirror_x", text="X", toggle=True) - row.prop(mesh, "use_mirror_y", text="Y", toggle=True) - row.prop(mesh, "use_mirror_z", text="Z", toggle=True) + row = layout.row(heading="Mirror") + sub = row.row(align=True) + sub.prop(mesh, "use_mirror_x", text="X", toggle=True) + sub.prop(mesh, "use_mirror_y", text="Y", toggle=True) + sub.prop(mesh, "use_mirror_z", text="Z", toggle=True) row = layout.row(align=True) row.active = ob.data.use_mirror_x or ob.data.use_mirror_y or ob.data.use_mirror_z @@ -254,62 +243,6 @@ class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel): col.prop(tool_settings, "use_mesh_automerge_and_split", toggle=False) col.prop(tool_settings, "double_threshold", text="Threshold") -# ********** default tools for editmode_curve **************** - - -class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel): - bl_category = "Tool" - bl_context = ".curve_edit" # dot on purpose (access from topbar) - bl_label = "Curve Stroke" - - def draw(self, context): - layout = self.layout - - tool_settings = context.tool_settings - cps = tool_settings.curve_paint_settings - - col = layout.column() - - col.prop(cps, "curve_type") - - if cps.curve_type == 'BEZIER': - col.label(text="Bezier Options:") - col.prop(cps, "error_threshold") - col.prop(cps, "fit_method") - col.prop(cps, "use_corners_detect") - - col = layout.column() - col.active = cps.use_corners_detect - col.prop(cps, "corner_angle") - - col.label(text="Pressure Radius:") - row = layout.row(align=True) - rowsub = row.row(align=True) - rowsub.prop(cps, "radius_min", text="Min") - rowsub.prop(cps, "radius_max", text="Max") - - row.prop(cps, "use_pressure_radius", text="", icon_only=True) - - col = layout.column() - col.label(text="Taper Radius:") - row = layout.row(align=True) - row.prop(cps, "radius_taper_start", text="Start") - row.prop(cps, "radius_taper_end", text="End") - - col = layout.column() - col.label(text="Projection Depth:") - row = layout.row(align=True) - row.prop(cps, "depth_mode", expand=True) - - col = layout.column() - if cps.depth_mode == 'SURFACE': - col.prop(cps, "surface_offset") - col.prop(cps, "use_offset_absolute") - col.prop(cps, "use_stroke_endpoints") - if cps.use_stroke_endpoints: - colsub = layout.column(align=True) - colsub.prop(cps, "surface_plane", expand=True) - # ********** default tools for editmode_armature **************** @@ -872,10 +805,13 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel): col.prop(mesh, "remesh_voxel_adaptivity") col.prop(mesh, "use_remesh_fix_poles") col.prop(mesh, "use_remesh_smooth_normals") - col.prop(mesh, "use_remesh_preserve_volume") - col.prop(mesh, "use_remesh_preserve_paint_mask") - col.prop(mesh, "use_remesh_preserve_sculpt_face_sets") - col.operator("object.voxel_remesh", text="Remesh") + + col = layout.column(heading="Preserve", align=True) + col.prop(mesh, "use_remesh_preserve_volume", text="Volume") + col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask") + col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets") + + layout.operator("object.voxel_remesh", text="Remesh") # TODO, move to space_view3d.py @@ -896,23 +832,19 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel): tool_settings = context.tool_settings sculpt = tool_settings.sculpt - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() + col = layout.column(heading="Display", align=True) col.prop(sculpt, "use_threaded", text="Threaded Sculpt") - col = flow.column() col.prop(sculpt, "show_low_resolution") - col = flow.column() col.prop(sculpt, "use_sculpt_delay_updates") - col = flow.column() col.prop(sculpt, "use_deform_only") - col = flow.column() col.separator() - col.prop(sculpt, "use_automasking_topology") - col.prop(sculpt, "use_automasking_face_sets") - col.prop(sculpt, "use_automasking_boundary_edges") - col.prop(sculpt, "use_automasking_boundary_face_sets") + + col = layout.column(heading="Auto-Masking", align=True) + col.prop(sculpt, "use_automasking_topology", text="Topology") + col.prop(sculpt, "use_automasking_face_sets", text="Face Sets") + col.prop(sculpt, "use_automasking_boundary_edges", text="Boundary Edges") + col.prop(sculpt, "use_automasking_boundary_face_sets", text="Boundary Face Sets") class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel): @@ -955,61 +887,34 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False sculpt = context.tool_settings.sculpt - split = layout.split() - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Mirror") - - col = split.column() - - row = col.row(align=True) + row = layout.row(align=True, heading="Mirror") row.prop(sculpt, "use_symmetry_x", text="X", toggle=True) row.prop(sculpt, "use_symmetry_y", text="Y", toggle=True) row.prop(sculpt, "use_symmetry_z", text="Z", toggle=True) - split = layout.split() - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Lock") - - col = split.column() - - row = col.row(align=True) + row = layout.row(align=True, heading="Lock") row.prop(sculpt, "lock_x", text="X", toggle=True) row.prop(sculpt, "lock_y", text="Y", toggle=True) row.prop(sculpt, "lock_z", text="Z", toggle=True) - split = layout.split() - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Tiling") - - col = split.column() - - row = col.row(align=True) + row = layout.row(align=True, heading="Tiling") row.prop(sculpt, "tile_x", text="X", toggle=True) row.prop(sculpt, "tile_y", text="Y", toggle=True) row.prop(sculpt, "tile_z", text="Z", toggle=True) - layout.use_property_split = True - layout.use_property_decorate = False - layout.prop(sculpt, "use_symmetry_feather", text="Feather") - layout.column().prop(sculpt, "radial_symmetry", text="Radial") - layout.column().prop(sculpt, "tile_offset", text="Tile Offset") + layout.prop(sculpt, "radial_symmetry", text="Radial") + layout.prop(sculpt, "tile_offset", text="Tile Offset") layout.separator() - col = layout.column() - - col.prop(sculpt, "symmetrize_direction") - col.operator("sculpt.symmetrize") + layout.prop(sculpt, "symmetrize_direction") + layout.operator("sculpt.symmetrize") class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel): @@ -1212,12 +1117,8 @@ class VIEW3D_PT_tools_imagepaint_options(View3DPaintPanel, Panel): layout.prop(ipaint, "seam_bleed") layout.prop(ipaint, "dither", slider=True) - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() + col = layout.column() col.prop(ipaint, "use_occlude") - - col = flow.column() col.prop(ipaint, "use_backface_culling", text="Backface Culling") @@ -1649,7 +1550,9 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel): layout.use_property_split = True layout.use_property_decorate = False - brush = context.tool_settings.gpencil_paint.brush + tool_settings = context.tool_settings + brush = tool_settings.gpencil_paint.brush + mode = tool_settings.gpencil_paint.color_mode gp_settings = brush.gpencil_settings if self.is_popover: @@ -1658,83 +1561,68 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel): row.label(text=self.bl_label) col = layout.column() - col.active = gp_settings.use_settings_random - - col.prop(gp_settings, "random_pressure", text="Pressure", slider=True) - col.prop(gp_settings, "random_strength", text="Strength", slider=True) - col.prop(gp_settings, "uv_random", text="UV", slider=True) + col.enabled = gp_settings.use_settings_random row = col.row(align=True) - row.prop(gp_settings, "pen_jitter", slider=True) - row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE') - - -# Grease Pencil drawingcurves -class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel): - bl_context = ".greasepencil_paint" - bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings' - bl_label = "Curves" - bl_category = "Tool" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - brush = context.tool_settings.gpencil_paint.brush - return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'} - - def draw(self, context): - pass - - -class VIEW3D_PT_tools_grease_pencil_brushcurves_sensitivity(View3DPanel, Panel): - bl_context = ".greasepencil_paint" - bl_label = "Sensitivity" - bl_category = "Tool" - bl_parent_id = "VIEW3D_PT_tools_grease_pencil_brushcurves" - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - - brush = context.tool_settings.gpencil_paint.brush - gp_settings = brush.gpencil_settings - - layout.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True, - use_negative_slope=True) - - -class VIEW3D_PT_tools_grease_pencil_brushcurves_strength(View3DPanel, Panel): - bl_context = ".greasepencil_paint" - bl_label = "Strength" - bl_category = "Tool" - bl_parent_id = "VIEW3D_PT_tools_grease_pencil_brushcurves" - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - - brush = context.tool_settings.gpencil_paint.brush - gp_settings = brush.gpencil_settings + row.prop(gp_settings, "random_pressure", text="Radius", slider=True) + row.prop(gp_settings, "use_stroke_random_radius", text="", icon='GP_SELECT_STROKES') + row.prop(gp_settings, "use_random_press_radius", text="", icon='STYLUS_PRESSURE') + if gp_settings.use_random_press_radius and self.is_popover is False: + col.template_curve_mapping(gp_settings, "curve_random_pressure", brush=True, + use_negative_slope=True) - layout.template_curve_mapping(gp_settings, "curve_strength", brush=True, - use_negative_slope=True) + row = col.row(align=True) + row.prop(gp_settings, "random_strength", text="Strength", slider=True) + row.prop(gp_settings, "use_stroke_random_strength", text="", icon='GP_SELECT_STROKES') + row.prop(gp_settings, "use_random_press_strength", text="", icon='STYLUS_PRESSURE') + if gp_settings.use_random_press_strength and self.is_popover is False: + col.template_curve_mapping(gp_settings, "curve_random_strength", brush=True, + use_negative_slope=True) + row = col.row(align=True) + row.prop(gp_settings, "uv_random", text="UV", slider=True) + row.prop(gp_settings, "use_stroke_random_uv", text="", icon='GP_SELECT_STROKES') + row.prop(gp_settings, "use_random_press_uv", text="", icon='STYLUS_PRESSURE') + if gp_settings.use_random_press_uv and self.is_popover is False: + col.template_curve_mapping(gp_settings, "curve_random_uv", brush=True, + use_negative_slope=True) -class VIEW3D_PT_tools_grease_pencil_brushcurves_jitter(View3DPanel, Panel): - bl_context = ".greasepencil_paint" - bl_label = "Jitter" - bl_category = "Tool" - bl_parent_id = "VIEW3D_PT_tools_grease_pencil_brushcurves" + col.separator() - def draw(self, context): - layout = self.layout - layout.use_property_split = True + col1 = col.column(align=True) + col1.enabled = mode == 'VERTEXCOLOR' and gp_settings.use_settings_random + row = col1.row(align=True) + row.prop(gp_settings, "random_hue_factor", slider=True) + row.prop(gp_settings, "use_stroke_random_hue", text="", icon='GP_SELECT_STROKES') + row.prop(gp_settings, "use_random_press_hue", text="", icon='STYLUS_PRESSURE') + if gp_settings.use_random_press_hue and self.is_popover is False: + col1.template_curve_mapping(gp_settings, "curve_random_hue", brush=True, + use_negative_slope=True) + + row = col1.row(align=True) + row.prop(gp_settings, "random_saturation_factor", slider=True) + row.prop(gp_settings, "use_stroke_random_sat", text="", icon='GP_SELECT_STROKES') + row.prop(gp_settings, "use_random_press_sat", text="", icon='STYLUS_PRESSURE') + if gp_settings.use_random_press_sat and self.is_popover is False: + col1.template_curve_mapping(gp_settings, "curve_random_saturation", brush=True, + use_negative_slope=True) + + row = col1.row(align=True) + row.prop(gp_settings, "random_value_factor", slider=True) + row.prop(gp_settings, "use_stroke_random_val", text="", icon='GP_SELECT_STROKES') + row.prop(gp_settings, "use_random_press_val", text="", icon='STYLUS_PRESSURE') + if gp_settings.use_random_press_val and self.is_popover is False: + col1.template_curve_mapping(gp_settings, "curve_random_value", brush=True, + use_negative_slope=True) - brush = context.tool_settings.gpencil_paint.brush - gp_settings = brush.gpencil_settings + col.separator() - layout.template_curve_mapping(gp_settings, "curve_jitter", brush=True, - use_negative_slope=True) + row = col.row(align=True) + row.prop(gp_settings, "pen_jitter", slider=True) + row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE') + if gp_settings.use_jitter_pressure and self.is_popover is False: + col.template_curve_mapping(gp_settings, "curve_jitter", brush=True, + use_negative_slope=True) class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel): @@ -2230,12 +2118,14 @@ class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilDisplayPanel, bl_category = "Tool" bl_label = "Cursor" + class VIEW3D_PT_tools_grease_pencil_vertex_appearance(GreasePencilDisplayPanel, Panel, View3DPanel): bl_context = ".greasepencil_vertex" bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_vertex_paint_settings' bl_category = "Tool" bl_label = "Cursor" + class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel): """Brush settings""" bl_label = "Brush Presets" @@ -2252,7 +2142,6 @@ classes = ( VIEW3D_PT_tools_object_options_transform, VIEW3D_PT_tools_meshedit_options, VIEW3D_PT_tools_meshedit_options_automerge, - VIEW3D_PT_tools_curveedit_options_stroke, VIEW3D_PT_tools_armatureedit_options, VIEW3D_PT_tools_posemode_options, @@ -2312,10 +2201,6 @@ classes = ( VIEW3D_PT_tools_grease_pencil_brush_post_processing, VIEW3D_PT_tools_grease_pencil_brush_random, VIEW3D_PT_tools_grease_pencil_brush_stabilizer, - VIEW3D_PT_tools_grease_pencil_brushcurves, - VIEW3D_PT_tools_grease_pencil_brushcurves_sensitivity, - VIEW3D_PT_tools_grease_pencil_brushcurves_strength, - VIEW3D_PT_tools_grease_pencil_brushcurves_jitter, VIEW3D_PT_tools_grease_pencil_paint_appearance, VIEW3D_PT_tools_grease_pencil_sculpt_select, VIEW3D_PT_tools_grease_pencil_sculpt_settings, diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 969a1ca1bd7..2dc6c6cd409 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -58,6 +58,13 @@ class TextureNodeCategory(SortedNodeCategory): context.space_data.tree_type == 'TextureNodeTree') +class SimulationNodeCategory(SortedNodeCategory): + @classmethod + def poll(cls, context): + return (context.space_data.type == 'NODE_EDITOR' and + context.space_data.tree_type == 'SimulationNodeTree') + + # menu entry for node group tools def group_tools_draw(self, layout, context): layout.operator("node.group_make") @@ -70,10 +77,11 @@ node_tree_group_type = { 'CompositorNodeTree': 'CompositorNodeGroup', 'ShaderNodeTree': 'ShaderNodeGroup', 'TextureNodeTree': 'TextureNodeGroup', + 'SimulationNodeTree': 'SimulationNodeGroup', } -# generic node group items generator for shader, compositor and texture node groups +# generic node group items generator for shader, compositor, simulation and texture node groups def node_group_items(context): if context is None: return @@ -467,17 +475,81 @@ texture_node_categories = [ ]), ] +simulation_node_categories = [ + # Simulation Nodes + SimulationNodeCategory("SIM_OUTPUT", "Output", items=[ + NodeItem("SimulationNodeParticleSimulation"), + ]), + SimulationNodeCategory("SIM_INPUTS", "Input", items=[ + NodeItem("SimulationNodeTime"), + NodeItem("SimulationNodeParticleAttribute"), + NodeItem("FunctionNodeGroupInstanceID"), + ]), + SimulationNodeCategory("SIM_EMITTERS", "Emitters", items=[ + NodeItem("SimulationNodeParticleMeshEmitter"), + NodeItem("SimulationNodeEmitParticles"), + ]), + SimulationNodeCategory("SIM_EVENTS", "Events", items=[ + NodeItem("SimulationNodeParticleBirthEvent"), + NodeItem("SimulationNodeParticleTimeStepEvent"), + NodeItem("SimulationNodeParticleMeshCollisionEvent"), + ]), + SimulationNodeCategory("SIM_FORCES", "Forces", items=[ + NodeItem("SimulationNodeForce"), + ]), + SimulationNodeCategory("SIM_EXECUTE", "Execute", items=[ + NodeItem("SimulationNodeSetParticleAttribute"), + NodeItem("SimulationNodeExecuteCondition"), + NodeItem("SimulationNodeMultiExecute"), + ]), + SimulationNodeCategory("SIM_NOISE", "Noise", items=[ + NodeItem("ShaderNodeTexNoise"), + NodeItem("ShaderNodeTexWhiteNoise"), + ]), + SimulationNodeCategory("SIM_COLOR", "Color", items=[ + NodeItem("ShaderNodeMixRGB"), + NodeItem("ShaderNodeInvert"), + NodeItem("ShaderNodeHueSaturation"), + NodeItem("ShaderNodeGamma"), + NodeItem("ShaderNodeBrightContrast"), + ]), + SimulationNodeCategory("SIM_CONVERTER", "Converter", items=[ + NodeItem("ShaderNodeMapRange"), + NodeItem("ShaderNodeClamp"), + NodeItem("ShaderNodeMath"), + NodeItem("ShaderNodeValToRGB"), + NodeItem("ShaderNodeVectorMath"), + NodeItem("ShaderNodeSeparateRGB"), + NodeItem("ShaderNodeCombineRGB"), + NodeItem("ShaderNodeSeparateXYZ"), + NodeItem("ShaderNodeCombineXYZ"), + NodeItem("ShaderNodeSeparateHSV"), + NodeItem("ShaderNodeCombineHSV"), + NodeItem("FunctionNodeBooleanMath"), + NodeItem("FunctionNodeFloatCompare"), + NodeItem("FunctionNodeSwitch"), + NodeItem("FunctionNodeCombineStrings"), + ]), + SimulationNodeCategory("SIM_GROUP", "Group", items=node_group_items), + SimulationNodeCategory("SIM_LAYOUT", "Layout", items=[ + NodeItem("NodeFrame"), + NodeItem("NodeReroute"), + ]), +] + def register(): nodeitems_utils.register_node_categories('SHADER', shader_node_categories) nodeitems_utils.register_node_categories('COMPOSITING', compositor_node_categories) nodeitems_utils.register_node_categories('TEXTURE', texture_node_categories) + nodeitems_utils.register_node_categories('SIMULATION', simulation_node_categories) def unregister(): nodeitems_utils.unregister_node_categories('SHADER') nodeitems_utils.unregister_node_categories('COMPOSITING') nodeitems_utils.unregister_node_categories('TEXTURE') + nodeitems_utils.unregister_node_categories('SIMULATION') if __name__ == "__main__": diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index f6f1393bd21..ddb88cf61ed 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -117,9 +117,11 @@ void BLF_draw_ascii(int fontid, const char *str, size_t len) ATTR_NONNULL(2); int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) ATTR_NONNULL(2); typedef bool (*BLF_GlyphBoundsFn)(const char *str, - const size_t str_ofs, - const struct rcti *glyph_bounds, + const size_t str_step_ofs, + const struct rcti *glyph_step_bounds, const int glyph_advance_x, + const struct rctf *glyph_bounds, + const int glyph_bearing[2], void *user_data); void BLF_boundbox_foreach_glyph_ex(int fontid, diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 394704e1c20..2f7d5a60a6f 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -946,8 +946,8 @@ void BLF_buffer(int fontid, if (font) { font->buf_info.fbuf = fbuf; font->buf_info.cbuf = cbuf; - font->buf_info.w = w; - font->buf_info.h = h; + font->buf_info.dims[0] = w; + font->buf_info.dims[1] = h; font->buf_info.ch = nch; font->buf_info.display = display; } diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index ed92e9aaff2..e5e03418073 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -613,28 +613,28 @@ static void blf_font_draw_buffer_ex(FontBLF *font, BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x); } - chx = pen_x + ((int)g->pos_x); - chy = pen_y_basis + g->height; + chx = pen_x + ((int)g->pos[0]); + chy = pen_y_basis + g->dims[1]; if (g->pitch < 0) { - pen_y = pen_y_basis + (g->height - (int)g->pos_y); + pen_y = pen_y_basis + (g->dims[1] - g->pos[1]); } else { - pen_y = pen_y_basis - (g->height - (int)g->pos_y); + pen_y = pen_y_basis - (g->dims[1] - g->pos[1]); } - if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && - pen_y < buf_info->h) { + if ((chx + g->dims[0]) >= 0 && chx < buf_info->dims[0] && (pen_y + g->dims[1]) >= 0 && + pen_y < buf_info->dims[1]) { /* don't draw beyond the buffer bounds */ - int width_clip = g->width; - int height_clip = g->height; - int yb_start = g->pitch < 0 ? 0 : g->height - 1; + int width_clip = g->dims[0]; + int height_clip = g->dims[1]; + int yb_start = g->pitch < 0 ? 0 : g->dims[1] - 1; - if (width_clip + chx > buf_info->w) { - width_clip -= chx + width_clip - buf_info->w; + if (width_clip + chx > buf_info->dims[0]) { + width_clip -= chx + width_clip - buf_info->dims[0]; } - if (height_clip + pen_y > buf_info->h) { - height_clip -= pen_y + height_clip - buf_info->h; + if (height_clip + pen_y > buf_info->dims[1]) { + height_clip -= pen_y + height_clip - buf_info->dims[1]; } /* drawing below the image? */ @@ -652,7 +652,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, if (a_byte) { const float a = (a_byte / 255.0f) * b_col_float[3]; const size_t buf_ofs = (((size_t)(chx + x) + - ((size_t)(pen_y + y) * (size_t)buf_info->w)) * + ((size_t)(pen_y + y) * (size_t)buf_info->dims[0])) * (size_t)buf_info->ch); float *fbuf = buf_info->fbuf + buf_ofs; @@ -689,7 +689,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, if (a_byte) { const float a = (a_byte / 255.0f) * b_col_float[3]; const size_t buf_ofs = (((size_t)(chx + x) + - ((size_t)(pen_y + y) * (size_t)buf_info->w)) * + ((size_t)(pen_y + y) * (size_t)buf_info->dims[0])) * (size_t)buf_info->ch); unsigned char *cbuf = buf_info->cbuf + buf_ofs; @@ -1246,13 +1246,13 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font, } gbox.xmin = pen_x; - gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->width); + gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->dims[0]); gbox.ymin = pen_y; - gbox.ymax = gbox.ymin - g->height; + gbox.ymax = gbox.ymin - g->dims[1]; pen_x += g->advance_i; - if (user_fn(str, i_curr, &gbox, g->advance_i, user_data) == false) { + if (user_fn(str, i_curr, &gbox, g->advance_i, &g->box, g->pos, user_data) == false) { break; } @@ -1365,8 +1365,8 @@ static void blf_font_fill(FontBLF *font) font->buf_info.fbuf = NULL; font->buf_info.cbuf = NULL; - font->buf_info.w = 0; - font->buf_info.h = 0; + font->buf_info.dims[0] = 0; + font->buf_info.dims[1] = 0; font->buf_info.ch = 0; font->buf_info.col_init[0] = 0; font->buf_info.col_init[1] = 0; diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index a38cb323777..ce17069e53f 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -212,7 +212,7 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc) GlyphBLF *g; unsigned int i; - for (i = 0; i < 257; i++) { + for (i = 0; i < ARRAY_SIZE(gc->bucket); i++) { while ((g = BLI_pophead(&gc->bucket[i]))) { blf_glyph_free(g); } @@ -327,26 +327,27 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un g->c = c; g->idx = (FT_UInt)index; bitmap = slot->bitmap; - g->width = (int)bitmap.width; - g->height = (int)bitmap.rows; + g->dims[0] = (int)bitmap.width; + g->dims[1] = (int)bitmap.rows; - if (g->width && g->height) { + const int buffer_size = g->dims[0] * g->dims[1]; + + if (buffer_size != 0) { if (font->flags & BLF_MONOCHROME) { /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */ - int i; - for (i = 0; i < (g->width * g->height); i++) { + for (int i = 0; i < buffer_size; i++) { bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0; } } - g->bitmap = (unsigned char *)MEM_mallocN((size_t)g->width * (size_t)g->height, "glyph bitmap"); - memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)g->width * (size_t)g->height); + g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap"); + memcpy(g->bitmap, bitmap.buffer, (size_t)buffer_size); } g->advance = ((float)slot->advance.x) / 64.0f; g->advance_i = (int)g->advance; - g->pos_x = (float)slot->bitmap_left; - g->pos_y = (float)slot->bitmap_top; + g->pos[0] = slot->bitmap_left; + g->pos[1] = slot->bitmap_top; g->pitch = slot->bitmap.pitch; FT_Outline_Get_CBox(&(slot->outline), &bbox); @@ -431,10 +432,10 @@ static void blf_texture3_draw(const unsigned char color_in[4], static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y) { - rect->xmin = floorf(x + g->pos_x); - rect->xmax = rect->xmin + (float)g->width; - rect->ymin = floorf(y + g->pos_y); - rect->ymax = rect->ymin - (float)g->height; + rect->xmin = floorf(x + (float)g->pos[0]); + rect->xmax = rect->xmin + (float)g->dims[0]; + rect->ymin = floorf(y + (float)g->pos[1]); + rect->ymax = rect->ymin - (float)g->dims[1]; } static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y) @@ -443,9 +444,9 @@ static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y) * width used by BLF_width. This allows that the text slightly * overlaps the clipping border to achieve better alignment. */ rect->xmin = floorf(x); - rect->xmax = rect->xmin + MIN2(g->advance, (float)g->width); + rect->xmax = rect->xmin + MIN2(g->advance, (float)g->dims[0]); rect->ymin = floorf(y); - rect->ymax = rect->ymin - (float)g->height; + rect->ymax = rect->ymin - (float)g->dims[1]; } static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y, FontBLF *font) @@ -455,7 +456,7 @@ static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, float y) { - if ((!g->width) || (!g->height)) { + if ((!g->dims[0]) || (!g->dims[1])) { return; } @@ -466,7 +467,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl g->offset = gc->bitmap_len; - int buff_size = g->width * g->height; + int buff_size = g->dims[0] * g->dims[1]; int bitmap_len = gc->bitmap_len + buff_size; if (bitmap_len > gc->bitmap_len_alloc) { @@ -514,7 +515,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl if (font->shadow == 0) { blf_texture_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -523,7 +524,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } else if (font->shadow <= 4) { blf_texture3_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -532,7 +533,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } else { blf_texture5_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -547,39 +548,18 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl #if BLF_BLUR_ENABLE switch (font->blur) { case 3: - blf_texture3_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture3_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; case 5: - blf_texture5_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture5_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; default: - blf_texture_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } #else - blf_texture_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture_draw(font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); #endif } diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 98ada87d16d..4ae592d323f 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -103,9 +103,11 @@ void blf_font_boundbox_foreach_glyph(struct FontBLF *font, const char *str, size_t len, bool (*user_fn)(const char *str, - const size_t str_ofs, - const struct rcti *glyph_bounds, + const size_t str_step_ofs, + const struct rcti *glyph_step_bounds, const int glyph_advance_x, + const struct rctf *glyph_bounds, + const int glyph_bearing[2], void *user_data), void *user_data, struct ResultBLF *r_info); diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 6fae3eb4376..362cbf6730f 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -119,17 +119,16 @@ typedef struct GlyphBLF { */ unsigned char *bitmap; - /* glyph width and height. */ - int width; - int height; + /* Glyph width and height. */ + int dims[2]; int pitch; - /* X and Y bearing of the glyph. + /** + * X and Y bearing of the glyph. * The X bearing is from the origin to the glyph left bbox edge. * The Y bearing is from the baseline to the top of the glyph edge. */ - float pos_x; - float pos_y; + int pos[2]; struct GlyphCacheBLF *glyph_cache; } GlyphBLF; @@ -141,9 +140,8 @@ typedef struct FontBufInfoBLF { /* the same but unsigned char */ unsigned char *cbuf; - /* buffer size, keep signed so comparisons with negative values work */ - int w; - int h; + /** Buffer size, keep signed so comparisons with negative values work. */ + int dims[2]; /* number of channels. */ int ch; diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index b7308d47d71..37eed29f6fe 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -78,8 +78,8 @@ void BLF_thumb_preview(const char *filename, /* Would be done via the BLF API, but we're not using a fontid here */ font->buf_info.cbuf = buf; font->buf_info.ch = channels; - font->buf_info.w = w; - font->buf_info.h = h; + font->buf_info.dims[0] = w; + font->buf_info.dims[1] = h; /* Always create the image with a white font, * the caller can theme how it likes */ diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 5f4f3f35b82..104582be932 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -25,12 +25,12 @@ * \brief Blender kernel action and pose functionality. */ +#include "DNA_listBase.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_listBase.h" - /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ struct FCurve; struct Main; diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h index 071254be783..8809fadd55c 100644 --- a/source/blender/blenkernel/BKE_anim_data.h +++ b/source/blender/blenkernel/BKE_anim_data.h @@ -24,12 +24,12 @@ * \ingroup bke */ +#include "BLI_sys_types.h" /* for bool */ + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" /* for bool */ - struct AnimData; struct ID; struct Main; diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index a8915c178d4..4a2ad28f90f 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -24,12 +24,12 @@ * \ingroup bke */ +#include "BLI_sys_types.h" /* for bool */ + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" /* for bool */ - struct AnimData; struct Depsgraph; struct FCurve; @@ -207,17 +207,15 @@ bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_val bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value); /* Evaluation loop for evaluating animation data */ -void BKE_animsys_evaluate_animdata(struct Scene *scene, - struct ID *id, +void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, float ctime, - short recalc, + eAnimData_Recalc recalc, const bool flush_to_original); /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Depsgraph *depsgraph, - struct Scene *scene, float ctime); /* ------------ Specialized API --------------- */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 6c383ae5011..5238853a105 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -22,6 +22,7 @@ /** \file * \ingroup bke */ +#include "BLI_listbase.h" #ifdef __cplusplus extern "C" { diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 52a603ede72..852549f22d4 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -16,6 +16,10 @@ #ifndef __BKE_BLENDER_VERSION_H__ #define __BKE_BLENDER_VERSION_H__ +#ifdef __cplusplus +extern "C" { +#endif + /** \file * \ingroup bke */ @@ -26,8 +30,8 @@ * * \note Use #STRINGIFY() rather than defining with quotes. */ -#define BLENDER_VERSION 283 -#define BLENDER_SUBVERSION 16 +#define BLENDER_VERSION 290 +#define BLENDER_SUBVERSION 1 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 @@ -36,11 +40,15 @@ /** Can be left blank, otherwise a,b,c... etc with no quotes. */ #define BLENDER_VERSION_CHAR /** alpha/beta/rc/release, docs use this. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /** Optionally set to 1,2,... for example to get alpha1 or rc2. */ #define BLENDER_VERSION_CYCLE_NUMBER /** Defined in from blender.c */ extern char versionstr[]; +#ifdef __cplusplus +} +#endif + #endif /* __BKE_BLENDER_VERSION_H__ */ diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 1d6db319eb7..dd7d20c0407 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index c4fb19ea355..70ca29d5795 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -25,6 +25,7 @@ */ #include "DNA_listBase.h" +#include "DNA_object_enums.h" #include "RNA_types.h" #ifdef __cplusplus @@ -66,8 +67,6 @@ struct bScreen; struct wmWindow; struct wmWindowManager; -#include "DNA_object_enums.h" - /* Structs */ struct bContext; diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 164867b228b..2b17cb7a875 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -23,12 +23,12 @@ * \ingroup bke */ +#include "DNA_scene_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_scene_types.h" - struct BezTriple; struct Curve; struct Depsgraph; @@ -111,6 +111,8 @@ void BKE_curve_material_index_clear(struct Curve *cu); bool BKE_curve_material_index_validate(struct Curve *cu); void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len); +void BKE_curve_smooth_flag_set(struct Curve *cu, const bool use_smooth); + ListBase *BKE_curve_nurbs_get(struct Curve *cu); int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index a4a36343ca3..42beda352f5 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. @@ -25,15 +25,15 @@ #ifndef __BKE_CUSTOMDATA_H__ #define __BKE_CUSTOMDATA_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_sys_types.h" #include "BLI_utildefines.h" #include "DNA_customdata_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct BMesh; struct CustomData; struct CustomData_MeshMasks; diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index 79ef512bc1f..a723a9ed38c 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -10,7 +10,7 @@ * 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, + * 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) 2014 Blender Foundation. @@ -24,12 +24,12 @@ #ifndef __BKE_DATA_TRANSFER_H__ #define __BKE_DATA_TRANSFER_H__ +#include "BKE_customdata.h" + #ifdef __cplusplus extern "C" { #endif -#include "BKE_customdata.h" - struct Depsgraph; struct Object; struct ReportList; diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index 0dc133e34b3..5e3603a8339 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -21,12 +21,12 @@ * \ingroup bke */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - struct Depsgraph; struct DynamicPaintCanvasSettings; struct DynamicPaintModifierData; diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index d389b557503..21a9b7b8b04 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -24,13 +24,13 @@ * \ingroup bke */ +#include "DNA_curve_types.h" + #ifdef __cplusplus extern "C" { #endif struct ChannelDriver; -struct DriverTarget; -struct DriverVar; struct FCM_EnvelopeData; struct FCurve; struct FModifier; @@ -44,8 +44,6 @@ struct StructRNA; struct bAction; struct bContext; -#include "DNA_curve_types.h" - /* ************** Keyframe Tools ***************** */ typedef struct CfraElem { @@ -56,67 +54,6 @@ typedef struct CfraElem { void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt); -/* ************** F-Curve Drivers ***************** */ - -/* With these iterators for convenience, the variables "tarIndex" and "dtar" can be - * accessed directly from the code using them, but it is not recommended that their - * values be changed to point at other slots... - */ - -/* convenience looper over ALL driver targets for a given variable (even the unused ones) */ -#define DRIVER_TARGETS_LOOPER_BEGIN(dvar) \ - { \ - DriverTarget *dtar = &dvar->targets[0]; \ - int tarIndex = 0; \ - for (; tarIndex < MAX_DRIVER_TARGETS; tarIndex++, dtar++) - -/* convenience looper over USED driver targets only */ -#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar) \ - { \ - DriverTarget *dtar = &dvar->targets[0]; \ - int tarIndex = 0; \ - for (; tarIndex < dvar->num_targets; tarIndex++, dtar++) - -/* tidy up for driver targets loopers */ -#define DRIVER_TARGETS_LOOPER_END \ - } \ - ((void)0) - -/* ---------------------- */ - -void fcurve_free_driver(struct FCurve *fcu); -struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver); - -void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars); - -void BKE_driver_target_matrix_to_rot_channels( - float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]); - -void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar); -void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar); - -void driver_change_variable_type(struct DriverVar *dvar, int type); -void driver_variable_name_validate(struct DriverVar *dvar); -struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver); - -float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar); -bool driver_get_variable_property(struct ChannelDriver *driver, - struct DriverTarget *dtar, - struct PointerRNA *r_ptr, - struct PropertyRNA **r_prop, - int *r_index); - -bool BKE_driver_has_simple_expression(struct ChannelDriver *driver); -bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver); -void BKE_driver_invalidate_expression(struct ChannelDriver *driver, - bool expr_changed, - bool varname_changed); - -float evaluate_driver(struct PathResolvedRNA *anim_rna, - struct ChannelDriver *driver, - struct ChannelDriver *driver_orig, - const float evaltime); - /* ************** F-Curve Modifiers *************** */ /* F-Curve Modifier Type-Info (fmi): diff --git a/source/blender/blenkernel/BKE_fcurve_driver.h b/source/blender/blenkernel/BKE_fcurve_driver.h new file mode 100644 index 00000000000..563ed408ed7 --- /dev/null +++ b/source/blender/blenkernel/BKE_fcurve_driver.h @@ -0,0 +1,106 @@ +/* + * 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, Joshua Leung + * All rights reserved. + */ + +#ifndef __BKE_FCURVE_DRIVER_H__ +#define __BKE_FCURVE_DRIVER_H__ + +/** \file + * \ingroup bke + */ + +#include "DNA_curve_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ChannelDriver; +struct DriverTarget; +struct DriverVar; +struct FCurve; +struct PathResolvedRNA; +struct PointerRNA; +struct PropertyRNA; + +/* ************** F-Curve Drivers ***************** */ + +/* With these iterators for convenience, the variables "tarIndex" and "dtar" can be + * accessed directly from the code using them, but it is not recommended that their + * values be changed to point at other slots... + */ + +/* convenience looper over ALL driver targets for a given variable (even the unused ones) */ +#define DRIVER_TARGETS_LOOPER_BEGIN(dvar) \ + { \ + DriverTarget *dtar = &dvar->targets[0]; \ + int tarIndex = 0; \ + for (; tarIndex < MAX_DRIVER_TARGETS; tarIndex++, dtar++) + +/* convenience looper over USED driver targets only */ +#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar) \ + { \ + DriverTarget *dtar = &dvar->targets[0]; \ + int tarIndex = 0; \ + for (; tarIndex < dvar->num_targets; tarIndex++, dtar++) + +/* tidy up for driver targets loopers */ +#define DRIVER_TARGETS_LOOPER_END \ + } \ + ((void)0) + +/* ---------------------- */ + +void fcurve_free_driver(struct FCurve *fcu); +struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver); + +void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars); + +void BKE_driver_target_matrix_to_rot_channels( + float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]); + +void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar); +void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar); + +void driver_change_variable_type(struct DriverVar *dvar, int type); +void driver_variable_name_validate(struct DriverVar *dvar); +struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver); + +float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar); +bool driver_get_variable_property(struct ChannelDriver *driver, + struct DriverTarget *dtar, + struct PointerRNA *r_ptr, + struct PropertyRNA **r_prop, + int *r_index); + +bool BKE_driver_has_simple_expression(struct ChannelDriver *driver); +bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver); +void BKE_driver_invalidate_expression(struct ChannelDriver *driver, + bool expr_changed, + bool varname_changed); + +float evaluate_driver(struct PathResolvedRNA *anim_rna, + struct ChannelDriver *driver, + struct ChannelDriver *driver_orig, + const float evaltime); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_FCURVE_DRIVER_H__*/ diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h new file mode 100644 index 00000000000..cf6f9074bda --- /dev/null +++ b/source/blender/blenkernel/BKE_gpencil_curve.h @@ -0,0 +1,47 @@ +/* + * 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) 2008, Blender Foundation + * This is a new part of Blender + */ + +#ifndef __BKE_GPENCIL_CURVE_H__ +#define __BKE_GPENCIL_CURVE_H__ + +/** \file + * \ingroup bke + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Main; +struct Object; +struct Scene; + +void BKE_gpencil_convert_curve(struct Main *bmain, + struct Scene *scene, + struct Object *ob_gp, + struct Object *ob_cu, + const bool gpencil_lines, + const bool use_collections, + const bool only_stroke); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_GPENCIL_CURVE_H__ */ diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 8c52e6d458b..b26016aa26c 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -98,14 +98,6 @@ bool BKE_gpencil_stroke_shrink(struct bGPDstroke *gps, const float dist); float BKE_gpencil_stroke_length(const struct bGPDstroke *gps, bool use_3d); -void BKE_gpencil_convert_curve(struct Main *bmain, - struct Scene *scene, - struct Object *ob_gp, - struct Object *ob_cu, - const bool gpencil_lines, - const bool use_collections, - const bool only_stroke); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index b48a6284567..966d3a98234 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -260,28 +260,28 @@ typedef struct GpencilModifierTypeInfo { /* Initialize modifier's global data (type info and some common global storages). */ void BKE_gpencil_modifier_init(void); -const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type); +const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType type); struct GpencilModifierData *BKE_gpencil_modifier_new(int type); void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, const int flag); void BKE_gpencil_modifier_free(struct GpencilModifierData *md); bool BKE_gpencil_modifier_unique_name(struct ListBase *modifiers, struct GpencilModifierData *gmd); -bool BKE_gpencil_modifier_dependsOnTime(struct GpencilModifierData *md); -struct GpencilModifierData *BKE_gpencil_modifiers_findByType(struct Object *ob, - GpencilModifierType type); -struct GpencilModifierData *BKE_gpencil_modifiers_findByName(struct Object *ob, const char *name); -void BKE_gpencil_modifier_copyData_generic(const struct GpencilModifierData *md_src, +bool BKE_gpencil_modifier_depends_ontime(struct GpencilModifierData *md); +struct GpencilModifierData *BKE_gpencil_modifiers_findby_type(struct Object *ob, + GpencilModifierType type); +struct GpencilModifierData *BKE_gpencil_modifiers_findby_name(struct Object *ob, const char *name); +void BKE_gpencil_modifier_copydata_generic(const struct GpencilModifierData *md_src, struct GpencilModifierData *md_dst); -void BKE_gpencil_modifier_copyData(struct GpencilModifierData *md, +void BKE_gpencil_modifier_copydata(struct GpencilModifierData *md, struct GpencilModifierData *target); -void BKE_gpencil_modifier_copyData_ex(struct GpencilModifierData *md, +void BKE_gpencil_modifier_copydata_ex(struct GpencilModifierData *md, struct GpencilModifierData *target, const int flag); -void BKE_gpencil_modifiers_foreachIDLink(struct Object *ob, - GreasePencilIDWalkFunc walk, - void *userData); -void BKE_gpencil_modifiers_foreachTexLink(struct Object *ob, - GreasePencilTexWalkFunc walk, - void *userData); +void BKE_gpencil_modifiers_foreach_ID_link(struct Object *ob, + GreasePencilIDWalkFunc walk, + void *userData); +void BKE_gpencil_modifiers_foreach_tex_link(struct Object *ob, + GreasePencilTexWalkFunc walk, + void *userData); bool BKE_gpencil_has_geometry_modifiers(struct Object *ob); bool BKE_gpencil_has_time_modifiers(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h index 05545216217..b6dfadd3b2a 100644 --- a/source/blender/blenkernel/BKE_idtype.h +++ b/source/blender/blenkernel/BKE_idtype.h @@ -33,6 +33,7 @@ extern "C" { #endif struct ID; +struct LibraryForeachIDData; struct Main; /** IDTypeInfo.flags. */ @@ -60,6 +61,8 @@ typedef void (*IDTypeFreeDataFunction)(struct ID *id); /** \param flag: See BKE_lib_id.h's LIB_ID_MAKELOCAL_... flags. */ typedef void (*IDTypeMakeLocalFunction)(struct Main *bmain, struct ID *id, const int flags); +typedef void (*IDTypeForeachIDFunction)(struct ID *id, struct LibraryForeachIDData *data); + typedef struct IDTypeInfo { /* ********** General IDType data. ********** */ @@ -121,6 +124,12 @@ typedef struct IDTypeInfo { * `BKE_lib_id_make_local_generic()` is enough. */ IDTypeMakeLocalFunction make_local; + + /** + * Called by `BKE_library_foreach_ID_link()` to apply a callback over all other ID usages (ID + * pointers) of given data-block. + */ + IDTypeForeachIDFunction foreach_id; } IDTypeInfo; /* ********** Declaration of each IDTypeInfo. ********** */ @@ -165,6 +174,7 @@ extern IDTypeInfo IDType_ID_LP; extern IDTypeInfo IDType_ID_HA; extern IDTypeInfo IDType_ID_PT; extern IDTypeInfo IDType_ID_VO; +extern IDTypeInfo IDType_ID_SIM; extern IDTypeInfo IDType_ID_LINK_PLACEHOLDER; diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 0d8b6efb4b1..1e5573ab014 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -23,12 +23,12 @@ * \ingroup bke */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - struct Depsgraph; struct ID; struct ImBuf; @@ -318,7 +318,7 @@ bool BKE_image_fill_tile(struct Image *ima, bool is_float); struct ImageTile *BKE_image_get_tile(struct Image *ima, int tile_number); -struct ImageTile *BKE_image_get_tile_from_iuser(struct Image *ima, struct ImageUser *iuser); +struct ImageTile *BKE_image_get_tile_from_iuser(struct Image *ima, const struct ImageUser *iuser); int BKE_image_get_tile_from_pos(struct Image *ima, const float uv[2], diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index 0c91ba6231b..1f89edf905a 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -46,12 +46,12 @@ * specific cases requiring advanced (and potentially dangerous) handling. */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct GHash; struct ID; struct Library; diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h index 3aa27bf557c..353ee3bbf5a 100644 --- a/source/blender/blenkernel/BKE_lib_query.h +++ b/source/blender/blenkernel/BKE_lib_query.h @@ -40,6 +40,7 @@ extern "C" { #endif struct ID; +struct IDProperty; struct Main; /* Tips for the callback for cases it's gonna to modify the pointer. */ @@ -126,6 +127,33 @@ enum { IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */ }; +typedef struct LibraryForeachIDData LibraryForeachIDData; + +bool BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data, + struct ID **id_pp, + int cb_flag); + +#define BKE_LIB_FOREACHID_PROCESS_ID(_data, _id, _cb_flag) \ + { \ + CHECK_TYPE_ANY((_id), ID *, void *); \ + if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id), (_cb_flag))) { \ + return; \ + } \ + } \ + ((void)0) + +#define BKE_LIB_FOREACHID_PROCESS(_data, _id_super, _cb_flag) \ + { \ + CHECK_TYPE(&((_id_super)->id), ID *); \ + if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag))) { \ + return; \ + } \ + } \ + ((void)0) + +bool BKE_library_foreach_ID_embedded(struct LibraryForeachIDData *data, struct ID **id_pp); +void BKE_lib_query_idpropertiesForeachIDLink_callback(struct IDProperty *id_prop, void *user_data); + /* Loop over all of the ID's this datablock links to. */ void BKE_library_foreach_ID_link( struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag); diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h index 72c5f1d1b0e..8129b9dbafb 100644 --- a/source/blender/blenkernel/BKE_lib_remap.h +++ b/source/blender/blenkernel/BKE_lib_remap.h @@ -33,12 +33,12 @@ * - `BKE_lib_remap_callback_` should be used for functions managing remapping callbacks. */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct wmWindowManager; /* BKE_libblock_free, delete are declared in BKE_lib_id.h for convenience. */ diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 5bc3d50bf8d..7883d740b0a 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -25,12 +25,12 @@ * API to manage `Library` data-blocks. */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct Library; struct Main; diff --git a/source/blender/blenkernel/BKE_light.h b/source/blender/blenkernel/BKE_light.h index a6f0fdbc8a3..17f7a8596bf 100644 --- a/source/blender/blenkernel/BKE_light.h +++ b/source/blender/blenkernel/BKE_light.h @@ -24,12 +24,13 @@ * \ingroup bke * \brief General operations, lookup, etc. for blender lights. */ + +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct Light; struct Main; diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index ed1f67350c3..b2472e862ec 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -147,6 +147,7 @@ typedef struct Main { ListBase hairs; ListBase pointclouds; ListBase volumes; + ListBase simulations; /** * Must be generated, used and freed by same code - never assume this is valid data unless you @@ -220,7 +221,7 @@ const char *BKE_main_blendfile_path_from_global(void); struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 40 +#define MAX_LIBARRAY 41 int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); #define MAIN_VERSION_ATLEAST(main, ver, subver) \ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index c37e56149eb..a4bf86f61f3 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -100,7 +100,7 @@ typedef enum { /* For modifiers that use CD_PREVIEW_MCOL for preview. */ eModifierTypeFlag_UsesPreview = (1 << 9), - eModifierTypeFlag_AcceptsLattice = (1 << 10), + eModifierTypeFlag_AcceptsVertexCosOnly = (1 << 10), } ModifierTypeFlag; /* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */ @@ -211,18 +211,28 @@ typedef struct ModifierTypeInfo { /********************* Non-deform modifier functions *********************/ - /* For non-deform types: apply the modifier and return a mesh object. + /* For non-deform types: apply the modifier and return a mesh datablock. * - * The mesh argument should always be non-NULL; the modifier - * should read the object data from the mesh object instead of the - * actual object data. + * The mesh argument should always be non-NULL; the modifier should use the + * passed in mesh datablock rather than object->data, as it contains the mesh + * with modifier applied up to this point. * - * The modifier may reuse the mesh argument (i.e. return it in - * modified form), but must not release it. + * The modifier may modify and return the mesh argument, but must not free it + * and must ensure any referenced data layers are converted to non-referenced + * before modification. */ - struct Mesh *(*applyModifier)(struct ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *mesh); + struct Mesh *(*modifyMesh)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Mesh *mesh); + struct Hair *(*modifyHair)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Hair *hair); + struct PointCloud *(*modifyPointCloud)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct PointCloud *pointcloud); + struct Volume *(*modifyVolume)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Volume *volume); /********************* Optional functions *********************/ @@ -343,60 +353,64 @@ typedef struct ModifierTypeInfo { /* Initialize modifier's global data (type info and some common global storages). */ void BKE_modifier_init(void); -const ModifierTypeInfo *modifierType_getInfo(ModifierType type); +const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type); /* Modifier utility calls, do call through type pointer and return * default values if pointer is optional. */ -struct ModifierData *modifier_new(int type); -void modifier_free_ex(struct ModifierData *md, const int flag); -void modifier_free(struct ModifierData *md); - -bool modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md); - -void modifier_copyData_generic(const struct ModifierData *md, - struct ModifierData *target, - const int flag); -void modifier_copyData(struct ModifierData *md, struct ModifierData *target); -void modifier_copyData_ex(struct ModifierData *md, struct ModifierData *target, const int flag); -bool modifier_dependsOnTime(struct ModifierData *md); -bool modifier_supportsMapping(struct ModifierData *md); -bool modifier_supportsCage(struct Scene *scene, struct ModifierData *md); -bool modifier_couldBeCage(struct Scene *scene, struct ModifierData *md); -bool modifier_isCorrectableDeformed(struct ModifierData *md); -bool modifier_isSameTopology(ModifierData *md); -bool modifier_isNonGeometrical(ModifierData *md); -bool modifier_isEnabled(const struct Scene *scene, struct ModifierData *md, int required_mode); -void modifier_setError(struct ModifierData *md, const char *format, ...) ATTR_PRINTF_FORMAT(2, 3); -bool modifier_isPreview(struct ModifierData *md); - -void modifiers_foreachObjectLink(struct Object *ob, ObjectWalkFunc walk, void *userData); -void modifiers_foreachIDLink(struct Object *ob, IDWalkFunc walk, void *userData); -void modifiers_foreachTexLink(struct Object *ob, TexWalkFunc walk, void *userData); - -struct ModifierData *modifiers_findByType(struct Object *ob, ModifierType type); -struct ModifierData *modifiers_findByName(struct Object *ob, const char *name); -void modifiers_clearErrors(struct Object *ob); -int modifiers_getCageIndex(struct Scene *scene, - struct Object *ob, - int *r_lastPossibleCageIndex, - bool is_virtual); - -bool modifiers_isModifierEnabled(struct Object *ob, int modifierType); -bool modifiers_isSoftbodyEnabled(struct Object *ob); -bool modifiers_isClothEnabled(struct Object *ob); -bool modifiers_isParticleEnabled(struct Object *ob); - -struct Object *modifiers_isDeformedByArmature(struct Object *ob); -struct Object *modifiers_isDeformedByMeshDeform(struct Object *ob); -struct Object *modifiers_isDeformedByLattice(struct Object *ob); -struct Object *modifiers_isDeformedByCurve(struct Object *ob); -bool modifiers_usesMultires(struct Object *ob); -bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm); -bool modifiers_usesSubsurfFacedots(struct Scene *scene, struct Object *ob); -bool modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob); -void modifier_freeTemporaryData(struct ModifierData *md); -bool modifiers_isPreview(struct Object *ob); +struct ModifierData *BKE_modifier_new(int type); +void BKE_modifier_free_ex(struct ModifierData *md, const int flag); +void BKE_modifier_free(struct ModifierData *md); + +bool BKE_modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md); + +void BKE_modifier_copydata_generic(const struct ModifierData *md, + struct ModifierData *target, + const int flag); +void BKE_modifier_copydata(struct ModifierData *md, struct ModifierData *target); +void BKE_modifier_copydata_ex(struct ModifierData *md, + struct ModifierData *target, + const int flag); +bool BKE_modifier_depends_ontime(struct ModifierData *md); +bool BKE_modifier_supports_mapping(struct ModifierData *md); +bool BKE_modifier_supports_cage(struct Scene *scene, struct ModifierData *md); +bool BKE_modifier_couldbe_cage(struct Scene *scene, struct ModifierData *md); +bool BKE_modifier_is_correctable_deformed(struct ModifierData *md); +bool BKE_modifier_is_same_topology(ModifierData *md); +bool BKE_modifier_is_non_geometrical(ModifierData *md); +bool BKE_modifier_is_enabled(const struct Scene *scene, + struct ModifierData *md, + int required_mode); +void BKE_modifier_set_error(struct ModifierData *md, const char *format, ...) + ATTR_PRINTF_FORMAT(2, 3); +bool BKE_modifier_is_preview(struct ModifierData *md); + +void BKE_modifiers_foreach_object_link(struct Object *ob, ObjectWalkFunc walk, void *userData); +void BKE_modifiers_foreach_ID_link(struct Object *ob, IDWalkFunc walk, void *userData); +void BKE_modifiers_foreach_tex_link(struct Object *ob, TexWalkFunc walk, void *userData); + +struct ModifierData *BKE_modifiers_findby_type(struct Object *ob, ModifierType type); +struct ModifierData *BKE_modifiers_findny_name(struct Object *ob, const char *name); +void BKE_modifiers_clear_errors(struct Object *ob); +int BKE_modifiers_get_cage_index(struct Scene *scene, + struct Object *ob, + int *r_lastPossibleCageIndex, + bool is_virtual); + +bool BKE_modifiers_is_modifier_enabled(struct Object *ob, int modifierType); +bool BKE_modifiers_is_softbody_enabled(struct Object *ob); +bool BKE_modifiers_is_cloth_enabled(struct Object *ob); +bool BKE_modifiers_is_particle_enabled(struct Object *ob); + +struct Object *BKE_modifiers_is_deformed_by_armature(struct Object *ob); +struct Object *BKE_modifiers_is_deformed_by_meshdeform(struct Object *ob); +struct Object *BKE_modifiers_is_deformed_by_lattice(struct Object *ob); +struct Object *BKE_modifiers_is_deformed_by_curve(struct Object *ob); +bool BKE_modifiers_uses_multires(struct Object *ob); +bool BKE_modifiers_uses_armature(struct Object *ob, struct bArmature *arm); +bool BKE_modifiers_uses_subsurf_facedots(struct Scene *scene, struct Object *ob); +bool BKE_modifiers_is_correctable_deformed(struct Scene *scene, struct Object *ob); +void BKE_modifier_free_temporary_data(struct ModifierData *md); typedef struct CDMaskLink { struct CDMaskLink *next; @@ -408,16 +422,16 @@ typedef struct CDMaskLink { * pointed to by md for correct evaluation, assuming the data indicated by * final_datamask is required at the end of the stack. */ -struct CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, - struct Object *ob, - struct ModifierData *md, - struct CustomData_MeshMasks *final_datamask, - int required_mode, - ModifierData *previewmd, - const struct CustomData_MeshMasks *previewmask); -struct ModifierData *modifiers_getLastPreview(struct Scene *scene, - struct ModifierData *md, - int required_mode); +struct CDMaskLink *BKE_modifier_calc_data_masks(struct Scene *scene, + struct Object *ob, + struct ModifierData *md, + struct CustomData_MeshMasks *final_datamask, + int required_mode, + ModifierData *previewmd, + const struct CustomData_MeshMasks *previewmask); +struct ModifierData *BKE_modifier_get_last_preview(struct Scene *scene, + struct ModifierData *md, + int required_mode); typedef struct VirtualModifierData { ArmatureModifierData amd; @@ -426,46 +440,46 @@ typedef struct VirtualModifierData { ShapeKeyModifierData smd; } VirtualModifierData; -struct ModifierData *modifiers_getVirtualModifierList(const struct Object *ob, - struct VirtualModifierData *data); +struct ModifierData *BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, + struct VirtualModifierData *data); /* ensure modifier correctness when changing ob->data */ -void test_object_modifiers(struct Object *ob); +void BKE_modifiers_test_object(struct Object *ob); /* here for do_versions */ -void modifier_mdef_compact_influences(struct ModifierData *md); +void BKE_modifier_mdef_compact_influences(struct ModifierData *md); -void modifier_path_init(char *path, int path_maxlen, const char *name); -const char *modifier_path_relbase(struct Main *bmain, struct Object *ob); -const char *modifier_path_relbase_from_global(struct Object *ob); +void BKE_modifier_path_init(char *path, int path_maxlen, const char *name); +const char *BKE_modifier_path_relbase(struct Main *bmain, struct Object *ob); +const char *BKE_modifier_path_relbase_from_global(struct Object *ob); /* Accessors of original/evaluated modifiers. */ /* For a given modifier data, get corresponding original one. * If the modifier data is already original, return it as-is. */ -struct ModifierData *modifier_get_original(struct ModifierData *md); -struct ModifierData *modifier_get_evaluated(struct Depsgraph *depsgraph, - struct Object *object, - struct ModifierData *md); +struct ModifierData *BKE_modifier_get_original(struct ModifierData *md); +struct ModifierData *BKE_modifier_get_evaluated(struct Depsgraph *depsgraph, + struct Object *object, + struct ModifierData *md); /* wrappers for modifier callbacks that ensure valid normals */ -struct Mesh *modwrap_applyModifier(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *me); - -void modwrap_deformVerts(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *me, - float (*vertexCos)[3], - int numVerts); - -void modwrap_deformVertsEM(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct BMEditMesh *em, - struct Mesh *me, - float (*vertexCos)[3], - int numVerts); +struct Mesh *BKE_modifier_modify_mesh(ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Mesh *me); + +void BKE_modifier_deform_verts(ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Mesh *me, + float (*vertexCos)[3], + int numVerts); + +void BKE_modifier_deform_vertsEM(ModifierData *md, + const struct ModifierEvalContext *ctx, + struct BMEditMesh *em, + struct Mesh *me, + float (*vertexCos)[3], + int numVerts); struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index fe5b8cff31c..15ba72ef5b5 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -10,7 +10,7 @@ * 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, + * 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) 2007 by Nicholas Bishop @@ -110,6 +110,11 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, void multiresModifier_base_apply(struct Depsgraph *depsgraph, struct Object *object, struct MultiresModifierData *mmd); +int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph, + struct Object *object, + struct MultiresModifierData *mmd, + int rebuild_limit, + bool switch_view_to_lower_level); void multiresModifier_subdivide_legacy(struct MultiresModifierData *mmd, struct Scene *scene, struct Object *ob, @@ -175,13 +180,25 @@ bool multiresModifier_reshapeFromCCG(const int tot_level, struct SubdivCCG *subdiv_ccg); /* Subdivide multires displacement once. */ -void multiresModifier_subdivide(struct Object *object, struct MultiresModifierData *mmd); + +typedef enum eMultiresSubdivideModeType { + MULTIRES_SUBDIVIDE_CATMULL_CLARK, + MULTIRES_SUBDIVIDE_SIMPLE, + MULTIRES_SUBDIVIDE_LINEAR, +} eMultiresSubdivideModeType; + +void multiresModifier_subdivide(struct Object *object, + struct MultiresModifierData *mmd, + const eMultiresSubdivideModeType mode); +void multires_subdivide_create_tangent_displacement_linear_grids(struct Object *object, + struct MultiresModifierData *mmd); /* Subdivide displacement to the given level. * If level is lower than the current top level nothing happens. */ void multiresModifier_subdivide_to_level(struct Object *object, struct MultiresModifierData *mmd, - const int top_level); + const int top_level, + const eMultiresSubdivideModeType mode); /* Subdivision integration, defined in multires_subdiv.c */ @@ -213,8 +230,6 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3] const float dPdv[3], const int corner); -int BKE_multires_sculpt_level_get(const struct MultiresModifierData *mmd); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 38fe974c228..536d04f8bd3 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -385,8 +385,8 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char /* copy/free funcs, need to manage ID users */ void ntreeFreeTree(struct bNodeTree *ntree); -/* Free tree which is owned byt another datablock. */ -void ntreeFreeNestedTree(struct bNodeTree *ntree); +/* Free tree which is embedded into another datablock. */ +void ntreeFreeEmbeddedTree(struct bNodeTree *ntree); struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user); @@ -852,6 +852,7 @@ struct NodeTreeIterStore { struct Light *light; struct World *world; struct FreestyleLineStyle *linestyle; + struct Simulation *simulation; }; void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain); @@ -1275,13 +1276,44 @@ int ntreeTexExecTree(struct bNodeTree *ntree, float dyt[3], int osatex, const short thread, - struct Tex *tex, + const struct Tex *tex, short which_output, int cfra, int preview, struct MTex *mtex); /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Simulation Nodes + * \{ */ + +#define SIM_NODE_PARTICLE_SIMULATION 1000 +#define SIM_NODE_FORCE 1001 +#define SIM_NODE_SET_PARTICLE_ATTRIBUTE 1002 +#define SIM_NODE_PARTICLE_BIRTH_EVENT 1003 +#define SIM_NODE_PARTICLE_TIME_STEP_EVENT 1004 +#define SIM_NODE_EXECUTE_CONDITION 1005 +#define SIM_NODE_MULTI_EXECUTE 1006 +#define SIM_NODE_PARTICLE_MESH_EMITTER 1007 +#define SIM_NODE_PARTICLE_MESH_COLLISION_EVENT 1008 +#define SIM_NODE_EMIT_PARTICLES 1009 +#define SIM_NODE_TIME 1010 +#define SIM_NODE_PARTICLE_ATTRIBUTE 1011 + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Function Nodes + * \{ */ + +#define FN_NODE_BOOLEAN_MATH 1200 +#define FN_NODE_SWITCH 1201 +#define FN_NODE_FLOAT_COMPARE 1202 +#define FN_NODE_GROUP_INSTANCE_ID 1203 +#define FN_NODE_COMBINE_STRINGS 1204 + +/** \} */ + void init_nodesystem(void); void free_nodesystem(void); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 70a44d6d8ce..3710ec810ce 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -21,12 +21,15 @@ * \ingroup bke * \brief General operations, lookup, etc. for blender objects. */ + +#include "BLI_compiler_attrs.h" + +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct Base; struct BoundBox; struct Depsgraph; @@ -46,8 +49,6 @@ struct ShaderFxData; struct View3D; struct ViewLayer; -#include "DNA_object_enums.h" - void BKE_object_workob_clear(struct Object *workob); void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index a354cb52f59..a7ece2e3167 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -10,7 +10,7 @@ * 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, + * 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 by Nicholas Bishop @@ -24,6 +24,9 @@ * \ingroup bke */ +#include "BLI_utildefines.h" +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -65,9 +68,6 @@ struct tPaletteColorHSV; enum eOverlayFlags; -#include "BLI_utildefines.h" -#include "DNA_object_enums.h" - extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; extern const char PAINT_CURSOR_WEIGHT_PAINT[3]; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 94f0e544a6b..35dd241c173 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -48,6 +48,7 @@ struct Mesh; struct PBVH; struct PBVHNode; struct SubdivCCG; +struct TaskParallelSettings; struct TaskParallelTLS; typedef struct PBVH PBVH; @@ -456,30 +457,10 @@ bool pbvh_has_face_sets(PBVH *bvh); void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets); /* Parallelization */ -typedef void (*PBVHParallelRangeFunc)(void *__restrict userdata, - const int iter, - const struct TaskParallelTLS *__restrict tls); -typedef void (*PBVHParallelReduceFunc)(const void *__restrict userdata, - void *__restrict chunk_join, - void *__restrict chunk); - -typedef struct PBVHParallelSettings { - bool use_threading; - void *userdata_chunk; - size_t userdata_chunk_size; - PBVHParallelReduceFunc func_reduce; -} PBVHParallelSettings; - -void BKE_pbvh_parallel_range_settings(struct PBVHParallelSettings *settings, +void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode); -void BKE_pbvh_parallel_range(const int start, - const int stop, - void *userdata, - PBVHParallelRangeFunc func, - const struct PBVHParallelSettings *settings); - struct MVert *BKE_pbvh_get_verts(const PBVH *bvh); #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index c2fad6db314..164783f4d14 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index d7ce9625548..063c0831a0d 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -21,16 +21,16 @@ * \ingroup bke */ -#ifdef __cplusplus -extern "C" { -#endif - #include <stdio.h> #include "BLI_compiler_attrs.h" #include "BLI_utildefines.h" #include "DNA_windowmanager_types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Reporting Information and Errors * * These functions also accept NULL in case no error reporting diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 5f0c10c9a5f..cf3061248f5 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -219,6 +219,15 @@ struct ImBuf *BKE_sequencer_give_ibuf_seqbase(const SeqRenderData *context, float cfra, int chan_shown, struct ListBase *seqbasep); +struct ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh, + const SeqRenderData *context, + struct Sequence *seq, + float cfra, + float facf0, + float facf1, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3); /* ********************************************************************** * sequencer.c @@ -375,6 +384,10 @@ struct Sequence *BKE_sequencer_prefetch_get_original_sequence(struct Sequence *s /* intern */ struct SeqEffectHandle BKE_sequence_get_blend(struct Sequence *seq); void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force); +float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + int input); /* extern */ struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq); @@ -508,6 +521,7 @@ void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); void BKE_sequence_init_colorspace(struct Sequence *seq); float BKE_sequence_get_fps(struct Scene *scene, struct Sequence *seq); +float BKE_sequencer_give_stripelem_index(struct Sequence *seq, float cfra); /* RNA enums, just to be more readable */ enum { diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index c8386a42c9a..bdc782a606e 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -162,20 +162,20 @@ typedef struct ShaderFxTypeInfo { /* Initialize global data (type info and some common global storages). */ void BKE_shaderfx_init(void); -const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type); +const ShaderFxTypeInfo *BKE_shaderfx_get_info(ShaderFxType type); struct ShaderFxData *BKE_shaderfx_new(int type); void BKE_shaderfx_free_ex(struct ShaderFxData *fx, const int flag); void BKE_shaderfx_free(struct ShaderFxData *fx); bool BKE_shaderfx_unique_name(struct ListBase *shaderfx, struct ShaderFxData *fx); -bool BKE_shaderfx_dependsOnTime(struct ShaderFxData *fx); -struct ShaderFxData *BKE_shaderfx_findByType(struct Object *ob, ShaderFxType type); -struct ShaderFxData *BKE_shaderfx_findByName(struct Object *ob, const char *name); -void BKE_shaderfx_copyData_generic(const struct ShaderFxData *fx_src, struct ShaderFxData *fx_dst); -void BKE_shaderfx_copyData(struct ShaderFxData *fx, struct ShaderFxData *target); -void BKE_shaderfx_copyData_ex(struct ShaderFxData *fx, +bool BKE_shaderfx_depends_ontime(struct ShaderFxData *fx); +struct ShaderFxData *BKE_shaderfx_findby_type(struct Object *ob, ShaderFxType type); +struct ShaderFxData *BKE_shaderfx_findby_name(struct Object *ob, const char *name); +void BKE_shaderfx_copydata_generic(const struct ShaderFxData *fx_src, struct ShaderFxData *fx_dst); +void BKE_shaderfx_copydata(struct ShaderFxData *fx, struct ShaderFxData *target); +void BKE_shaderfx_copydata_ex(struct ShaderFxData *fx, struct ShaderFxData *target, const int flag); -void BKE_shaderfx_foreachIDLink(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData); +void BKE_shaderfx_foreach_ID_link(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData); bool BKE_shaderfx_has_gpencil(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h new file mode 100644 index 00000000000..aad0ada75a9 --- /dev/null +++ b/source/blender/blenkernel/BKE_simulation.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef __BKE_SIMULATION_H__ +#define __BKE_SIMULATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Main; +struct Simulation; + +void *BKE_simulation_add(struct Main *bmain, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_SIMULATION_H__ */ diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 685582bcecf..b93591b7b60 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -164,7 +164,7 @@ void BKE_sound_stop_scene(struct Scene *scene); void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene); -float BKE_sound_sync_scene(struct Scene *scene); +double BKE_sound_sync_scene(struct Scene *scene); int BKE_sound_scene_playing(struct Scene *scene); @@ -180,10 +180,10 @@ float BKE_sound_get_length(struct Main *bmain, struct bSound *sound); char **BKE_sound_get_device_names(void); -typedef void (*SoundJackSyncCallback)(struct Main *bmain, int mode, float time); +typedef void (*SoundJackSyncCallback)(struct Main *bmain, int mode, double time); void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback); -void BKE_sound_jack_scene_update(struct Scene *scene, int mode, float time); +void BKE_sound_jack_scene_update(struct Scene *scene, int mode, double time); /* Dependency graph evaluation. */ diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 7c7638e65d2..8d2565c31f7 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -40,7 +40,7 @@ struct DMFlagMat; struct Mesh; struct Subdiv; -/* ============================================================================= +/* -------------------------------------------------------------------- * Masks. */ @@ -61,7 +61,7 @@ typedef struct SubdivCCGMaskEvaluator { bool BKE_subdiv_ccg_mask_init_from_paint(SubdivCCGMaskEvaluator *mask_evaluator, const struct Mesh *mesh); -/* ============================================================================= +/* -------------------------------------------------------------------- * Materials. */ @@ -80,7 +80,7 @@ typedef struct SubdivCCGMaterialFlagsEvaluator { void BKE_subdiv_ccg_material_flags_init_from_mesh( SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator, const struct Mesh *mesh); -/* ============================================================================= +/* -------------------------------------------------------------------- * SubdivCCG. */ diff --git a/source/blender/blenkernel/BKE_text_suggestions.h b/source/blender/blenkernel/BKE_text_suggestions.h index dc908ee5232..d618fcd6d11 100644 --- a/source/blender/blenkernel/BKE_text_suggestions.h +++ b/source/blender/blenkernel/BKE_text_suggestions.h @@ -23,12 +23,12 @@ * \ingroup bke */ +#include "DNA_text_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_text_types.h" - /* **************************************************************************** * Suggestions should be added in sorted order although a linear sorting method is * implemented. The list is then divided up based on the prefix provided by diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 20236745438..bb88fbf863b 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -261,8 +261,16 @@ void BKE_tracking_distortion_undistort_v2(struct MovieDistortion *distortion, float r_co[2]); void BKE_tracking_distortion_free(struct MovieDistortion *distortion); -void BKE_tracking_distort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]); -void BKE_tracking_undistort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]); +void BKE_tracking_distort_v2(struct MovieTracking *tracking, + int image_width, + int image_height, + const float co[2], + float r_co[2]); +void BKE_tracking_undistort_v2(struct MovieTracking *tracking, + int image_width, + int image_height, + const float co[2], + float r_co[2]); struct ImBuf *BKE_tracking_undistort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, @@ -276,6 +284,8 @@ struct ImBuf *BKE_tracking_distort_frame(struct MovieTracking *tracking, float overscan); void BKE_tracking_max_distortion_delta_across_bound(struct MovieTracking *tracking, + int image_width, + int image_height, struct rcti *rect, bool undistort, float delta[2]); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 6e612df33d5..9716e5f5d3f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -116,11 +116,13 @@ set(SRC intern/editmesh_tangent.c intern/effect.c intern/fcurve.c + intern/fcurve_driver.c intern/fluid.c intern/fmodifier.c intern/font.c intern/freestyle.c intern/gpencil.c + intern/gpencil_curve.c intern/gpencil_geom.c intern/gpencil_modifier.c intern/hair.c @@ -175,9 +177,11 @@ set(SRC intern/multires_reshape_apply_base.c intern/multires_reshape_ccg.c intern/multires_reshape_smooth.c + intern/multires_reshape_subdivide.c intern/multires_reshape_util.c intern/multires_reshape_vertcos.c intern/multires_subdiv.c + intern/multires_unsubdivide.c intern/nla.c intern/node.c intern/object.c @@ -197,7 +201,6 @@ set(SRC intern/particle_system.c intern/pbvh.c intern/pbvh_bmesh.c - intern/pbvh_parallel.cc intern/pointcache.c intern/pointcloud.c intern/report.c @@ -211,6 +214,7 @@ set(SRC intern/sequencer.c intern/shader_fx.c intern/shrinkwrap.c + intern/simulation.cc intern/softbody.c intern/sound.c intern/speaker.c @@ -299,11 +303,13 @@ set(SRC BKE_editmesh_tangent.h BKE_effect.h BKE_fcurve.h + BKE_fcurve_driver.h BKE_fluid.h BKE_font.h BKE_freestyle.h BKE_global.h BKE_gpencil.h + BKE_gpencil_curve.h BKE_gpencil_geom.h BKE_gpencil_modifier.h BKE_hair.h @@ -362,6 +368,7 @@ set(SRC BKE_sequencer.h BKE_shader_fx.h BKE_shrinkwrap.h + BKE_simulation.h BKE_softbody.h BKE_sound.h BKE_speaker.h @@ -396,6 +403,7 @@ set(SRC intern/lib_intern.h intern/multires_inline.h intern/multires_reshape.h + intern/multires_unsubdivide.h intern/pbvh_intern.h intern/subdiv_converter.h intern/subdiv_inline.h @@ -666,17 +674,6 @@ if(WITH_QUADRIFLOW) add_definitions(-DWITH_QUADRIFLOW) endif() -if(WITH_TBB) - add_definitions(-DWITH_TBB) - - list(APPEND INC_SYS - ${TBB_INCLUDE_DIRS} - ) - list(APPEND LIB - ${TBB_LIBRARIES} - ) -endif() - if(WITH_XR_OPENXR) add_definitions(-DWITH_XR_OPENXR) endif() diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index baef2b2290e..b3893d8600f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -698,7 +698,8 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free) /* apply shape key for cloth, this should really be solved * by a more flexible customdata system, but not simple */ if (!em) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type( + ob, eModifierType_Cloth); KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest); @@ -901,21 +902,21 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* Sculpt can skip certain modifiers. */ MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); - const bool has_multires = (mmd && BKE_multires_sculpt_level_get(mmd) != 0); + const bool has_multires = (mmd && mmd->sculptlvl != 0); bool multires_applied = false; const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !use_render; const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !use_render; /* Modifier evaluation contexts for different types of modifiers. */ - ModifierApplyFlag app_render = use_render ? MOD_APPLY_RENDER : 0; - ModifierApplyFlag app_cache = use_cache ? MOD_APPLY_USECACHE : 0; - const ModifierEvalContext mectx = {depsgraph, ob, app_render | app_cache}; - const ModifierEvalContext mectx_orco = {depsgraph, ob, app_render | MOD_APPLY_ORCO}; + ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : 0; + ModifierApplyFlag apply_cache = use_cache ? MOD_APPLY_USECACHE : 0; + const ModifierEvalContext mectx = {depsgraph, ob, apply_render | apply_cache}; + const ModifierEvalContext mectx_orco = {depsgraph, ob, apply_render | MOD_APPLY_ORCO}; /* Get effective list of modifiers to execute. Some effects like shape keys * are added as virtual modifiers before the user created modifiers. */ VirtualModifierData virtualModifierData; - ModifierData *firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *firstmd = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *md = firstmd; /* Preview colors by modifiers such as dynamic paint, to show the results @@ -929,7 +930,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* XXX Currently, DPaint modifier just ignores this. * Needs a stupid hack... * The whole "modifier preview" thing has to be (re?)designed, anyway! */ - previewmd = modifiers_getLastPreview(scene, md, required_mode); + previewmd = BKE_modifier_get_last_preview(scene, md, required_mode); } /* Compute accumulated datamasks needed by each modifier. It helps to do @@ -937,21 +938,21 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, * an armature modifier, but not through a following subsurf modifier where * subdividing them is expensive. */ CustomData_MeshMasks final_datamask = *dataMask; - CDMaskLink *datamasks = modifiers_calcDataMasks( + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( scene, ob, md, &final_datamask, required_mode, previewmd, &previewmask); CDMaskLink *md_datamask = datamasks; /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX; /* Clear errors before evaluation. */ - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); /* Apply all leading deform modifiers. */ if (useDeform) { for (; md; md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } @@ -971,7 +972,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } - modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); isPrevDeform = true; } @@ -1001,9 +1002,9 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* Apply all remaining constructive and deforming modifiers. */ bool have_non_onlydeform_modifiers_appled = false; for (; md; md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } @@ -1013,15 +1014,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && have_non_onlydeform_modifiers_appled) { - modifier_setError(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); continue; } if (sculpt_mode && (!has_multires || multires_applied || sculpt_dyntopo)) { bool unsupported = false; - if (md->type == eModifierType_Multires && - BKE_multires_sculpt_level_get((MultiresModifierData *)md) == 0) { + if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) { /* If multires is on level 0 skip it silently without warning message. */ if (!sculpt_dyntopo) { continue; @@ -1040,19 +1040,19 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if (unsupported) { if (sculpt_dyntopo) { - modifier_setError(md, "Not supported in dyntopo"); + BKE_modifier_set_error(md, "Not supported in dyntopo"); } else { - modifier_setError(md, "Not supported in sculpt mode"); + BKE_modifier_set_error(md, "Not supported in sculpt mode"); } continue; } else { - modifier_setError(md, "Sculpt: Hide, Mask and optimized display disabled"); + BKE_modifier_set_error(md, "Sculpt: Hide, Mask and optimized display disabled"); } } - if (need_mapping && !modifier_supportsMapping(md)) { + if (need_mapping && !BKE_modifier_supports_mapping(md)) { continue; } @@ -1094,7 +1094,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } - modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); } else { have_non_onlydeform_modifiers_appled = true; @@ -1176,7 +1176,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final); + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1212,7 +1212,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask); mesh_set_only_copy(mesh_orco, &temp_cddata_masks); - mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco); + mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1238,7 +1238,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, nextmask.pmask |= CD_MASK_ORIGINDEX; mesh_set_only_copy(mesh_orco_cloth, &nextmask); - mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco_cloth); + mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco_cloth); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1276,7 +1276,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, BLI_linklist_free((LinkNode *)datamasks, NULL); for (md = firstmd; md; md = md->next) { - modifier_freeTemporaryData(md); + BKE_modifier_free_temporary_data(md); } /* Yay, we are done. If we have a Mesh and deformed vertices, @@ -1376,15 +1376,15 @@ float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev_mesh) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { return false; } if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) { - modifier_setError(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); return false; } @@ -1486,30 +1486,30 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, /* Get effective list of modifiers to execute. Some effects like shape keys * are added as virtual modifiers before the user created modifiers. */ VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* Compute accumulated datamasks needed by each modifier. It helps to do * this fine grained so that for example vertex groups are preserved up to * an armature modifier, but not through a following subsurf modifier where * subdividing them is expensive. */ CustomData_MeshMasks final_datamask = *dataMask; - CDMaskLink *datamasks = modifiers_calcDataMasks( + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( scene, ob, md, &final_datamask, required_mode, NULL, NULL); CDMaskLink *md_datamask = datamasks; CustomData_MeshMasks append_mask = CD_MASK_BAREMESH; /* Evaluate modifiers up to certain index to get the mesh cage. */ - int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); if (r_cage && cageIndex == -1) { mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap( em_input, &final_datamask, NULL, mesh_input); } /* Clear errors before evaluation. */ - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (!editbmesh_modifier_is_enabled(scene, md, mesh_final != NULL)) { continue; @@ -1550,11 +1550,11 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } if (mti->deformVertsEM) { - modwrap_deformVertsEM( + BKE_modifier_deform_vertsEM( md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts); } else { - modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); } } else { @@ -1595,7 +1595,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, mask.pmask |= CD_MASK_ORIGINDEX; mesh_set_only_copy(mesh_orco, &mask); - Mesh *mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco); + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1626,7 +1626,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final); + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index ba77538bfb6..4f51e23496c 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1665,6 +1665,6 @@ void what_does_obaction( adt.action = act; /* execute effects of Action on to workob (or it's PoseChannels) */ - BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM, false); } } diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 41bfc5b59e4..02b7763a9b4 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -29,6 +29,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -95,6 +96,7 @@ bool id_type_can_have_animdata(const short id_type) case ID_HA: case ID_PT: case ID_VO: + case ID_SIM: return true; /* no AnimData */ @@ -1321,6 +1323,9 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use /* volumes */ ANIMDATA_IDS_CB(bmain->volumes.first); + + /* simulations */ + ANIMDATA_IDS_CB(bmain->simulations.first); } /* Fix all RNA-Paths throughout the database (directly access the Global.main version) @@ -1430,6 +1435,9 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, /* volumes */ RENAMEFIX_ANIM_IDS(bmain->volumes.first); + /* simulations */ + RENAMEFIX_ANIM_IDS(bmain->simulations.first); + /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(bmain->scenes.first, Scene); } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 18320ef0f8d..5e4b280d0d0 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -2500,7 +2500,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) * have been set already by the depsgraph. Now, we use the recalc */ void BKE_animsys_evaluate_animdata( - Scene *scene, ID *id, AnimData *adt, float ctime, short recalc, const bool flush_to_original) + ID *id, AnimData *adt, float ctime, eAnimData_Recalc recalc, const bool flush_to_original) { PointerRNA id_ptr; @@ -2547,13 +2547,6 @@ void BKE_animsys_evaluate_animdata( * - It is best that we execute this every time, so that no errors are likely to occur. */ animsys_evaluate_overrides(&id_ptr, adt); - - /* execute and clear all cached property update functions */ - if (scene) { - Main *bmain = G.main; // xxx - to get passed in! - RNA_property_update_cache_flush(bmain, scene); - RNA_property_update_cache_free(); - } } /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only @@ -2563,10 +2556,7 @@ void BKE_animsys_evaluate_animdata( * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a * standard 'root') block are overridden by a larger 'user' */ -void BKE_animsys_evaluate_all_animation(Main *main, - Depsgraph *depsgraph, - Scene *scene, - float ctime) +void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float ctime) { ID *id; @@ -2585,7 +2575,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, for (id = first; id; id = id->next) { \ if (ID_REAL_USERS(id) > 0) { \ AnimData *adt = BKE_animdata_from_id(id); \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2604,9 +2594,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, if (ntp->nodetree) { \ AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \ BKE_animsys_evaluate_animdata( \ - scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ + &ntp->nodetree->id, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ } \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2690,6 +2680,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, /* volumes */ EVAL_ANIM_IDS(main->volumes.first, ADT_RECALC_ANIM); + /* simulations */ + EVAL_ANIM_IDS(main->simulations.first, ADT_RECALC_ANIM); + /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets * this tagged by Depsgraph on framechange. This optimization means that objects @@ -2718,10 +2711,9 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id) AnimData *adt = BKE_animdata_from_id(id); /* XXX: this is only needed for flushing RNA updates, * which should get handled as part of the dependency graph instead. */ - Scene *scene = NULL; DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime); const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); } void BKE_animsys_update_driver_array(ID *id) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 4071cc024aa..8189385a69d 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -359,7 +359,7 @@ static bool get_path_user(char *targetpath, * \param folder_name: default name of folder within installation area * \param subfolder_name: optional name of subfolder within folder * \param ver: Blender version, used to construct a subdirectory name - * \return true if it was able to construct such a path. + * \return true if it was able to construct such a path. */ static bool get_path_system(char *targetpath, size_t targetpath_len, diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index af98992cc01..06a97fc3826 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -61,6 +61,7 @@ #include "BKE_idtype.h" #include "BKE_lattice.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -150,6 +151,24 @@ static void armature_free_data(struct ID *id) } } +static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data) +{ + IDP_foreach_property( + bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + + LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) { + armature_foreach_id_bone(curbone, data); + } +} + +static void armature_foreach_id(ID *id, LibraryForeachIDData *data) +{ + bArmature *arm = (bArmature *)id; + LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { + armature_foreach_id_bone(bone, data); + } +} + IDTypeInfo IDType_ID_AR = { .id_code = ID_AR, .id_filter = FILTER_ID_AR, @@ -164,6 +183,7 @@ IDTypeInfo IDType_ID_AR = { .copy_data = armature_copy_data, .free_data = armature_free_data, .make_local = NULL, + .foreach_id = armature_foreach_id, }; /* **************** Generic Functions, data level *************** */ diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 5c000fbcb36..13dcc7b06f6 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -279,9 +279,6 @@ static void setup_app_data(bContext *C, // CTX_wm_manager_set(C, NULL); BKE_blender_globals_clear(); - /* clear old property update cache, in case some old references are left dangling */ - RNA_property_update_cache_free(); - bmain = G_MAIN = bfd->main; bfd->main = NULL; diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index a493d5f49c8..6197b9dbefd 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -861,7 +861,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, SurfaceModifierData *surmd = NULL; float x[3], v[3]; - surmd = (SurfaceModifierData *)modifiers_findByType(bpa->ground, eModifierType_Surface); + surmd = (SurfaceModifierData *)BKE_modifiers_findby_type(bpa->ground, eModifierType_Surface); /* take surface velocity into account */ closest_point_on_surface(surmd, pa->state.co, x, NULL, v); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 8d35abc1523..0e6b9409404 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -49,7 +49,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "RE_render_ext.h" /* externtex */ +#include "RE_render_ext.h" /* RE_texture_evaluate */ static void brush_init_data(ID *id) { @@ -89,6 +89,19 @@ static void brush_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c brush_src->gpencil_settings->curve_strength); brush_dst->gpencil_settings->curve_jitter = BKE_curvemapping_copy( brush_src->gpencil_settings->curve_jitter); + + brush_dst->gpencil_settings->curve_rand_pressure = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_pressure); + brush_dst->gpencil_settings->curve_rand_strength = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_strength); + brush_dst->gpencil_settings->curve_rand_uv = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_uv); + brush_dst->gpencil_settings->curve_rand_hue = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_hue); + brush_dst->gpencil_settings->curve_rand_saturation = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_saturation); + brush_dst->gpencil_settings->curve_rand_value = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_value); } /* enable fake user by default */ @@ -107,6 +120,14 @@ static void brush_free_data(ID *id) BKE_curvemapping_free(brush->gpencil_settings->curve_sensitivity); BKE_curvemapping_free(brush->gpencil_settings->curve_strength); BKE_curvemapping_free(brush->gpencil_settings->curve_jitter); + + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_pressure); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_strength); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_uv); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_hue); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_saturation); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_value); + MEM_SAFE_FREE(brush->gpencil_settings); } @@ -280,6 +301,13 @@ void BKE_brush_init_gpencil_settings(Brush *brush) brush->gpencil_settings->curve_sensitivity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); brush->gpencil_settings->curve_strength = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); brush->gpencil_settings->curve_jitter = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + + brush->gpencil_settings->curve_rand_pressure = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_strength = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_uv = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_hue = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_saturation = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_value = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); } /* add a new gp-brush */ @@ -1572,8 +1600,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene, else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { /* Get strength by feeding the vertex * location directly into a texture */ - hasrgb = externtex( - mtex, point, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + hasrgb = RE_texture_evaluate(mtex, point, thread, pool, false, false, &intensity, rgba); } else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { float rotation = -mtex->rot; @@ -1603,8 +1630,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene, co[1] = y; co[2] = 0.0f; - hasrgb = externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } else { float rotation = -mtex->rot; @@ -1660,8 +1686,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene, co[1] = y; co[2] = 0.0f; - hasrgb = externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } intensity += br->texture_sample_bias; @@ -1718,8 +1743,7 @@ float BKE_brush_sample_masktex( co[1] = y; co[2] = 0.0f; - externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } else { float rotation = -mtex->rot; @@ -1775,8 +1799,7 @@ float BKE_brush_sample_masktex( co[1] = y; co[2] = 0.0f; - externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } CLAMP(intensity, 0.0f, 1.0f); @@ -2080,7 +2103,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_sec unsigned int *texcache = NULL; MTex *mtex = (use_secondary) ? &br->mask_mtex : &br->mtex; float intensity; - float rgba[4]; + float rgba_dummy[4]; int ix, iy; int side = half_side * 2; @@ -2098,11 +2121,8 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_sec /* This is copied from displace modifier code */ /* TODO(sergey): brush are always caching with CM enabled for now. */ - externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false); - - ((char *)texcache)[(iy * side + ix) * 4] = ((char *)texcache)[(iy * side + ix) * 4 + 1] = - ((char *)texcache)[(iy * side + ix) * 4 + 2] = (( - char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(intensity * 255.0f); + RE_texture_evaluate(mtex, co, 0, NULL, false, false, &intensity, rgba_dummy); + copy_v4_uchar((uchar *)&texcache[iy * side + ix], (char)(intensity * 255.0f)); } } } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 8a0df6375be..879313783d9 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 04663115424..0b9780ac81c 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -333,13 +333,13 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int if (clmd->clothObject == NULL) { if (!cloth_from_object(ob, clmd, result, framenr, 1)) { BKE_ptcache_invalidate(cache); - modifier_setError(&(clmd->modifier), "Can't initialize cloth"); + BKE_modifier_set_error(&(clmd->modifier), "Can't initialize cloth"); return 0; } if (clmd->clothObject == NULL) { BKE_ptcache_invalidate(cache); - modifier_setError(&(clmd->modifier), "Null cloth object"); + BKE_modifier_set_error(&(clmd->modifier), "Null cloth object"); return 0; } @@ -841,7 +841,7 @@ static int cloth_from_object( clmd->clothObject->edgeset = NULL; } else { - modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject"); + BKE_modifier_set_error(&(clmd->modifier), "Out of memory on allocating clmd->clothObject"); return 0; } @@ -913,7 +913,7 @@ static int cloth_from_object( if (!cloth_build_springs(clmd, mesh)) { cloth_free_modifier(clmd); - modifier_setError(&(clmd->modifier), "Cannot build springs"); + BKE_modifier_set_error(&(clmd->modifier), "Cannot build springs"); return 0; } @@ -943,7 +943,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) "clothVertex"); if (clmd->clothObject->verts == NULL) { cloth_free_modifier(clmd); - modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts"); + BKE_modifier_set_error(&(clmd->modifier), + "Out of memory on allocating clmd->clothObject->verts"); printf("cloth_free_modifier clmd->clothObject->verts\n"); return; } @@ -959,7 +960,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) clmd->clothObject->tri = MEM_mallocN(sizeof(MVertTri) * looptri_num, "clothLoopTris"); if (clmd->clothObject->tri == NULL) { cloth_free_modifier(clmd); - modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->looptri"); + BKE_modifier_set_error(&(clmd->modifier), + "Out of memory on allocating clmd->clothObject->looptri"); printf("cloth_free_modifier clmd->clothObject->looptri\n"); return; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 7cc40007e26..daf1602319f 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1307,7 +1307,7 @@ static void add_collision_object(ListBase *relations, /* only get objects with collision modifier */ if (((modifier_type == eModifierType_Collision) && ob->pd && ob->pd->deflect) || (modifier_type != eModifierType_Collision)) { - cmd = (CollisionModifierData *)modifiers_findByType(ob, modifier_type); + cmd = (CollisionModifierData *)BKE_modifiers_findby_type(ob, modifier_type); } if (cmd) { @@ -1426,7 +1426,7 @@ ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collecti continue; } - CollisionModifierData *cmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *cmd = (CollisionModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Collision); if (cmd && cmd->bvhtree) { if (cache == NULL) { @@ -1527,7 +1527,7 @@ static int cloth_bvh_objcollisions_resolve(ClothModifierData *clmd, for (i = 0; i < numcollobj; i++) { Object *collob = collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *collmd = (CollisionModifierData *)BKE_modifiers_findby_type( collob, eModifierType_Collision); if (collmd->bvhtree) { @@ -1658,7 +1658,7 @@ int cloth_bvh_collision( for (i = 0; i < numcollobj; i++) { Object *collob = collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *collmd = (CollisionModifierData *)BKE_modifiers_findby_type( collob, eModifierType_Collision); if (!collmd->bvhtree) { @@ -1693,7 +1693,7 @@ int cloth_bvh_collision( for (i = 0; i < numcollobj; i++) { Object *collob = collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *collmd = (CollisionModifierData *)BKE_modifiers_findby_type( collob, eModifierType_Collision); if (!collmd->bvhtree) { diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index f82b8b6675c..3da384a2745 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1383,8 +1383,6 @@ typedef struct ScopesUpdateData { struct ColormanageProcessor *cm_processor; const unsigned char *display_buffer; const int ycc_mode; - - unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; } ScopesUpdateData; typedef struct ScopesUpdateDataChunk { @@ -1495,23 +1493,24 @@ static void scopes_update_cb(void *__restrict userdata, } } -static void scopes_update_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void scopes_update_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - const ScopesUpdateData *data = userdata; - const ScopesUpdateDataChunk *data_chunk = userdata_chunk; - - unsigned int *bin_lum = data->bin_lum; - unsigned int *bin_r = data->bin_r; - unsigned int *bin_g = data->bin_g; - unsigned int *bin_b = data->bin_b; - unsigned int *bin_a = data->bin_a; + ScopesUpdateDataChunk *join_chunk = chunk_join; + const ScopesUpdateDataChunk *data_chunk = chunk; + + unsigned int *bin_lum = join_chunk->bin_lum; + unsigned int *bin_r = join_chunk->bin_r; + unsigned int *bin_g = join_chunk->bin_g; + unsigned int *bin_b = join_chunk->bin_b; + unsigned int *bin_a = join_chunk->bin_a; const unsigned int *bin_lum_c = data_chunk->bin_lum; const unsigned int *bin_r_c = data_chunk->bin_r; const unsigned int *bin_g_c = data_chunk->bin_g; const unsigned int *bin_b_c = data_chunk->bin_b; const unsigned int *bin_a_c = data_chunk->bin_a; - float(*minmax)[2] = data->scopes->minmax; const float *min = data_chunk->min; const float *max = data_chunk->max; @@ -1524,11 +1523,11 @@ static void scopes_update_finalize(void *__restrict userdata, void *__restrict u } for (int c = 3; c--;) { - if (min[c] < minmax[c][0]) { - minmax[c][0] = min[c]; + if (min[c] < join_chunk->min[c]) { + join_chunk->min[c] = min[c]; } - if (max[c] > minmax[c][1]) { - minmax[c][1] = max[c]; + if (max[c] > join_chunk->max[c]) { + join_chunk->max[c] = max[c]; } } } @@ -1542,7 +1541,6 @@ void BKE_scopes_update(Scopes *scopes, unsigned int nl, na, nr, ng, nb; double divl, diva, divr, divg, divb; const unsigned char *display_buffer = NULL; - uint bin_lum[256] = {0}, bin_r[256] = {0}, bin_g[256] = {0}, bin_b[256] = {0}, bin_a[256] = {0}; int ycc_mode = -1; void *cache_handle = NULL; struct ColormanageProcessor *cm_processor = NULL; @@ -1638,11 +1636,6 @@ void BKE_scopes_update(Scopes *scopes, .cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode, - .bin_lum = bin_lum, - .bin_r = bin_r, - .bin_g = bin_g, - .bin_b = bin_b, - .bin_a = bin_a, }; ScopesUpdateDataChunk data_chunk = {{0}}; INIT_MINMAX(data_chunk.min, data_chunk.max); @@ -1652,26 +1645,26 @@ void BKE_scopes_update(Scopes *scopes, settings.use_threading = (ibuf->y > 256); settings.userdata_chunk = &data_chunk; settings.userdata_chunk_size = sizeof(data_chunk); - settings.func_finalize = scopes_update_finalize; + settings.func_reduce = scopes_update_reduce; BLI_task_parallel_range(0, ibuf->y, &data, scopes_update_cb, &settings); /* convert hist data to float (proportional to max count) */ nl = na = nr = nb = ng = 0; for (a = 0; a < 256; a++) { - if (bin_lum[a] > nl) { - nl = bin_lum[a]; + if (data_chunk.bin_lum[a] > nl) { + nl = data_chunk.bin_lum[a]; } - if (bin_r[a] > nr) { - nr = bin_r[a]; + if (data_chunk.bin_r[a] > nr) { + nr = data_chunk.bin_r[a]; } - if (bin_g[a] > ng) { - ng = bin_g[a]; + if (data_chunk.bin_g[a] > ng) { + ng = data_chunk.bin_g[a]; } - if (bin_b[a] > nb) { - nb = bin_b[a]; + if (data_chunk.bin_b[a] > nb) { + nb = data_chunk.bin_b[a]; } - if (bin_a[a] > na) { - na = bin_a[a]; + if (data_chunk.bin_a[a] > na) { + na = data_chunk.bin_a[a]; } } divl = nl ? 1.0 / (double)nl : 1.0; @@ -1681,11 +1674,11 @@ void BKE_scopes_update(Scopes *scopes, divb = nb ? 1.0 / (double)nb : 1.0; for (a = 0; a < 256; a++) { - scopes->hist.data_luma[a] = bin_lum[a] * divl; - scopes->hist.data_r[a] = bin_r[a] * divr; - scopes->hist.data_g[a] = bin_g[a] * divg; - scopes->hist.data_b[a] = bin_b[a] * divb; - scopes->hist.data_a[a] = bin_a[a] * diva; + scopes->hist.data_luma[a] = data_chunk.bin_lum[a] * divl; + scopes->hist.data_r[a] = data_chunk.bin_r[a] * divr; + scopes->hist.data_g[a] = data_chunk.bin_g[a] * divg; + scopes->hist.data_b[a] = data_chunk.bin_b[a] * divb; + scopes->hist.data_a[a] = data_chunk.bin_a[a] * diva; } if (cm_processor) { diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 099fdacf401..679fe703b13 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -62,7 +62,7 @@ #include "BKE_deform.h" #include "BKE_displist.h" #include "BKE_editmesh.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_lib_id.h" @@ -1009,8 +1009,8 @@ static void trackto_new_data(void *cdata) { bTrackToConstraint *data = (bTrackToConstraint *)cdata; - data->reserved1 = TRACK_Y; - data->reserved2 = UP_Z; + data->reserved1 = TRACK_nZ; + data->reserved2 = UP_Y; } static void trackto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -4590,230 +4590,390 @@ static void followtrack_id_looper(bConstraint *con, ConstraintIDFunc func, void func(con, (ID **)&data->depth_ob, false, userdata); } -static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) +static MovieClip *followtrack_tracking_clip_get(bConstraint *con, bConstraintOb *cob) { - Depsgraph *depsgraph = cob->depsgraph; - Scene *scene = cob->scene; bFollowTrackConstraint *data = con->data; - MovieClip *clip = data->clip; + + if (data->flag & FOLLOWTRACK_ACTIVECLIP) { + Scene *scene = cob->scene; + return scene->clip; + } + + return data->clip; +} + +static MovieTrackingObject *followtrack_tracking_object_get(bConstraint *con, bConstraintOb *cob) +{ + MovieClip *clip = followtrack_tracking_clip_get(con, cob); + MovieTracking *tracking = &clip->tracking; + bFollowTrackConstraint *data = con->data; + + if (data->object[0]) { + return BKE_tracking_object_get_named(tracking, data->object); + } + return BKE_tracking_object_get_camera(tracking); +} + +static Object *followtrack_camera_object_get(bConstraint *con, bConstraintOb *cob) +{ + bFollowTrackConstraint *data = con->data; + + if (data->camera == NULL) { + Scene *scene = cob->scene; + return scene->camera; + } + + return data->camera; +} + +typedef struct FollowTrackContext { + int flag; + int frame_method; + + Depsgraph *depsgraph; + Scene *scene; + + MovieClip *clip; + Object *camera_object; + Object *depth_object; + MovieTracking *tracking; - MovieTrackingTrack *track; MovieTrackingObject *tracking_object; - Object *camob = data->camera ? data->camera : scene->camera; + MovieTrackingTrack *track; - float ctime = DEG_get_ctime(depsgraph); - float framenr; + float depsgraph_time; + float clip_frame; +} FollowTrackContext; - if (data->flag & FOLLOWTRACK_ACTIVECLIP) { - clip = scene->clip; - } +static bool followtrack_context_init(FollowTrackContext *context, + bConstraint *con, + bConstraintOb *cob) +{ + bFollowTrackConstraint *data = con->data; - if (!clip || !data->track[0] || !camob) { - return; + context->flag = data->flag; + context->frame_method = data->frame_method; + + context->depsgraph = cob->depsgraph; + context->scene = cob->scene; + + context->clip = followtrack_tracking_clip_get(con, cob); + context->camera_object = followtrack_camera_object_get(con, cob); + if (context->clip == NULL || context->camera_object == NULL) { + return false; } + context->depth_object = data->depth_ob; - tracking = &clip->tracking; + context->tracking = &context->clip->tracking; + context->tracking_object = followtrack_tracking_object_get(con, cob); + if (context->tracking_object == NULL) { + return false; + } - if (data->object[0]) { - tracking_object = BKE_tracking_object_get_named(tracking, data->object); + context->track = BKE_tracking_track_get_named( + context->tracking, context->tracking_object, data->track); + if (context->track == NULL) { + return false; } - else { - tracking_object = BKE_tracking_object_get_camera(tracking); + + context->depsgraph_time = DEG_get_ctime(context->depsgraph); + context->clip_frame = BKE_movieclip_remap_scene_to_clip_frame(context->clip, + context->depsgraph_time); + + return true; +} + +static void followtrack_evaluate_using_3d_position_object(FollowTrackContext *context, + bConstraintOb *cob) +{ + Object *camera_object = context->camera_object; + MovieTracking *tracking = context->tracking; + MovieTrackingTrack *track = context->track; + MovieTrackingObject *tracking_object = context->tracking_object; + + /* Matrix of the object which is being solved prior to this contraint. */ + float obmat[4][4]; + copy_m4_m4(obmat, cob->matrix); + + /* Object matrix of the camera. */ + float camera_obmat[4][4]; + copy_m4_m4(camera_obmat, camera_object->obmat); + + /* Calculate inverted matrix of the solved camera at the current time. */ + float reconstructed_camera_mat[4][4]; + BKE_tracking_camera_get_reconstructed_interpolate( + tracking, tracking_object, context->clip_frame, reconstructed_camera_mat); + float reconstructed_camera_mat_inv[4][4]; + invert_m4_m4(reconstructed_camera_mat_inv, reconstructed_camera_mat); + + mul_m4_series(cob->matrix, obmat, camera_obmat, reconstructed_camera_mat_inv); + translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); +} + +static void followtrack_evaluate_using_3d_position_camera(FollowTrackContext *context, + bConstraintOb *cob) +{ + Object *camera_object = context->camera_object; + MovieTrackingTrack *track = context->track; + + /* Matrix of the object which is being solved prior to this contraint. */ + float obmat[4][4]; + copy_m4_m4(obmat, cob->matrix); + + float reconstructed_camera_mat[4][4]; + BKE_tracking_get_camera_object_matrix(camera_object, reconstructed_camera_mat); + + mul_m4_m4m4(cob->matrix, obmat, reconstructed_camera_mat); + translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); +} + +static void followtrack_evaluate_using_3d_position(FollowTrackContext *context, bConstraintOb *cob) +{ + MovieTrackingTrack *track = context->track; + if ((track->flag & TRACK_HAS_BUNDLE) == 0) { + return; } - if (!tracking_object) { + if ((context->tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { + followtrack_evaluate_using_3d_position_object(context, cob); return; } - track = BKE_tracking_track_get_named(tracking, tracking_object, data->track); + followtrack_evaluate_using_3d_position_camera(context, cob); +} - if (!track) { +/* Apply undistortion if it is enabled in constraint settings. */ +static void followtrack_undistort_if_needed(FollowTrackContext *context, + const int clip_width, + const int clip_height, + float marker_position[2]) +{ + if ((context->flag & FOLLOWTRACK_USE_UNDISTORTION) == 0) { return; } - framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); + /* Undistortion need to happen in pixel space. */ + marker_position[0] *= clip_width; + marker_position[1] *= clip_height; - if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { - if (track->flag & TRACK_HAS_BUNDLE) { - float obmat[4][4], mat[4][4]; + BKE_tracking_undistort_v2( + context->tracking, clip_width, clip_height, marker_position, marker_position); - copy_m4_m4(obmat, cob->matrix); + /* Normalize pixel coordinates back. */ + marker_position[0] /= clip_width; + marker_position[1] /= clip_height; +} - if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { - float imat[4][4]; +/* Modify the marker position matching the frame fitting method. */ +static void followtrack_fit_frame(FollowTrackContext *context, + const int clip_width, + const int clip_height, + float marker_position[2]) +{ + if (context->frame_method == FOLLOWTRACK_FRAME_STRETCH) { + return; + } - copy_m4_m4(mat, camob->obmat); + Scene *scene = context->scene; + MovieClip *clip = context->clip; - BKE_tracking_camera_get_reconstructed_interpolate( - tracking, tracking_object, framenr, imat); - invert_m4(imat); + /* apply clip display aspect */ + const float w_src = clip_width * clip->aspx; + const float h_src = clip_height * clip->aspy; - mul_m4_series(cob->matrix, obmat, mat, imat); - translate_m4( - cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); - } - else { - BKE_tracking_get_camera_object_matrix(camob, mat); + const float w_dst = scene->r.xsch * scene->r.xasp; + const float h_dst = scene->r.ysch * scene->r.yasp; - mul_m4_m4m4(cob->matrix, obmat, mat); - translate_m4( - cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); - } - } + const float asp_src = w_src / h_src; + const float asp_dst = w_dst / h_dst; + + if (fabsf(asp_src - asp_dst) < FLT_EPSILON) { + return; + } + + if ((asp_src > asp_dst) == (context->frame_method == FOLLOWTRACK_FRAME_CROP)) { + /* fit X */ + float div = asp_src / asp_dst; + float cent = (float)clip_width / 2.0f; + + marker_position[0] = (((marker_position[0] * clip_width - cent) * div) + cent) / clip_width; } else { - float vec[3], disp[3], axis[3], mat[4][4]; - float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); - float len, d; + /* fit Y */ + float div = asp_dst / asp_src; + float cent = (float)clip_height / 2.0f; - BKE_object_where_is_calc_mat4(camob, mat); + marker_position[1] = (((marker_position[1] * clip_height - cent) * div) + cent) / clip_height; + } +} - /* camera axis */ - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 1.0f; - mul_v3_m4v3(axis, mat, vec); +/* Effectively this is a Z-depth of the object form the movie clip camera. + * The idea is to preserve this depth while moving the object in 2D. */ +static float followtrack_distance_from_viewplane_get(FollowTrackContext *context, + bConstraintOb *cob) +{ + Object *camera_object = context->camera_object; - /* distance to projection plane */ - copy_v3_v3(vec, cob->matrix[3]); - sub_v3_v3(vec, mat[3]); - project_v3_v3v3(disp, vec, axis); + float camera_matrix[4][4]; + BKE_object_where_is_calc_mat4(camera_object, camera_matrix); - len = len_v3(disp); + const float z_axis[3] = {0.0f, 0.0f, 1.0f}; - if (len > FLT_EPSILON) { - CameraParams params; - int width, height; - float pos[2], rmat[4][4]; + /* Direction of camera's local Z axis in the world space. */ + float camera_axis[3]; + mul_v3_mat3_m4v3(camera_axis, camera_matrix, z_axis); - BKE_movieclip_get_size(clip, NULL, &width, &height); - BKE_tracking_marker_get_subframe_position(track, framenr, pos); + /* Distance to projection plane. */ + float vec[3]; + copy_v3_v3(vec, cob->matrix[3]); + sub_v3_v3(vec, camera_matrix[3]); - if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) { - /* Undistortion need to happen in pixel space. */ - pos[0] *= width; - pos[1] *= height; + float projection[3]; + project_v3_v3v3(projection, vec, camera_axis); - BKE_tracking_undistort_v2(tracking, pos, pos); + return len_v3(projection); +} - /* Normalize pixel coordinates back. */ - pos[0] /= width; - pos[1] /= height; - } +/* For the evaluated constraint object project it to the surface of the depth object. */ +static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *context, + bConstraintOb *cob) +{ + if (context->depth_object == NULL) { + return; + } - /* aspect correction */ - if (data->frame_method != FOLLOWTRACK_FRAME_STRETCH) { - float w_src, h_src, w_dst, h_dst, asp_src, asp_dst; + Object *depth_object = context->depth_object; + Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object); + if (depth_mesh == NULL) { + return; + } - /* apply clip display aspect */ - w_src = width * clip->aspx; - h_src = height * clip->aspy; + float depth_object_mat_inv[4][4]; + invert_m4_m4(depth_object_mat_inv, depth_object->obmat); - w_dst = scene->r.xsch * scene->r.xasp; - h_dst = scene->r.ysch * scene->r.yasp; + float ray_start[3], ray_end[3]; + mul_v3_m4v3(ray_start, depth_object_mat_inv, context->camera_object->obmat[3]); + mul_v3_m4v3(ray_end, depth_object_mat_inv, cob->matrix[3]); - asp_src = w_src / h_src; - asp_dst = w_dst / h_dst; + float ray_direction[3]; + sub_v3_v3v3(ray_direction, ray_end, ray_start); + normalize_v3(ray_direction); - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { - if ((asp_src > asp_dst) == (data->frame_method == FOLLOWTRACK_FRAME_CROP)) { - /* fit X */ - float div = asp_src / asp_dst; - float cent = (float)width / 2.0f; + BVHTreeFromMesh tree_data = NULL_BVHTreeFromMesh; + BKE_bvhtree_from_mesh_get(&tree_data, depth_mesh, BVHTREE_FROM_LOOPTRI, 4); - pos[0] = (((pos[0] * width - cent) * div) + cent) / width; - } - else { - /* fit Y */ - float div = asp_dst / asp_src; - float cent = (float)height / 2.0f; + BVHTreeRayHit hit; + hit.dist = BVH_RAYCAST_DIST_MAX; + hit.index = -1; - pos[1] = (((pos[1] * height - cent) * div) + cent) / height; - } - } - } + const int result = BLI_bvhtree_ray_cast(tree_data.tree, + ray_start, + ray_direction, + 0.0f, + &hit, + tree_data.raycast_callback, + &tree_data); - BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, camob); + if (result != -1) { + mul_v3_m4v3(cob->matrix[3], depth_object->obmat, hit.co); + } - if (params.is_ortho) { - vec[0] = params.ortho_scale * (pos[0] - 0.5f + params.shiftx); - vec[1] = params.ortho_scale * (pos[1] - 0.5f + params.shifty); - vec[2] = -len; + free_bvhtree_from_mesh(&tree_data); +} - if (aspect > 1.0f) { - vec[1] /= aspect; - } - else { - vec[0] *= aspect; - } +static void followtrack_evaluate_using_2d_position(FollowTrackContext *context, bConstraintOb *cob) +{ + Scene *scene = context->scene; + MovieClip *clip = context->clip; + MovieTrackingTrack *track = context->track; + Object *camera_object = context->camera_object; + const float clip_frame = context->clip_frame; + const float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); - mul_v3_m4v3(disp, camob->obmat, vec); + const float object_depth = followtrack_distance_from_viewplane_get(context, cob); + if (object_depth < FLT_EPSILON) { + return; + } - copy_m4_m4(rmat, camob->obmat); - zero_v3(rmat[3]); - mul_m4_m4m4(cob->matrix, cob->matrix, rmat); + int clip_width, clip_height; + BKE_movieclip_get_size(clip, NULL, &clip_width, &clip_height); - copy_v3_v3(cob->matrix[3], disp); - } - else { - d = (len * params.sensor_x) / (2.0f * params.lens); + float marker_position[2]; + BKE_tracking_marker_get_subframe_position(track, clip_frame, marker_position); - vec[0] = d * (2.0f * (pos[0] + params.shiftx) - 1.0f); - vec[1] = d * (2.0f * (pos[1] + params.shifty) - 1.0f); - vec[2] = -len; + followtrack_undistort_if_needed(context, clip_width, clip_height, marker_position); + followtrack_fit_frame(context, clip_width, clip_height, marker_position); - if (aspect > 1.0f) { - vec[1] /= aspect; - } - else { - vec[0] *= aspect; - } + float rmat[4][4]; + CameraParams params; + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, camera_object); - mul_v3_m4v3(disp, camob->obmat, vec); + if (params.is_ortho) { + float vec[3]; + vec[0] = params.ortho_scale * (marker_position[0] - 0.5f + params.shiftx); + vec[1] = params.ortho_scale * (marker_position[1] - 0.5f + params.shifty); + vec[2] = -object_depth; - /* apply camera rotation so Z-axis would be co-linear */ - copy_m4_m4(rmat, camob->obmat); - zero_v3(rmat[3]); - mul_m4_m4m4(cob->matrix, cob->matrix, rmat); + if (aspect > 1.0f) { + vec[1] /= aspect; + } + else { + vec[0] *= aspect; + } - copy_v3_v3(cob->matrix[3], disp); - } + float disp[3]; + mul_v3_m4v3(disp, camera_object->obmat, vec); - if (data->depth_ob) { - Object *depth_ob = data->depth_ob; - Mesh *target_eval = BKE_object_get_evaluated_mesh(depth_ob); - if (target_eval) { - BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; - BVHTreeRayHit hit; - float ray_start[3], ray_end[3], ray_nor[3], imat[4][4]; - int result; + copy_m4_m4(rmat, camera_object->obmat); + zero_v3(rmat[3]); + mul_m4_m4m4(cob->matrix, cob->matrix, rmat); - invert_m4_m4(imat, depth_ob->obmat); + copy_v3_v3(cob->matrix[3], disp); + } + else { + const float d = (object_depth * params.sensor_x) / (2.0f * params.lens); - mul_v3_m4v3(ray_start, imat, camob->obmat[3]); - mul_v3_m4v3(ray_end, imat, cob->matrix[3]); + float vec[3]; + vec[0] = d * (2.0f * (marker_position[0] + params.shiftx) - 1.0f); + vec[1] = d * (2.0f * (marker_position[1] + params.shifty) - 1.0f); + vec[2] = -object_depth; + + if (aspect > 1.0f) { + vec[1] /= aspect; + } + else { + vec[0] *= aspect; + } - sub_v3_v3v3(ray_nor, ray_end, ray_start); - normalize_v3(ray_nor); + float disp[3]; + mul_v3_m4v3(disp, camera_object->obmat, vec); - BKE_bvhtree_from_mesh_get(&treeData, target_eval, BVHTREE_FROM_LOOPTRI, 4); + /* apply camera rotation so Z-axis would be co-linear */ + copy_m4_m4(rmat, camera_object->obmat); + zero_v3(rmat[3]); + mul_m4_m4m4(cob->matrix, cob->matrix, rmat); - hit.dist = BVH_RAYCAST_DIST_MAX; - hit.index = -1; + copy_v3_v3(cob->matrix[3], disp); + } - result = BLI_bvhtree_ray_cast( - treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData); + followtrack_project_to_depth_object_if_needed(context, cob); +} - if (result != -1) { - mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co); - } +static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) +{ + FollowTrackContext context; + if (!followtrack_context_init(&context, con, cob)) { + return; + } - free_bvhtree_from_mesh(&treeData); - } - } - } + bFollowTrackConstraint *data = con->data; + if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { + followtrack_evaluate_using_3d_position(&context, cob); + return; } + + followtrack_evaluate_using_2d_position(&context, cob); } static bConstraintTypeInfo CTI_FOLLOWTRACK = { diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 7ec1da8eab4..f4acbdca772 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -84,7 +84,7 @@ static void set_crazy_vertex_quat(float r_quat[4], static bool modifiers_disable_subsurf_temporary(struct Scene *scene, Object *ob) { bool disabled = false; - int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); ModifierData *md = ob->modifiers.first; for (int i = 0; md && i <= cageIndex; i++, md = md->next) { @@ -265,20 +265,20 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra Mesh *me_input = ob->data; Mesh *me = NULL; int i, a, numleft = 0, numVerts = 0; - int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; VirtualModifierData virtualModifierData; ModifierEvalContext mectx = {depsgraph, ob, 0}; - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); - md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* compute the deformation matrices and coordinates for the first * modifiers with on cage editing that are enabled and support computing * deform matrices */ for (i = 0; md && i <= cageIndex; i++, md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (!editbmesh_modifier_is_enabled(scene, md, me != NULL)) { continue; @@ -288,7 +288,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra if (!defmats) { const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; CustomData_MeshMasks cd_mask_extra = CD_MASK_BAREMESH; - CDMaskLink *datamasks = modifiers_calcDataMasks( + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( scene, ob, md, &cd_mask_extra, required_mode, NULL, NULL); cd_mask_extra = datamasks->mask; BLI_linklist_free((LinkNode *)datamasks, NULL); @@ -310,7 +310,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra for (; md && i <= cageIndex; md = md->next, i++) { if (editbmesh_modifier_is_enabled(scene, md, me != NULL) && - modifier_isCorrectableDeformed(md)) { + BKE_modifier_is_correctable_deformed(md)) { numleft++; } } @@ -361,13 +361,13 @@ static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md) if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) { return true; } - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_OnlyDeform); } static bool crazyspace_modifier_supports_deform(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_OnlyDeform); } @@ -386,7 +386,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, crazyspace_init_object_for_eval(depsgraph, object, &object_eval); MultiresModifierData *mmd = get_multires_modifier(scene, &object_eval, 0); const bool is_sculpt_mode = (object->mode & OB_MODE_SCULPT) != 0; - const bool has_multires = mmd != NULL && BKE_multires_sculpt_level_get(mmd) > 0; + const bool has_multires = mmd != NULL && mmd->sculptlvl > 0; const ModifierEvalContext mectx = {depsgraph, &object_eval, 0}; if (is_sculpt_mode && has_multires) { @@ -395,15 +395,15 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, return numleft; } - md = modifiers_getVirtualModifierList(&object_eval, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } if (crazyspace_modifier_supports_deform_matrices(md)) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (defmats == NULL) { /* NOTE: Evaluated object si re-set to its original undeformed * state. */ @@ -425,7 +425,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, } for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } @@ -471,16 +471,16 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, VirtualModifierData virtualModifierData; Object object_eval; crazyspace_init_object_for_eval(depsgraph, object, &object_eval); - ModifierData *md = modifiers_getVirtualModifierList(&object_eval, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); const ModifierEvalContext mectx = {depsgraph, &object_eval, 0}; for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } if (crazyspace_modifier_supports_deform(md)) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); /* skip leading modifiers which have been already * handled in sculpt_get_first_deform_matrices */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b4a8625c0bb..72197869f58 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -52,6 +52,7 @@ #include "BKE_idtype.h" #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_object.h" @@ -117,6 +118,22 @@ static void curve_free_data(ID *id) MEM_SAFE_FREE(curve->tb); } +static void curve_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Curve *curve = (Curve *)id; + BKE_LIB_FOREACHID_PROCESS(data, curve->bevobj, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, curve->taperobj, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, curve->textoncurve, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, curve->key, IDWALK_CB_USER); + for (int i = 0; i < curve->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, curve->mat[i], IDWALK_CB_USER); + } + BKE_LIB_FOREACHID_PROCESS(data, curve->vfont, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, curve->vfontb, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, curve->vfonti, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, curve->vfontbi, IDWALK_CB_USER); +} + IDTypeInfo IDType_ID_CU = { .id_code = ID_CU, .id_filter = FILTER_ID_CU, @@ -131,6 +148,7 @@ IDTypeInfo IDType_ID_CU = { .copy_data = curve_copy_data, .free_data = curve_free_data, .make_local = NULL, + .foreach_id = curve_foreach_id, }; static int cu_isectLL(const float v1[3], @@ -5506,6 +5524,20 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int #undef MAT_NR_REMAP } +void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth) +{ + if (use_smooth) { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + nu->flag |= CU_SMOOTH; + } + } + else { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + nu->flag &= ~CU_SMOOTH; + } + } +} + void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index eb5a90a7c4a..8c47401cbc3 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 5cb536f98b9..d73f92b6073 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -805,7 +805,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, const bool editmode) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *pretessellatePoint; int required_mode; @@ -822,9 +822,9 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, pretessellatePoint = NULL; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } if (mti->type == eModifierTypeType_Constructive) { @@ -853,31 +853,31 @@ static bool curve_calc_modifiers_pre( Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb, const bool for_render) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *pretessellatePoint; Curve *cu = ob->data; int numElems = 0, numVerts = 0; const bool editmode = (!for_render && (cu->editnurb || cu->editfont)); - ModifierApplyFlag app_flag = 0; + ModifierApplyFlag apply_flag = 0; float(*deformedVerts)[3] = NULL; float *keyVerts = NULL; int required_mode; bool modified = false; - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); if (editmode) { - app_flag |= MOD_APPLY_USECACHE; + apply_flag |= MOD_APPLY_USECACHE; } if (for_render) { - app_flag |= MOD_APPLY_RENDER; + apply_flag |= MOD_APPLY_RENDER; required_mode = eModifierMode_Render; } else { required_mode = eModifierMode_Realtime; } - const ModifierEvalContext mectx = {depsgraph, ob, app_flag}; + const ModifierEvalContext mectx = {depsgraph, ob, apply_flag}; pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode); @@ -901,9 +901,9 @@ static bool curve_calc_modifiers_pre( if (pretessellatePoint) { for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } if (mti->type != eModifierTypeType_OnlyDeform) { @@ -982,7 +982,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, const bool force_mesh_conversion) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *pretessellatePoint; Curve *cu = ob->data; int required_mode = 0, totvert = 0; @@ -990,10 +990,10 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, Mesh *modified = NULL, *mesh_applied; float(*vertCos)[3] = NULL; int useCache = !for_render; - ModifierApplyFlag app_flag = 0; + ModifierApplyFlag apply_flag = 0; if (for_render) { - app_flag |= MOD_APPLY_RENDER; + apply_flag |= MOD_APPLY_RENDER; required_mode = eModifierMode_Render; } else { @@ -1001,9 +1001,9 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, } const ModifierEvalContext mectx_deform = { - depsgraph, ob, editmode ? app_flag | MOD_APPLY_USECACHE : app_flag}; + depsgraph, ob, editmode ? apply_flag | MOD_APPLY_USECACHE : apply_flag}; const ModifierEvalContext mectx_apply = { - depsgraph, ob, useCache ? app_flag | MOD_APPLY_USECACHE : app_flag}; + depsgraph, ob, useCache ? apply_flag | MOD_APPLY_USECACHE : apply_flag}; pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode); @@ -1020,9 +1020,9 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, } for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } @@ -1100,7 +1100,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, if (need_normal) { BKE_mesh_ensure_normals(modified); } - mesh_applied = mti->applyModifier(md, &mectx_apply, modified); + mesh_applied = mti->modifyMesh(md, &mectx_apply, modified); if (mesh_applied) { /* Modifier returned a new derived mesh */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index a704e199007..79d9a40f06b 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -540,7 +540,7 @@ static int surface_getBrushFlags(DynamicPaintSurface *surface, Depsgraph *depsgr for (int i = 0; i < numobjects; i++) { Object *brushObj = objects[i]; - ModifierData *md = modifiers_findByType(brushObj, eModifierType_DynamicPaint); + ModifierData *md = BKE_modifiers_findby_type(brushObj, eModifierType_DynamicPaint); if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) { DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md; @@ -653,15 +653,15 @@ static void grid_bound_insert_cb_ex(void *__restrict userdata, boundInsert(grid_bound, bData->realCoord[bData->s_pos[i]].v); } -static void grid_bound_insert_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void grid_bound_insert_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - PaintBakeData *bData = userdata; - VolumeGrid *grid = bData->grid; - - Bounds3D *grid_bound = userdata_chunk; + Bounds3D *join = chunk_join; + Bounds3D *grid_bound = chunk; - boundInsert(&grid->grid_bounds, grid_bound->min); - boundInsert(&grid->grid_bounds, grid_bound->max); + boundInsert(join, grid_bound->min); + boundInsert(join, grid_bound->max); } static void grid_cell_points_cb_ex(void *__restrict userdata, @@ -685,17 +685,20 @@ static void grid_cell_points_cb_ex(void *__restrict userdata, s_num[temp_t_index[i]]++; } -static void grid_cell_points_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void grid_cell_points_reduce(const void *__restrict userdata, + void *__restrict chunk_join, + void *__restrict chunk) { - PaintBakeData *bData = userdata; - VolumeGrid *grid = bData->grid; + const PaintBakeData *bData = userdata; + const VolumeGrid *grid = bData->grid; const int grid_cells = grid->dim[0] * grid->dim[1] * grid->dim[2]; - int *s_num = userdata_chunk; + int *join_s_num = chunk_join; + int *s_num = chunk; /* calculate grid indexes */ for (int i = 0; i < grid_cells; i++) { - grid->s_num[i] += s_num[i]; + join_s_num[i] += s_num[i]; } } @@ -753,7 +756,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = &grid->grid_bounds; settings.userdata_chunk_size = sizeof(grid->grid_bounds); - settings.func_finalize = grid_bound_insert_finalize; + settings.func_reduce = grid_bound_insert_reduce; BLI_task_parallel_range(0, sData->total_points, bData, grid_bound_insert_cb_ex, &settings); } /* get dimensions */ @@ -814,7 +817,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = grid->s_num; settings.userdata_chunk_size = sizeof(*grid->s_num) * grid_cells; - settings.func_finalize = grid_cell_points_finalize; + settings.func_reduce = grid_cell_points_reduce; BLI_task_parallel_range(0, sData->total_points, bData, grid_cell_points_cb_ex, &settings); } @@ -1096,7 +1099,7 @@ DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *c surface->wave_spring = 0.20f; surface->wave_smoothness = 1.0f; - modifier_path_init( + BKE_modifier_path_init( surface->image_output_path, sizeof(surface->image_output_path), "cache_dynamicpaint"); /* Using ID_BRUSH i18n context, as we have no physics/dpaint one for now... */ @@ -4882,7 +4885,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 _finalize 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++) { @@ -6245,7 +6248,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph, Object *brushObj = objects[i]; /* check if target has an active dp modifier */ - ModifierData *md = modifiers_findByType(brushObj, eModifierType_DynamicPaint); + ModifierData *md = BKE_modifiers_findby_type(brushObj, eModifierType_DynamicPaint); if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) { DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md; /* make sure we're dealing with a brush */ diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c index c3ae2a54e13..6fcaf84d4ca 100644 --- a/source/blender/blenkernel/intern/editmesh_tangent.c +++ b/source/blender/blenkernel/intern/editmesh_tangent.c @@ -251,9 +251,7 @@ finally: pRes[3] = fSign; } -static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata) { struct SGLSLEditMeshToTangent *mesh2tangent = taskdata; /* new computation method */ @@ -362,9 +360,8 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, #endif /* Calculation */ if (em->tottri != 0) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; - task_pool = BLI_task_pool_create(scheduler, NULL, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(NULL, TASK_PRIORITY_LOW); tangent_mask_curr = 0; /* Calculate tangent layers */ diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e1e818a5a34..bfb03dea39c 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -177,7 +177,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef } } else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) { - eff->surmd = (SurfaceModifierData *)modifiers_findByType(eff->ob, eModifierType_Surface); + eff->surmd = (SurfaceModifierData *)BKE_modifiers_findby_type(eff->ob, eModifierType_Surface); if (eff->ob->type == OB_CURVE) { eff->flag |= PE_USE_NORMAL_DATA; } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 439992a4113..543d5c8b7c7 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -30,49 +30,28 @@ #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" -#include "DNA_constraint_types.h" #include "DNA_object_types.h" -#include "BLI_alloca.h" #include "BLI_blenlib.h" #include "BLI_easing.h" -#include "BLI_expr_pylike_eval.h" #include "BLI_math.h" -#include "BLI_string_utils.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" -#include "BLT_translation.h" - -#include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_animsys.h" -#include "BKE_armature.h" -#include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_nla.h" -#include "BKE_object.h" #include "RNA_access.h" -#include "atomic_ops.h" - #include "CLG_log.h" -#ifdef WITH_PYTHON -# include "BPY_extern.h" -#endif - #define SMALL -1.0e-10 #define SELECT 1 -#ifdef WITH_PYTHON -static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER; -#endif - static CLG_LogRef LOG = {"bke.fcurve"}; /* ************************** Data-Level Functions ************************* */ @@ -1256,1236 +1235,6 @@ short test_time_fcurve(FCurve *fcu) return 0; } -/* ***************************** Drivers ********************************* */ - -/* Driver Variables --------------------------- */ - -/* TypeInfo for Driver Variables (dvti) */ -typedef struct DriverVarTypeInfo { - /* evaluation callback */ - float (*get_value)(ChannelDriver *driver, DriverVar *dvar); - - /* allocation of target slots */ - int num_targets; /* number of target slots required */ - const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ - short target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */ -} DriverVarTypeInfo; - -/* Macro to begin definitions */ -#define BEGIN_DVAR_TYPEDEF(type) { - -/* Macro to end definitions */ -#define END_DVAR_TYPEDEF } - -/* ......... */ - -static ID *dtar_id_ensure_proxy_from(ID *id) -{ - if (id && GS(id->name) == ID_OB && ((Object *)id)->proxy_from) { - return (ID *)(((Object *)id)->proxy_from); - } - return id; -} - -/** - * Helper function to obtain a value using RNA from the specified source - * (for evaluating drivers). - */ -static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) -{ - PointerRNA id_ptr, ptr; - PropertyRNA *prop; - ID *id; - int index = -1; - float value = 0.0f; - - /* sanity check */ - if (ELEM(NULL, driver, dtar)) { - return 0.0f; - } - - id = dtar_id_ensure_proxy_from(dtar->id); - - /* error check for missing pointer... */ - if (id == NULL) { - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - - /* get RNA-pointer for the ID-block given in target */ - RNA_id_pointer_create(id, &id_ptr); - - /* get property to read from, and get value as appropriate */ - if (!RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { - /* path couldn't be resolved */ - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, - "Driver Evaluation Error: cannot resolve target for %s -> %s", - id->name, - dtar->rna_path); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - - if (RNA_property_array_check(prop)) { - /* array */ - if (index < 0 || index >= RNA_property_array_length(&ptr, prop)) { - /* out of bounds */ - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, - "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)", - id->name, - dtar->rna_path, - index); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get_index(&ptr, prop, index); - break; - case PROP_INT: - value = (float)RNA_property_int_get_index(&ptr, prop, index); - break; - case PROP_FLOAT: - value = RNA_property_float_get_index(&ptr, prop, index); - break; - default: - break; - } - } - else { - /* not an array */ - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get(&ptr, prop); - break; - case PROP_INT: - value = (float)RNA_property_int_get(&ptr, prop); - break; - case PROP_FLOAT: - value = RNA_property_float_get(&ptr, prop); - break; - case PROP_ENUM: - value = (float)RNA_property_enum_get(&ptr, prop); - break; - default: - break; - } - } - - /* if we're still here, we should be ok... */ - dtar->flag &= ~DTAR_FLAG_INVALID; - return value; -} - -/** - * Same as 'dtar_get_prop_val'. but get the RNA property. - */ -bool driver_get_variable_property(ChannelDriver *driver, - DriverTarget *dtar, - PointerRNA *r_ptr, - PropertyRNA **r_prop, - int *r_index) -{ - PointerRNA id_ptr; - PointerRNA ptr; - PropertyRNA *prop; - ID *id; - int index = -1; - - /* sanity check */ - if (ELEM(NULL, driver, dtar)) { - return false; - } - - id = dtar_id_ensure_proxy_from(dtar->id); - - /* error check for missing pointer... */ - if (id == NULL) { - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return false; - } - - /* get RNA-pointer for the ID-block given in target */ - RNA_id_pointer_create(id, &id_ptr); - - /* get property to read from, and get value as appropriate */ - if (dtar->rna_path == NULL || dtar->rna_path[0] == '\0') { - ptr = PointerRNA_NULL; - prop = NULL; /* ok */ - } - else if (RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { - /* ok */ - } - else { - /* path couldn't be resolved */ - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, - "Driver Evaluation Error: cannot resolve target for %s -> %s", - id->name, - dtar->rna_path); - } - - ptr = PointerRNA_NULL; - *r_prop = NULL; - *r_index = -1; - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return false; - } - - *r_ptr = ptr; - *r_prop = prop; - *r_index = index; - - /* if we're still here, we should be ok... */ - dtar->flag &= ~DTAR_FLAG_INVALID; - return true; -} - -static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar) -{ - short valid_targets = 0; - - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - - /* check if this target has valid data */ - if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { - /* invalid target, so will not have enough targets */ - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - } - else { - /* target seems to be OK now... */ - dtar->flag &= ~DTAR_FLAG_INVALID; - valid_targets++; - } - } - DRIVER_TARGETS_LOOPER_END; - - return valid_targets; -} - -/* ......... */ - -/* evaluate 'single prop' driver variable */ -static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar) -{ - /* just evaluate the first target slot */ - return dtar_get_prop_val(driver, &dvar->targets[0]); -} - -/* evaluate 'rotation difference' driver variable */ -static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) -{ - short valid_targets = driver_check_valid_targets(driver, dvar); - - /* make sure we have enough valid targets to use - all or nothing for now... */ - if (driver_check_valid_targets(driver, dvar) != 2) { - if (G.debug & G_DEBUG) { - CLOG_WARN(&LOG, - "RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", - valid_targets, - dvar->targets[0].id, - dvar->targets[1].id); - } - return 0.0f; - } - - float(*mat[2])[4]; - - /* NOTE: for now, these are all just worldspace */ - for (int i = 0; i < 2; i++) { - /* get pointer to loc values to store in */ - DriverTarget *dtar = &dvar->targets[i]; - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - bPoseChannel *pchan; - - /* after the checks above, the targets should be valid here... */ - BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); - - /* try to get posechannel */ - pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - - /* check if object or bone */ - if (pchan) { - /* bone */ - mat[i] = pchan->pose_mat; - } - else { - /* object */ - mat[i] = ob->obmat; - } - } - - float q1[4], q2[4], quat[4], angle; - - /* use the final posed locations */ - mat4_to_quat(q1, mat[0]); - mat4_to_quat(q2, mat[1]); - - invert_qt_normalized(q1); - mul_qt_qtqt(quat, q1, q2); - angle = 2.0f * (saacos(quat[0])); - angle = fabsf(angle); - - return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle); -} - -/* evaluate 'location difference' driver variable */ -/* TODO: this needs to take into account space conversions... */ -static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) -{ - float loc1[3] = {0.0f, 0.0f, 0.0f}; - float loc2[3] = {0.0f, 0.0f, 0.0f}; - short valid_targets = driver_check_valid_targets(driver, dvar); - - /* make sure we have enough valid targets to use - all or nothing for now... */ - if (valid_targets < dvar->num_targets) { - if (G.debug & G_DEBUG) { - CLOG_WARN(&LOG, - "LocDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", - valid_targets, - dvar->targets[0].id, - dvar->targets[1].id); - } - return 0.0f; - } - - /* SECOND PASS: get two location values */ - /* NOTE: for now, these are all just worldspace */ - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - /* get pointer to loc values to store in */ - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - bPoseChannel *pchan; - float tmp_loc[3]; - - /* after the checks above, the targets should be valid here... */ - BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); - - /* try to get posechannel */ - pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - - /* check if object or bone */ - if (pchan) { - /* bone */ - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - float mat[4][4]; - - /* extract transform just like how the constraints do it! */ - copy_m4_m4(mat, pchan->pose_mat); - BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); - - /* ... and from that, we get our transform */ - copy_v3_v3(tmp_loc, mat[3]); - } - else { - /* transform space (use transform values directly) */ - copy_v3_v3(tmp_loc, pchan->loc); - } - } - else { - /* convert to worldspace */ - copy_v3_v3(tmp_loc, pchan->pose_head); - mul_m4_v3(ob->obmat, tmp_loc); - } - } - else { - /* object */ - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* XXX: this should practically be the same as transform space... */ - float mat[4][4]; - - /* extract transform just like how the constraints do it! */ - copy_m4_m4(mat, ob->obmat); - BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); - - /* ... and from that, we get our transform */ - copy_v3_v3(tmp_loc, mat[3]); - } - else { - /* transform space (use transform values directly) */ - copy_v3_v3(tmp_loc, ob->loc); - } - } - else { - /* worldspace */ - copy_v3_v3(tmp_loc, ob->obmat[3]); - } - } - - /* copy the location to the right place */ - if (tarIndex) { - copy_v3_v3(loc2, tmp_loc); - } - else { - copy_v3_v3(loc1, tmp_loc); - } - } - DRIVER_TARGETS_LOOPER_END; - - /* if we're still here, there should now be two targets to use, - * so just take the length of the vector between these points - */ - return len_v3v3(loc1, loc2); -} - -/* evaluate 'transform channel' driver variable */ -static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) -{ - DriverTarget *dtar = &dvar->targets[0]; - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - bPoseChannel *pchan; - float mat[4][4]; - float oldEul[3] = {0.0f, 0.0f, 0.0f}; - bool use_eulers = false; - short rot_order = ROT_MODE_EUL; - - /* check if this target has valid data */ - if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { - /* invalid target, so will not have enough targets */ - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - else { - /* target should be valid now */ - dtar->flag &= ~DTAR_FLAG_INVALID; - } - - /* try to get posechannel */ - pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - - /* check if object or bone, and get transform matrix accordingly - * - "useEulers" code is used to prevent the problems associated with non-uniqueness - * of euler decomposition from matrices [#20870] - * - localspace is for [#21384], where parent results are not wanted - * but local-consts is for all the common "corrective-shapes-for-limbs" situations - */ - if (pchan) { - /* bone */ - if (pchan->rotmode > 0) { - copy_v3_v3(oldEul, pchan->eul); - rot_order = pchan->rotmode; - use_eulers = true; - } - - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* just like how the constraints do it! */ - copy_m4_m4(mat, pchan->pose_mat); - BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); - } - else { - /* specially calculate local matrix, since chan_mat is not valid - * since it stores delta transform of pose_mat so that deforms work - * so it cannot be used here for "transform" space - */ - BKE_pchan_to_mat4(pchan, mat); - } - } - else { - /* worldspace matrix */ - mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); - } - } - else { - /* object */ - if (ob->rotmode > 0) { - copy_v3_v3(oldEul, ob->rot); - rot_order = ob->rotmode; - use_eulers = true; - } - - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* just like how the constraints do it! */ - copy_m4_m4(mat, ob->obmat); - BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); - } - else { - /* transforms to matrix */ - BKE_object_to_mat4(ob, mat); - } - } - else { - /* worldspace matrix - just the good-old one */ - copy_m4_m4(mat, ob->obmat); - } - } - - /* check which transform */ - if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) { - /* not valid channel */ - return 0.0f; - } - else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) { - /* Cubic root of the change in volume, equal to the geometric mean - * of scale over all three axes unless the matrix includes shear. */ - return cbrtf(mat4_to_volume_scale(mat)); - } - else if (ELEM(dtar->transChan, - DTAR_TRANSCHAN_SCALEX, - DTAR_TRANSCHAN_SCALEY, - DTAR_TRANSCHAN_SCALEZ)) { - /* Extract scale, and choose the right axis, - * inline 'mat4_to_size'. */ - return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]); - } - else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) { - /* extract rotation as eulers (if needed) - * - definitely if rotation order isn't eulers already - * - if eulers, then we have 2 options: - * a) decompose transform matrix as required, then try to make eulers from - * there compatible with original values - * b) [NOT USED] directly use the original values (no decomposition) - * - only an option for "transform space", if quality is really bad with a) - */ - float quat[4]; - int channel; - - if (dtar->transChan == DTAR_TRANSCHAN_ROTW) { - channel = 0; - } - else { - channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX; - BLI_assert(channel < 4); - } - - BKE_driver_target_matrix_to_rot_channels( - mat, rot_order, dtar->rotation_mode, channel, false, quat); - - if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) { - compatible_eul(quat + 1, oldEul); - } - - return quat[channel]; - } - else { - /* extract location and choose right axis */ - return mat[3][dtar->transChan]; - } -} - -/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */ -static void quaternion_to_angles(float quat[4], int channel) -{ - if (channel < 0) { - quat[0] = 2.0f * saacosf(quat[0]); - - for (int i = 1; i < 4; i++) { - quat[i] = 2.0f * saasinf(quat[i]); - } - } - else if (channel == 0) { - quat[0] = 2.0f * saacosf(quat[0]); - } - else { - quat[channel] = 2.0f * saasinf(quat[channel]); - } -} - -/* Compute channel values for a rotational Transform Channel driver variable. */ -void BKE_driver_target_matrix_to_rot_channels( - float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]) -{ - float *const quat = r_buf; - float *const eul = r_buf + 1; - - zero_v4(r_buf); - - if (rotation_mode == DTAR_ROTMODE_AUTO) { - mat4_to_eulO(eul, auto_order, mat); - } - else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) { - mat4_to_eulO(eul, rotation_mode, mat); - } - else if (rotation_mode == DTAR_ROTMODE_QUATERNION) { - mat4_to_quat(quat, mat); - - /* For Transformation constraint convenience, convert to pseudo-angles. */ - if (angles) { - quaternion_to_angles(quat, channel); - } - } - else if (rotation_mode >= DTAR_ROTMODE_SWING_TWIST_X && - rotation_mode <= DTAR_ROTMODE_SWING_TWIST_Z) { - int axis = rotation_mode - DTAR_ROTMODE_SWING_TWIST_X; - float raw_quat[4], twist; - - mat4_to_quat(raw_quat, mat); - - if (channel == axis + 1) { - /* If only the twist angle is needed, skip computing swing. */ - twist = quat_split_swing_and_twist(raw_quat, axis, NULL, NULL); - } - else { - twist = quat_split_swing_and_twist(raw_quat, axis, quat, NULL); - - quaternion_to_angles(quat, channel); - } - - quat[axis + 1] = twist; - } - else { - BLI_assert(false); - } -} - -/* ......... */ - -/* Table of Driver Variable Type Info Data */ -static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) dvar_eval_singleProp, /* eval callback */ - 1, /* number of targets used */ - {"Property"}, /* UI names for targets */ - {0} /* flags */ - END_DVAR_TYPEDEF, - - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF) dvar_eval_rotDiff, /* eval callback */ - 2, /* number of targets used */ - {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ - {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, - DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ - END_DVAR_TYPEDEF, - - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF) dvar_eval_locDiff, /* eval callback */ - 2, /* number of targets used */ - {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ - {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, - DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ - END_DVAR_TYPEDEF, - - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN) dvar_eval_transChan, /* eval callback */ - 1, /* number of targets used */ - {"Object/Bone"}, /* UI names for targets */ - {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ - END_DVAR_TYPEDEF, -}; - -/* Get driver variable typeinfo */ -static const DriverVarTypeInfo *get_dvar_typeinfo(int type) -{ - /* check if valid type */ - if ((type >= 0) && (type < MAX_DVAR_TYPES)) { - return &dvar_types[type]; - } - else { - return NULL; - } -} - -/* Driver API --------------------------------- */ - -/* Perform actual freeing driver variable and remove it from the given list */ -void driver_free_variable(ListBase *variables, DriverVar *dvar) -{ - /* sanity checks */ - if (dvar == NULL) { - return; - } - - /* free target vars - * - need to go over all of them, not just up to the ones that are used - * currently, since there may be some lingering RNA paths from - * previous users needing freeing - */ - DRIVER_TARGETS_LOOPER_BEGIN (dvar) { - /* free RNA path if applicable */ - if (dtar->rna_path) { - MEM_freeN(dtar->rna_path); - } - } - DRIVER_TARGETS_LOOPER_END; - - /* remove the variable from the driver */ - BLI_freelinkN(variables, dvar); -} - -/* Free the driver variable and do extra updates */ -void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar) -{ - /* remove and free the driver variable */ - driver_free_variable(&driver->variables, dvar); - - /* since driver variables are cached, the expression needs re-compiling too */ - BKE_driver_invalidate_expression(driver, false, true); -} - -/* Copy driver variables from src_vars list to dst_vars list */ -void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars) -{ - BLI_assert(BLI_listbase_is_empty(dst_vars)); - BLI_duplicatelist(dst_vars, src_vars); - - LISTBASE_FOREACH (DriverVar *, dvar, dst_vars) { - /* need to go over all targets so that we don't leave any dangling paths */ - DRIVER_TARGETS_LOOPER_BEGIN (dvar) { - /* make a copy of target's rna path if available */ - if (dtar->rna_path) { - dtar->rna_path = MEM_dupallocN(dtar->rna_path); - } - } - DRIVER_TARGETS_LOOPER_END; - } -} - -/* Change the type of driver variable */ -void driver_change_variable_type(DriverVar *dvar, int type) -{ - const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type); - - /* sanity check */ - if (ELEM(NULL, dvar, dvti)) { - return; - } - - /* set the new settings */ - dvar->type = type; - dvar->num_targets = dvti->num_targets; - - /* make changes to the targets based on the defines for these types - * NOTE: only need to make sure the ones we're using here are valid... - */ - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - short flags = dvti->target_flags[tarIndex]; - - /* store the flags */ - dtar->flag = flags; - - /* object ID types only, or idtype not yet initialized */ - if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0)) { - dtar->idtype = ID_OB; - } - } - DRIVER_TARGETS_LOOPER_END; -} - -/* Validate driver name (after being renamed) */ -void driver_variable_name_validate(DriverVar *dvar) -{ - /* Special character blacklist */ - const char special_char_blacklist[] = { - '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '+', '=', '-', '/', '\\', - '?', ':', ';', '<', '>', '{', '}', '[', ']', '|', ' ', '.', '\t', '\n', '\r', - }; - - /* sanity checks */ - if (dvar == NULL) { - return; - } - - /* clear all invalid-name flags */ - dvar->flag &= ~DVAR_ALL_INVALID_FLAGS; - - /* 0) Zero-length identifiers are not allowed */ - if (dvar->name[0] == '\0') { - dvar->flag |= DVAR_FLAG_INVALID_EMPTY; - } - - /* 1) Must start with a letter */ - /* XXX: We assume that valid unicode letters in other languages are ok too, - * hence the blacklisting. */ - if (IN_RANGE_INCL(dvar->name[0], '0', '9')) { - dvar->flag |= DVAR_FLAG_INVALID_START_NUM; - } - else if (dvar->name[0] == '_') { - /* NOTE: We don't allow names to start with underscores - * (i.e. it helps when ruling out security risks) */ - dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; - } - - /* 2) Must not contain invalid stuff in the middle of the string */ - if (strchr(dvar->name, ' ')) { - dvar->flag |= DVAR_FLAG_INVALID_HAS_SPACE; - } - if (strchr(dvar->name, '.')) { - dvar->flag |= DVAR_FLAG_INVALID_HAS_DOT; - } - - /* 3) Check for special characters - Either at start, or in the middle */ - for (int i = 0; i < sizeof(special_char_blacklist); i++) { - char *match = strchr(dvar->name, special_char_blacklist[i]); - - if (match == dvar->name) { - dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; - } - else if (match != NULL) { - dvar->flag |= DVAR_FLAG_INVALID_HAS_SPECIAL; - } - } - - /* 4) Check if the name is a reserved keyword - * NOTE: These won't confuse Python, but it will be impossible to use the variable - * in an expression without Python misinterpreting what these are for - */ -#ifdef WITH_PYTHON - if (BPY_string_is_keyword(dvar->name)) { - dvar->flag |= DVAR_FLAG_INVALID_PY_KEYWORD; - } -#endif - - /* If any these conditions match, the name is invalid */ - if (dvar->flag & DVAR_ALL_INVALID_FLAGS) { - dvar->flag |= DVAR_FLAG_INVALID_NAME; - } -} - -/* Add a new driver variable */ -DriverVar *driver_add_new_variable(ChannelDriver *driver) -{ - DriverVar *dvar; - - /* sanity checks */ - if (driver == NULL) { - return NULL; - } - - /* make a new variable */ - dvar = MEM_callocN(sizeof(DriverVar), "DriverVar"); - BLI_addtail(&driver->variables, dvar); - - /* give the variable a 'unique' name */ - strcpy(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var")); - BLI_uniquename(&driver->variables, - dvar, - CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"), - '_', - offsetof(DriverVar, name), - sizeof(dvar->name)); - - /* set the default type to 'single prop' */ - driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP); - - /* since driver variables are cached, the expression needs re-compiling too */ - BKE_driver_invalidate_expression(driver, false, true); - - /* return the target */ - return dvar; -} - -/* This frees the driver itself */ -void fcurve_free_driver(FCurve *fcu) -{ - ChannelDriver *driver; - DriverVar *dvar, *dvarn; - - /* sanity checks */ - if (ELEM(NULL, fcu, fcu->driver)) { - return; - } - driver = fcu->driver; - - /* free driver targets */ - for (dvar = driver->variables.first; dvar; dvar = dvarn) { - dvarn = dvar->next; - driver_free_variable_ex(driver, dvar); - } - -#ifdef WITH_PYTHON - /* free compiled driver expression */ - if (driver->expr_comp) { - BPY_DECREF(driver->expr_comp); - } -#endif - - BLI_expr_pylike_free(driver->expr_simple); - - /* Free driver itself, then set F-Curve's point to this to NULL - * (as the curve may still be used). */ - MEM_freeN(driver); - fcu->driver = NULL; -} - -/* This makes a copy of the given driver */ -ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver) -{ - ChannelDriver *ndriver; - - /* sanity checks */ - if (driver == NULL) { - return NULL; - } - - /* copy all data */ - ndriver = MEM_dupallocN(driver); - ndriver->expr_comp = NULL; - ndriver->expr_simple = NULL; - - /* copy variables */ - - /* to get rid of refs to non-copied data (that's still used on original) */ - BLI_listbase_clear(&ndriver->variables); - driver_variables_copy(&ndriver->variables, &driver->variables); - - /* return the new driver */ - return ndriver; -} - -/* Driver Expression Evaluation --------------- */ - -/* Index constants for the expression parameter array. */ -enum { - /* Index of the 'frame' variable. */ - VAR_INDEX_FRAME = 0, - /* Index of the first user-defined driver variable. */ - VAR_INDEX_CUSTOM -}; - -static ExprPyLike_Parsed *driver_compile_simple_expr_impl(ChannelDriver *driver) -{ - /* Prepare parameter names. */ - int names_len = BLI_listbase_count(&driver->variables); - const char **names = BLI_array_alloca(names, names_len + VAR_INDEX_CUSTOM); - int i = VAR_INDEX_CUSTOM; - - names[VAR_INDEX_FRAME] = "frame"; - - LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { - names[i++] = dvar->name; - } - - return BLI_expr_pylike_parse(driver->expression, names, names_len + VAR_INDEX_CUSTOM); -} - -static bool driver_check_simple_expr_depends_on_time(ExprPyLike_Parsed *expr) -{ - /* Check if the 'frame' parameter is actually used. */ - return BLI_expr_pylike_is_using_param(expr, VAR_INDEX_FRAME); -} - -static bool driver_evaluate_simple_expr(ChannelDriver *driver, - ExprPyLike_Parsed *expr, - float *result, - float time) -{ - /* Prepare parameter values. */ - int vars_len = BLI_listbase_count(&driver->variables); - double *vars = BLI_array_alloca(vars, vars_len + VAR_INDEX_CUSTOM); - int i = VAR_INDEX_CUSTOM; - - vars[VAR_INDEX_FRAME] = time; - - LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { - vars[i++] = driver_get_variable_value(driver, dvar); - } - - /* Evaluate expression. */ - double result_val; - eExprPyLike_EvalStatus status = BLI_expr_pylike_eval( - expr, vars, vars_len + VAR_INDEX_CUSTOM, &result_val); - const char *message; - - switch (status) { - case EXPR_PYLIKE_SUCCESS: - if (isfinite(result_val)) { - *result = (float)result_val; - } - return true; - - case EXPR_PYLIKE_DIV_BY_ZERO: - case EXPR_PYLIKE_MATH_ERROR: - message = (status == EXPR_PYLIKE_DIV_BY_ZERO) ? "Division by Zero" : "Math Domain Error"; - CLOG_ERROR(&LOG, "%s in Driver: '%s'", message, driver->expression); - - driver->flag |= DRIVER_FLAG_INVALID; - return true; - - default: - /* arriving here means a bug, not user error */ - CLOG_ERROR(&LOG, "simple driver expression evaluation failed: '%s'", driver->expression); - return false; - } -} - -/* Compile and cache the driver expression if necessary, with thread safety. */ -static bool driver_compile_simple_expr(ChannelDriver *driver) -{ - if (driver->expr_simple != NULL) { - return true; - } - - if (driver->type != DRIVER_TYPE_PYTHON) { - return false; - } - - /* It's safe to parse in multiple threads; at worst it'll - * waste some effort, but in return avoids mutex contention. */ - ExprPyLike_Parsed *expr = driver_compile_simple_expr_impl(driver); - - /* Store the result if the field is still NULL, or discard - * it if another thread got here first. */ - if (atomic_cas_ptr((void **)&driver->expr_simple, NULL, expr) != NULL) { - BLI_expr_pylike_free(expr); - } - - return true; -} - -/* Try using the simple expression evaluator to compute the result of the driver. - * On success, stores the result and returns true; on failure result is set to 0. */ -static bool driver_try_evaluate_simple_expr(ChannelDriver *driver, - ChannelDriver *driver_orig, - float *result, - float time) -{ - *result = 0.0f; - - return driver_compile_simple_expr(driver_orig) && - BLI_expr_pylike_is_valid(driver_orig->expr_simple) && - driver_evaluate_simple_expr(driver, driver_orig->expr_simple, result, time); -} - -/* Check if the expression in the driver conforms to the simple subset. */ -bool BKE_driver_has_simple_expression(ChannelDriver *driver) -{ - return driver_compile_simple_expr(driver) && BLI_expr_pylike_is_valid(driver->expr_simple); -} - -/* TODO(sergey): This is somewhat weak, but we don't want neither false-positive - * time dependencies nor special exceptions in the depsgraph evaluation. */ -static bool python_driver_exression_depends_on_time(const char *expression) -{ - if (expression[0] == '\0') { - /* Empty expression depends on nothing. */ - return false; - } - if (strchr(expression, '(') != NULL) { - /* Function calls are considered dependent on a time. */ - return true; - } - if (strstr(expression, "frame") != NULL) { - /* Variable `frame` depends on time. */ - /* TODO(sergey): This is a bit weak, but not sure about better way of handling this. */ - return true; - } - /* Possible indirect time relation s should be handled via variable targets. */ - return false; -} - -/* Check if the expression in the driver may depend on the current frame. */ -bool BKE_driver_expression_depends_on_time(ChannelDriver *driver) -{ - if (driver->type != DRIVER_TYPE_PYTHON) { - return false; - } - - if (BKE_driver_has_simple_expression(driver)) { - /* Simple expressions can be checked exactly. */ - return driver_check_simple_expr_depends_on_time(driver->expr_simple); - } - else { - /* Otherwise, heuristically scan the expression string for certain patterns. */ - return python_driver_exression_depends_on_time(driver->expression); - } -} - -/* Reset cached compiled expression data */ -void BKE_driver_invalidate_expression(ChannelDriver *driver, - bool expr_changed, - bool varname_changed) -{ - if (expr_changed || varname_changed) { - BLI_expr_pylike_free(driver->expr_simple); - driver->expr_simple = NULL; - } - -#ifdef WITH_PYTHON - if (expr_changed) { - driver->flag |= DRIVER_FLAG_RECOMPILE; - } - - if (varname_changed) { - driver->flag |= DRIVER_FLAG_RENAMEVAR; - } -#endif -} - -/* Driver Evaluation -------------------------- */ - -/* Evaluate a Driver Variable to get a value that contributes to the final */ -float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar) -{ - const DriverVarTypeInfo *dvti; - - /* sanity check */ - if (ELEM(NULL, driver, dvar)) { - return 0.0f; - } - - /* call the relevant callbacks to get the variable value - * using the variable type info, storing the obtained value - * in dvar->curval so that drivers can be debugged - */ - dvti = get_dvar_typeinfo(dvar->type); - - if (dvti && dvti->get_value) { - dvar->curval = dvti->get_value(driver, dvar); - } - else { - dvar->curval = 0.0f; - } - - return dvar->curval; -} - -static void evaluate_driver_sum(ChannelDriver *driver) -{ - DriverVar *dvar; - - /* check how many variables there are first (i.e. just one?) */ - if (BLI_listbase_is_single(&driver->variables)) { - /* just one target, so just use that */ - dvar = driver->variables.first; - driver->curval = driver_get_variable_value(driver, dvar); - return; - } - - /* more than one target, so average the values of the targets */ - float value = 0.0f; - int tot = 0; - - /* loop through targets, adding (hopefully we don't get any overflow!) */ - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - value += driver_get_variable_value(driver, dvar); - tot++; - } - - /* perform operations on the total if appropriate */ - if (driver->type == DRIVER_TYPE_AVERAGE) { - driver->curval = tot ? (value / (float)tot) : 0.0f; - } - else { - driver->curval = value; - } -} - -static void evaluate_driver_min_max(ChannelDriver *driver) -{ - DriverVar *dvar; - float value = 0.0f; - - /* loop through the variables, getting the values and comparing them to existing ones */ - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - /* get value */ - float tmp_val = driver_get_variable_value(driver, dvar); - - /* store this value if appropriate */ - if (dvar->prev) { - /* check if greater/smaller than the baseline */ - if (driver->type == DRIVER_TYPE_MAX) { - /* max? */ - if (tmp_val > value) { - value = tmp_val; - } - } - else { - /* min? */ - if (tmp_val < value) { - value = tmp_val; - } - } - } - else { - /* first item - make this the baseline for comparisons */ - value = tmp_val; - } - } - - /* store value in driver */ - driver->curval = value; -} - -static void evaluate_driver_python(PathResolvedRNA *anim_rna, - ChannelDriver *driver, - ChannelDriver *driver_orig, - const float evaltime) -{ - /* check for empty or invalid expression */ - if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) { - driver->curval = 0.0f; - } - else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) { -#ifdef WITH_PYTHON - /* this evaluates the expression using Python, and returns its result: - * - on errors it reports, then returns 0.0f - */ - BLI_mutex_lock(&python_driver_lock); - - driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime); - - BLI_mutex_unlock(&python_driver_lock); -#else /* WITH_PYTHON*/ - UNUSED_VARS(anim_rna, evaltime); -#endif /* WITH_PYTHON*/ - } -} - -/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" - * - "evaltime" is the frame at which F-Curve is being evaluated - * - has to return a float value - * - driver_orig is where we cache Python expressions, in case of COW - */ -float evaluate_driver(PathResolvedRNA *anim_rna, - ChannelDriver *driver, - ChannelDriver *driver_orig, - const float evaltime) -{ - /* check if driver can be evaluated */ - if (driver_orig->flag & DRIVER_FLAG_INVALID) { - return 0.0f; - } - - switch (driver->type) { - case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ - case DRIVER_TYPE_SUM: /* sum values of driver targets */ - evaluate_driver_sum(driver); - break; - case DRIVER_TYPE_MIN: /* smallest value */ - case DRIVER_TYPE_MAX: /* largest value */ - evaluate_driver_min_max(driver); - break; - case DRIVER_TYPE_PYTHON: /* expression */ - evaluate_driver_python(anim_rna, driver, driver_orig, evaltime); - break; - default: - /* special 'hack' - just use stored value - * This is currently used as the mechanism which allows animated settings to be able - * to be changed via the UI. - */ - break; - } - - /* return value for driver */ - return driver->curval; -} - /* ***************************** Curve Calculations ********************************* */ /* The total length of the handles is not allowed to be more @@ -2666,437 +1415,327 @@ static void berekeny(float f1, float f2, float f3, float f4, float *o, int b) /* -------------------------- */ -/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */ -static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) +static float fcurve_eval_keyframes_extrapolate( + FCurve *fcu, BezTriple *bezts, float evaltime, int endpoint_offset, int direction_to_neighbor) +{ + BezTriple *endpoint_bezt = bezts + endpoint_offset; /* The first/last keyframe. */ + BezTriple *neighbor_bezt = endpoint_bezt + + direction_to_neighbor; /* The second (to last) keyframe. */ + + if (endpoint_bezt->ipo == BEZT_IPO_CONST || fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT || + (fcu->flag & FCURVE_DISCRETE_VALUES) != 0) { + /* Constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, so just extend the + * endpoint's value. */ + return endpoint_bezt->vec[1][1]; + } + + if (endpoint_bezt->ipo == BEZT_IPO_LIN) { + /* Use the next center point instead of our own handle for linear interpolated extrapolate. */ + if (fcu->totvert == 1) { + return endpoint_bezt->vec[1][1]; + } + + float dx = endpoint_bezt->vec[1][0] - evaltime; + float fac = neighbor_bezt->vec[1][0] - endpoint_bezt->vec[1][0]; + + /* Prevent division by zero. */ + if (fac == 0.0f) { + return endpoint_bezt->vec[1][1]; + } + + fac = (neighbor_bezt->vec[1][1] - endpoint_bezt->vec[1][1]) / fac; + return endpoint_bezt->vec[1][1] - (fac * dx); + } + + /* Use the gradient of the second handle (later) of neighbour to calculate the gradient and thus + * the value of the curve at evaltime */ + int handle = direction_to_neighbor > 0 ? 0 : 2; + float dx = endpoint_bezt->vec[1][0] - evaltime; + float fac = endpoint_bezt->vec[1][0] - endpoint_bezt->vec[handle][0]; + + /* Prevent division by zero. */ + if (fac == 0.0f) { + return endpoint_bezt->vec[1][1]; + } + + fac = (endpoint_bezt->vec[1][1] - endpoint_bezt->vec[handle][1]) / fac; + return endpoint_bezt->vec[1][1] - (fac * dx); +} + +static float fcurve_eval_keyframes_interpolate(FCurve *fcu, BezTriple *bezts, float evaltime) { const float eps = 1.e-8f; - BezTriple *bezt, *prevbezt, *lastbezt; - float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac; + BezTriple *bezt, *prevbezt; unsigned int a; - int b; - float cvalue = 0.0f; - /* get pointers */ - a = fcu->totvert - 1; - prevbezt = bezts; - bezt = prevbezt + 1; - lastbezt = prevbezt + a; + /* evaltime occurs somewhere in the middle of the curve */ + bool exact = false; + + /* Use binary search to find appropriate keyframes... + * + * The threshold here has the following constraints: + * - 0.001 is too coarse: + * We get artifacts with 2cm driver movements at 1BU = 1m (see T40332) + * + * - 0.00001 is too fine: + * Weird errors, like selecting the wrong keyframe range (see T39207), occur. + * This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd. + */ + a = binarysearch_bezt_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact); + bezt = bezts + a; - /* evaluation time at or past endpoints? */ - if (prevbezt->vec[1][0] >= evaltime) { - /* before or on first keyframe */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) && - !(fcu->flag & FCURVE_DISCRETE_VALUES)) { - /* linear or bezier interpolation */ - if (prevbezt->ipo == BEZT_IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate - */ - if (fcu->totvert == 1) { - cvalue = prevbezt->vec[1][1]; - } - else { - bezt = prevbezt + 1; - dx = prevbezt->vec[1][0] - evaltime; - fac = bezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac = (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue = prevbezt->vec[1][1] - (fac * dx); - } - else { - cvalue = prevbezt->vec[1][1]; - } - } - } - else { - /* Use the first handle (earlier) of first BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ - dx = prevbezt->vec[1][0] - evaltime; - fac = prevbezt->vec[1][0] - prevbezt->vec[0][0]; + if (exact) { + /* index returned must be interpreted differently when it sits on top of an existing keyframe + * - that keyframe is the start of the segment we need (see action_bug_2.blend in T39207) + */ + return bezt->vec[1][1]; + } - /* prevent division by zero */ - if (fac) { - fac = (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac; - cvalue = prevbezt->vec[1][1] - (fac * dx); - } - else { - cvalue = prevbezt->vec[1][1]; - } - } - } - else { - /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, - * so just extend first keyframe's value - */ - cvalue = prevbezt->vec[1][1]; + /* index returned refers to the keyframe that the eval-time occurs *before* + * - hence, that keyframe marks the start of the segment we're dealing with + */ + prevbezt = (a > 0) ? (bezt - 1) : bezt; + + /* Use if the key is directly on the frame, in rare cases this is needed else we get 0.0 instead. + * XXX: consult T39207 for examples of files where failure of these checks can cause issues */ + if (fabsf(bezt->vec[1][0] - evaltime) < eps) { + return bezt->vec[1][1]; + } + + if (evaltime < prevbezt->vec[1][0] || bezt->vec[1][0] < evaltime) { + if (G.debug & G_DEBUG) { + printf(" ERROR: failed eval - p=%f b=%f, t=%f (%f)\n", + prevbezt->vec[1][0], + bezt->vec[1][0], + evaltime, + fabsf(bezt->vec[1][0] - evaltime)); } + return 0.0f; } - else if (lastbezt->vec[1][0] <= evaltime) { - /* after or on last keyframe */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) && - !(fcu->flag & FCURVE_DISCRETE_VALUES)) { - /* linear or bezier interpolation */ - if (lastbezt->ipo == BEZT_IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate + + /* Evaltime occurs within the interval defined by these two keyframes. */ + const float begin = prevbezt->vec[1][1]; + const float change = bezt->vec[1][1] - prevbezt->vec[1][1]; + const float duration = bezt->vec[1][0] - prevbezt->vec[1][0]; + const float time = evaltime - prevbezt->vec[1][0]; + const float amplitude = prevbezt->amplitude; + const float period = prevbezt->period; + + /* value depends on interpolation mode */ + if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES) || + (duration == 0)) { + /* constant (evaltime not relevant, so no interpolation needed) */ + return prevbezt->vec[1][1]; + } + + switch (prevbezt->ipo) { + /* interpolation ...................................... */ + case BEZT_IPO_BEZ: { + float v1[2], v2[2], v3[2], v4[2], opl[32]; + + /* bezier interpolation */ + /* (v1, v2) are the first keyframe and its 2nd handle */ + v1[0] = prevbezt->vec[1][0]; + v1[1] = prevbezt->vec[1][1]; + v2[0] = prevbezt->vec[2][0]; + v2[1] = prevbezt->vec[2][1]; + /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */ + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + if (fabsf(v1[1] - v4[1]) < FLT_EPSILON && fabsf(v2[1] - v3[1]) < FLT_EPSILON && + fabsf(v3[1] - v4[1]) < FLT_EPSILON) { + /* Optimization: If all the handles are flat/at the same values, + * the value is simply the shared value (see T40372 -> F91346) */ - if (fcu->totvert == 1) { - cvalue = lastbezt->vec[1][1]; - } - else { - prevbezt = lastbezt - 1; - dx = evaltime - lastbezt->vec[1][0]; - fac = lastbezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac = (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue = lastbezt->vec[1][1] + (fac * dx); - } - else { - cvalue = lastbezt->vec[1][1]; - } + return v1[1]; + } + /* adjust handles so that they don't overlap (forming a loop) */ + correct_bezpart(v1, v2, v3, v4); + + /* try to get a value for this position - if failure, try another set of points */ + if (!findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl)) { + if (G.debug & G_DEBUG) { + printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", + evaltime, + v1[0], + v2[0], + v3[0], + v4[0]); } + return 0.0; } - else { - /* Use the gradient of the second handle (later) of last BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ - dx = evaltime - lastbezt->vec[1][0]; - fac = lastbezt->vec[2][0] - lastbezt->vec[1][0]; - /* prevent division by zero */ - if (fac) { - fac = (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac; - cvalue = lastbezt->vec[1][1] + (fac * dx); - } - else { - cvalue = lastbezt->vec[1][1]; - } + berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); + return opl[0]; + } + case BEZT_IPO_LIN: + /* linear - simply linearly interpolate between values of the two keyframes */ + return BLI_easing_linear_ease(time, begin, change, duration); + + /* easing ............................................ */ + case BEZT_IPO_BACK: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_back_ease_in(time, begin, change, duration, prevbezt->back); + case BEZT_IPO_EASE_OUT: + return BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_back_ease_in_out(time, begin, change, duration, prevbezt->back); + + default: /* default/auto: same as ease out */ + return BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); } - } - else { - /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, - * so just extend last keyframe's value - */ - cvalue = lastbezt->vec[1][1]; - } - } - else { - /* evaltime occurs somewhere in the middle of the curve */ - bool exact = false; - - /* Use binary search to find appropriate keyframes... - * - * The threshold here has the following constraints: - * - 0.001 is too coarse: - * We get artifacts with 2cm driver movements at 1BU = 1m (see T40332) - * - * - 0.00001 is too fine: - * Weird errors, like selecting the wrong keyframe range (see T39207), occur. - * This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd. - */ - a = binarysearch_bezt_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact); + break; - if (exact) { - /* index returned must be interpreted differently when it sits on top of an existing keyframe - * - that keyframe is the start of the segment we need (see action_bug_2.blend in T39207) - */ - prevbezt = bezts + a; - bezt = (a < fcu->totvert - 1) ? (prevbezt + 1) : prevbezt; - } - else { - /* index returned refers to the keyframe that the eval-time occurs *before* - * - hence, that keyframe marks the start of the segment we're dealing with - */ - bezt = bezts + a; - prevbezt = (a > 0) ? (bezt - 1) : bezt; - } + case BEZT_IPO_BOUNCE: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_bounce_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_bounce_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_bounce_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease out */ + return BLI_easing_bounce_ease_out(time, begin, change, duration); + } + break; - /* use if the key is directly on the frame, - * rare cases this is needed else we get 0.0 instead. */ - /* XXX: consult T39207 for examples of files where failure of these checks can cause issues */ - if (exact) { - cvalue = prevbezt->vec[1][1]; - } - else if (fabsf(bezt->vec[1][0] - evaltime) < eps) { - cvalue = bezt->vec[1][1]; - } - /* evaltime occurs within the interval defined by these two keyframes */ - else if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) { - const float begin = prevbezt->vec[1][1]; - const float change = bezt->vec[1][1] - prevbezt->vec[1][1]; - const float duration = bezt->vec[1][0] - prevbezt->vec[1][0]; - const float time = evaltime - prevbezt->vec[1][0]; - const float amplitude = prevbezt->amplitude; - const float period = prevbezt->period; - - /* value depends on interpolation mode */ - if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES) || - (duration == 0)) { - /* constant (evaltime not relevant, so no interpolation needed) */ - cvalue = prevbezt->vec[1][1]; + case BEZT_IPO_CIRC: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_circ_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_circ_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_circ_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_circ_ease_in(time, begin, change, duration); } - else { - switch (prevbezt->ipo) { - /* interpolation ...................................... */ - case BEZT_IPO_BEZ: - /* bezier interpolation */ - /* (v1, v2) are the first keyframe and its 2nd handle */ - v1[0] = prevbezt->vec[1][0]; - v1[1] = prevbezt->vec[1][1]; - v2[0] = prevbezt->vec[2][0]; - v2[1] = prevbezt->vec[2][1]; - /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */ - v3[0] = bezt->vec[0][0]; - v3[1] = bezt->vec[0][1]; - v4[0] = bezt->vec[1][0]; - v4[1] = bezt->vec[1][1]; - - if (fabsf(v1[1] - v4[1]) < FLT_EPSILON && fabsf(v2[1] - v3[1]) < FLT_EPSILON && - fabsf(v3[1] - v4[1]) < FLT_EPSILON) { - /* Optimization: If all the handles are flat/at the same values, - * the value is simply the shared value (see T40372 -> F91346) - */ - cvalue = v1[1]; - } - else { - /* adjust handles so that they don't overlap (forming a loop) */ - correct_bezpart(v1, v2, v3, v4); - - /* try to get a value for this position - if failure, try another set of points */ - b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); - if (b) { - berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); - cvalue = opl[0]; - /* break; */ - } - else { - if (G.debug & G_DEBUG) { - printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", - evaltime, - v1[0], - v2[0], - v3[0], - v4[0]); - } - } - } - break; - - case BEZT_IPO_LIN: - /* linear - simply linearly interpolate between values of the two keyframes */ - cvalue = BLI_easing_linear_ease(time, begin, change, duration); - break; - - /* easing ............................................ */ - case BEZT_IPO_BACK: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_back_ease_in(time, begin, change, duration, prevbezt->back); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_back_ease_in_out( - time, begin, change, duration, prevbezt->back); - break; - - default: /* default/auto: same as ease out */ - cvalue = BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); - break; - } - break; - - case BEZT_IPO_BOUNCE: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_bounce_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_bounce_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_bounce_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease out */ - cvalue = BLI_easing_bounce_ease_out(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_CIRC: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_circ_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_circ_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_circ_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_circ_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_CUBIC: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_cubic_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_cubic_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_cubic_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_cubic_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_ELASTIC: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_elastic_ease_in( - time, begin, change, duration, amplitude, period); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_elastic_ease_out( - time, begin, change, duration, amplitude, period); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_elastic_ease_in_out( - time, begin, change, duration, amplitude, period); - break; - - default: /* default/auto: same as ease out */ - cvalue = BLI_easing_elastic_ease_out( - time, begin, change, duration, amplitude, period); - break; - } - break; - - case BEZT_IPO_EXPO: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_expo_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_expo_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_expo_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_expo_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_QUAD: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_quad_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_quad_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_quad_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_quad_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_QUART: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_quart_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_quart_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_quart_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_quart_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_QUINT: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_quint_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_quint_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_quint_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_quint_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_SINE: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_sine_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_sine_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_sine_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_sine_ease_in(time, begin, change, duration); - break; - } - break; + break; - default: - cvalue = prevbezt->vec[1][1]; - break; - } + case BEZT_IPO_CUBIC: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_cubic_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_cubic_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_cubic_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_cubic_ease_in(time, begin, change, duration); } - } - else { - if (G.debug & G_DEBUG) { - printf(" ERROR: failed eval - p=%f b=%f, t=%f (%f)\n", - prevbezt->vec[1][0], - bezt->vec[1][0], - evaltime, - fabsf(bezt->vec[1][0] - evaltime)); + break; + + case BEZT_IPO_ELASTIC: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_elastic_ease_in(time, begin, change, duration, amplitude, period); + case BEZT_IPO_EASE_OUT: + return BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_elastic_ease_in_out(time, begin, change, duration, amplitude, period); + + default: /* default/auto: same as ease out */ + return BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period); } - } + break; + + case BEZT_IPO_EXPO: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_expo_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_expo_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_expo_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_expo_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_QUAD: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_quad_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_quad_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_quad_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_quad_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_QUART: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_quart_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_quart_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_quart_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_quart_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_QUINT: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_quint_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_quint_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_quint_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_quint_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_SINE: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_sine_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_sine_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_sine_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_sine_ease_in(time, begin, change, duration); + } + break; + + default: + return prevbezt->vec[1][1]; } - /* return value */ - return cvalue; + return 0.0f; +} + +/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */ +static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) +{ + if (evaltime <= bezts->vec[1][0]) { + return fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, 0, +1); + } + + BezTriple *lastbezt = bezts + fcu->totvert - 1; + if (lastbezt->vec[1][0] <= evaltime) { + return fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, fcu->totvert - 1, -1); + } + + return fcurve_eval_keyframes_interpolate(fcu, bezts, evaltime); } /* Calculate F-Curve value for 'evaltime' using FPoint samples */ diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c new file mode 100644 index 00000000000..78a6cf28824 --- /dev/null +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -0,0 +1,1294 @@ +/* + * 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, Joshua Leung + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +// #include <float.h> +// #include <math.h> +// #include <stddef.h> +// #include <stdio.h> +// #include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_anim_types.h" +#include "DNA_constraint_types.h" +#include "DNA_object_types.h" + +#include "BLI_alloca.h" +#include "BLI_expr_pylike_eval.h" +#include "BLI_math.h" +#include "BLI_string_utils.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_fcurve_driver.h" +#include "BKE_global.h" +#include "BKE_object.h" + +#include "RNA_access.h" + +#include "atomic_ops.h" + +#include "CLG_log.h" + +#ifdef WITH_PYTHON +# include "BPY_extern.h" +#endif + +#ifdef WITH_PYTHON +static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER; +#endif + +static CLG_LogRef LOG = {"bke.fcurve"}; + +/* Driver Variables --------------------------- */ + +/* TypeInfo for Driver Variables (dvti) */ +typedef struct DriverVarTypeInfo { + /* evaluation callback */ + float (*get_value)(ChannelDriver *driver, DriverVar *dvar); + + /* allocation of target slots */ + int num_targets; /* number of target slots required */ + const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ + short target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */ +} DriverVarTypeInfo; + +/* Macro to begin definitions */ +#define BEGIN_DVAR_TYPEDEF(type) { + +/* Macro to end definitions */ +#define END_DVAR_TYPEDEF } + +/* ......... */ + +static ID *dtar_id_ensure_proxy_from(ID *id) +{ + if (id && GS(id->name) == ID_OB && ((Object *)id)->proxy_from) { + return (ID *)(((Object *)id)->proxy_from); + } + return id; +} + +/** + * Helper function to obtain a value using RNA from the specified source + * (for evaluating drivers). + */ +static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) +{ + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + ID *id; + int index = -1; + float value = 0.0f; + + /* sanity check */ + if (ELEM(NULL, driver, dtar)) { + return 0.0f; + } + + id = dtar_id_ensure_proxy_from(dtar->id); + + /* error check for missing pointer... */ + if (id == NULL) { + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + + /* get RNA-pointer for the ID-block given in target */ + RNA_id_pointer_create(id, &id_ptr); + + /* get property to read from, and get value as appropriate */ + if (!RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { + /* path couldn't be resolved */ + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, + "Driver Evaluation Error: cannot resolve target for %s -> %s", + id->name, + dtar->rna_path); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + + if (RNA_property_array_check(prop)) { + /* array */ + if (index < 0 || index >= RNA_property_array_length(&ptr, prop)) { + /* out of bounds */ + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, + "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)", + id->name, + dtar->rna_path, + index); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + value = (float)RNA_property_boolean_get_index(&ptr, prop, index); + break; + case PROP_INT: + value = (float)RNA_property_int_get_index(&ptr, prop, index); + break; + case PROP_FLOAT: + value = RNA_property_float_get_index(&ptr, prop, index); + break; + default: + break; + } + } + else { + /* not an array */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + value = (float)RNA_property_boolean_get(&ptr, prop); + break; + case PROP_INT: + value = (float)RNA_property_int_get(&ptr, prop); + break; + case PROP_FLOAT: + value = RNA_property_float_get(&ptr, prop); + break; + case PROP_ENUM: + value = (float)RNA_property_enum_get(&ptr, prop); + break; + default: + break; + } + } + + /* if we're still here, we should be ok... */ + dtar->flag &= ~DTAR_FLAG_INVALID; + return value; +} + +/** + * Same as 'dtar_get_prop_val'. but get the RNA property. + */ +bool driver_get_variable_property(ChannelDriver *driver, + DriverTarget *dtar, + PointerRNA *r_ptr, + PropertyRNA **r_prop, + int *r_index) +{ + PointerRNA id_ptr; + PointerRNA ptr; + PropertyRNA *prop; + ID *id; + int index = -1; + + /* sanity check */ + if (ELEM(NULL, driver, dtar)) { + return false; + } + + id = dtar_id_ensure_proxy_from(dtar->id); + + /* error check for missing pointer... */ + if (id == NULL) { + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return false; + } + + /* get RNA-pointer for the ID-block given in target */ + RNA_id_pointer_create(id, &id_ptr); + + /* get property to read from, and get value as appropriate */ + if (dtar->rna_path == NULL || dtar->rna_path[0] == '\0') { + ptr = PointerRNA_NULL; + prop = NULL; /* ok */ + } + else if (RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { + /* ok */ + } + else { + /* path couldn't be resolved */ + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, + "Driver Evaluation Error: cannot resolve target for %s -> %s", + id->name, + dtar->rna_path); + } + + ptr = PointerRNA_NULL; + *r_prop = NULL; + *r_index = -1; + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return false; + } + + *r_ptr = ptr; + *r_prop = prop; + *r_index = index; + + /* if we're still here, we should be ok... */ + dtar->flag &= ~DTAR_FLAG_INVALID; + return true; +} + +static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar) +{ + short valid_targets = 0; + + DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + + /* check if this target has valid data */ + if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { + /* invalid target, so will not have enough targets */ + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + } + else { + /* target seems to be OK now... */ + dtar->flag &= ~DTAR_FLAG_INVALID; + valid_targets++; + } + } + DRIVER_TARGETS_LOOPER_END; + + return valid_targets; +} + +/* ......... */ + +/* evaluate 'single prop' driver variable */ +static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar) +{ + /* just evaluate the first target slot */ + return dtar_get_prop_val(driver, &dvar->targets[0]); +} + +/* evaluate 'rotation difference' driver variable */ +static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) +{ + short valid_targets = driver_check_valid_targets(driver, dvar); + + /* make sure we have enough valid targets to use - all or nothing for now... */ + if (driver_check_valid_targets(driver, dvar) != 2) { + if (G.debug & G_DEBUG) { + CLOG_WARN(&LOG, + "RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", + valid_targets, + dvar->targets[0].id, + dvar->targets[1].id); + } + return 0.0f; + } + + float(*mat[2])[4]; + + /* NOTE: for now, these are all just worldspace */ + for (int i = 0; i < 2; i++) { + /* get pointer to loc values to store in */ + DriverTarget *dtar = &dvar->targets[i]; + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + bPoseChannel *pchan; + + /* after the checks above, the targets should be valid here... */ + BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); + + /* try to get posechannel */ + pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + + /* check if object or bone */ + if (pchan) { + /* bone */ + mat[i] = pchan->pose_mat; + } + else { + /* object */ + mat[i] = ob->obmat; + } + } + + float q1[4], q2[4], quat[4], angle; + + /* use the final posed locations */ + mat4_to_quat(q1, mat[0]); + mat4_to_quat(q2, mat[1]); + + invert_qt_normalized(q1); + mul_qt_qtqt(quat, q1, q2); + angle = 2.0f * (saacos(quat[0])); + angle = fabsf(angle); + + return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle); +} + +/* evaluate 'location difference' driver variable */ +/* TODO: this needs to take into account space conversions... */ +static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) +{ + float loc1[3] = {0.0f, 0.0f, 0.0f}; + float loc2[3] = {0.0f, 0.0f, 0.0f}; + short valid_targets = driver_check_valid_targets(driver, dvar); + + /* make sure we have enough valid targets to use - all or nothing for now... */ + if (valid_targets < dvar->num_targets) { + if (G.debug & G_DEBUG) { + CLOG_WARN(&LOG, + "LocDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", + valid_targets, + dvar->targets[0].id, + dvar->targets[1].id); + } + return 0.0f; + } + + /* SECOND PASS: get two location values */ + /* NOTE: for now, these are all just worldspace */ + DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { + /* get pointer to loc values to store in */ + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + bPoseChannel *pchan; + float tmp_loc[3]; + + /* after the checks above, the targets should be valid here... */ + BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); + + /* try to get posechannel */ + pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + + /* check if object or bone */ + if (pchan) { + /* bone */ + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + float mat[4][4]; + + /* extract transform just like how the constraints do it! */ + copy_m4_m4(mat, pchan->pose_mat); + BKE_constraint_mat_convertspace( + ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); + + /* ... and from that, we get our transform */ + copy_v3_v3(tmp_loc, mat[3]); + } + else { + /* transform space (use transform values directly) */ + copy_v3_v3(tmp_loc, pchan->loc); + } + } + else { + /* convert to worldspace */ + copy_v3_v3(tmp_loc, pchan->pose_head); + mul_m4_v3(ob->obmat, tmp_loc); + } + } + else { + /* object */ + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* XXX: this should practically be the same as transform space... */ + float mat[4][4]; + + /* extract transform just like how the constraints do it! */ + copy_m4_m4(mat, ob->obmat); + BKE_constraint_mat_convertspace( + ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); + + /* ... and from that, we get our transform */ + copy_v3_v3(tmp_loc, mat[3]); + } + else { + /* transform space (use transform values directly) */ + copy_v3_v3(tmp_loc, ob->loc); + } + } + else { + /* worldspace */ + copy_v3_v3(tmp_loc, ob->obmat[3]); + } + } + + /* copy the location to the right place */ + if (tarIndex) { + copy_v3_v3(loc2, tmp_loc); + } + else { + copy_v3_v3(loc1, tmp_loc); + } + } + DRIVER_TARGETS_LOOPER_END; + + /* if we're still here, there should now be two targets to use, + * so just take the length of the vector between these points + */ + return len_v3v3(loc1, loc2); +} + +/* evaluate 'transform channel' driver variable */ +static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) +{ + DriverTarget *dtar = &dvar->targets[0]; + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + bPoseChannel *pchan; + float mat[4][4]; + float oldEul[3] = {0.0f, 0.0f, 0.0f}; + bool use_eulers = false; + short rot_order = ROT_MODE_EUL; + + /* check if this target has valid data */ + if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { + /* invalid target, so will not have enough targets */ + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + else { + /* target should be valid now */ + dtar->flag &= ~DTAR_FLAG_INVALID; + } + + /* try to get posechannel */ + pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + + /* check if object or bone, and get transform matrix accordingly + * - "useEulers" code is used to prevent the problems associated with non-uniqueness + * of euler decomposition from matrices [#20870] + * - localspace is for [#21384], where parent results are not wanted + * but local-consts is for all the common "corrective-shapes-for-limbs" situations + */ + if (pchan) { + /* bone */ + if (pchan->rotmode > 0) { + copy_v3_v3(oldEul, pchan->eul); + rot_order = pchan->rotmode; + use_eulers = true; + } + + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* just like how the constraints do it! */ + copy_m4_m4(mat, pchan->pose_mat); + BKE_constraint_mat_convertspace( + ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); + } + else { + /* specially calculate local matrix, since chan_mat is not valid + * since it stores delta transform of pose_mat so that deforms work + * so it cannot be used here for "transform" space + */ + BKE_pchan_to_mat4(pchan, mat); + } + } + else { + /* worldspace matrix */ + mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); + } + } + else { + /* object */ + if (ob->rotmode > 0) { + copy_v3_v3(oldEul, ob->rot); + rot_order = ob->rotmode; + use_eulers = true; + } + + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* just like how the constraints do it! */ + copy_m4_m4(mat, ob->obmat); + BKE_constraint_mat_convertspace( + ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); + } + else { + /* transforms to matrix */ + BKE_object_to_mat4(ob, mat); + } + } + else { + /* worldspace matrix - just the good-old one */ + copy_m4_m4(mat, ob->obmat); + } + } + + /* check which transform */ + if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) { + /* not valid channel */ + return 0.0f; + } + else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) { + /* Cubic root of the change in volume, equal to the geometric mean + * of scale over all three axes unless the matrix includes shear. */ + return cbrtf(mat4_to_volume_scale(mat)); + } + else if (ELEM(dtar->transChan, + DTAR_TRANSCHAN_SCALEX, + DTAR_TRANSCHAN_SCALEY, + DTAR_TRANSCHAN_SCALEZ)) { + /* Extract scale, and choose the right axis, + * inline 'mat4_to_size'. */ + return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]); + } + else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) { + /* extract rotation as eulers (if needed) + * - definitely if rotation order isn't eulers already + * - if eulers, then we have 2 options: + * a) decompose transform matrix as required, then try to make eulers from + * there compatible with original values + * b) [NOT USED] directly use the original values (no decomposition) + * - only an option for "transform space", if quality is really bad with a) + */ + float quat[4]; + int channel; + + if (dtar->transChan == DTAR_TRANSCHAN_ROTW) { + channel = 0; + } + else { + channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX; + BLI_assert(channel < 4); + } + + BKE_driver_target_matrix_to_rot_channels( + mat, rot_order, dtar->rotation_mode, channel, false, quat); + + if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) { + compatible_eul(quat + 1, oldEul); + } + + return quat[channel]; + } + else { + /* extract location and choose right axis */ + return mat[3][dtar->transChan]; + } +} + +/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */ +static void quaternion_to_angles(float quat[4], int channel) +{ + if (channel < 0) { + quat[0] = 2.0f * saacosf(quat[0]); + + for (int i = 1; i < 4; i++) { + quat[i] = 2.0f * saasinf(quat[i]); + } + } + else if (channel == 0) { + quat[0] = 2.0f * saacosf(quat[0]); + } + else { + quat[channel] = 2.0f * saasinf(quat[channel]); + } +} + +/* Compute channel values for a rotational Transform Channel driver variable. */ +void BKE_driver_target_matrix_to_rot_channels( + float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]) +{ + float *const quat = r_buf; + float *const eul = r_buf + 1; + + zero_v4(r_buf); + + if (rotation_mode == DTAR_ROTMODE_AUTO) { + mat4_to_eulO(eul, auto_order, mat); + } + else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) { + mat4_to_eulO(eul, rotation_mode, mat); + } + else if (rotation_mode == DTAR_ROTMODE_QUATERNION) { + mat4_to_quat(quat, mat); + + /* For Transformation constraint convenience, convert to pseudo-angles. */ + if (angles) { + quaternion_to_angles(quat, channel); + } + } + else if (rotation_mode >= DTAR_ROTMODE_SWING_TWIST_X && + rotation_mode <= DTAR_ROTMODE_SWING_TWIST_Z) { + int axis = rotation_mode - DTAR_ROTMODE_SWING_TWIST_X; + float raw_quat[4], twist; + + mat4_to_quat(raw_quat, mat); + + if (channel == axis + 1) { + /* If only the twist angle is needed, skip computing swing. */ + twist = quat_split_swing_and_twist(raw_quat, axis, NULL, NULL); + } + else { + twist = quat_split_swing_and_twist(raw_quat, axis, quat, NULL); + + quaternion_to_angles(quat, channel); + } + + quat[axis + 1] = twist; + } + else { + BLI_assert(false); + } +} + +/* ......... */ + +/* Table of Driver Variable Type Info Data */ +static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) dvar_eval_singleProp, /* eval callback */ + 1, /* number of targets used */ + {"Property"}, /* UI names for targets */ + {0} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF) dvar_eval_rotDiff, /* eval callback */ + 2, /* number of targets used */ + {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, + DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF) dvar_eval_locDiff, /* eval callback */ + 2, /* number of targets used */ + {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, + DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN) dvar_eval_transChan, /* eval callback */ + 1, /* number of targets used */ + {"Object/Bone"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, +}; + +/* Get driver variable typeinfo */ +static const DriverVarTypeInfo *get_dvar_typeinfo(int type) +{ + /* check if valid type */ + if ((type >= 0) && (type < MAX_DVAR_TYPES)) { + return &dvar_types[type]; + } + else { + return NULL; + } +} + +/* Driver API --------------------------------- */ + +/* Perform actual freeing driver variable and remove it from the given list */ +void driver_free_variable(ListBase *variables, DriverVar *dvar) +{ + /* sanity checks */ + if (dvar == NULL) { + return; + } + + /* free target vars + * - need to go over all of them, not just up to the ones that are used + * currently, since there may be some lingering RNA paths from + * previous users needing freeing + */ + DRIVER_TARGETS_LOOPER_BEGIN (dvar) { + /* free RNA path if applicable */ + if (dtar->rna_path) { + MEM_freeN(dtar->rna_path); + } + } + DRIVER_TARGETS_LOOPER_END; + + /* remove the variable from the driver */ + BLI_freelinkN(variables, dvar); +} + +/* Free the driver variable and do extra updates */ +void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar) +{ + /* remove and free the driver variable */ + driver_free_variable(&driver->variables, dvar); + + /* since driver variables are cached, the expression needs re-compiling too */ + BKE_driver_invalidate_expression(driver, false, true); +} + +/* Copy driver variables from src_vars list to dst_vars list */ +void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars) +{ + BLI_assert(BLI_listbase_is_empty(dst_vars)); + BLI_duplicatelist(dst_vars, src_vars); + + LISTBASE_FOREACH (DriverVar *, dvar, dst_vars) { + /* need to go over all targets so that we don't leave any dangling paths */ + DRIVER_TARGETS_LOOPER_BEGIN (dvar) { + /* make a copy of target's rna path if available */ + if (dtar->rna_path) { + dtar->rna_path = MEM_dupallocN(dtar->rna_path); + } + } + DRIVER_TARGETS_LOOPER_END; + } +} + +/* Change the type of driver variable */ +void driver_change_variable_type(DriverVar *dvar, int type) +{ + const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type); + + /* sanity check */ + if (ELEM(NULL, dvar, dvti)) { + return; + } + + /* set the new settings */ + dvar->type = type; + dvar->num_targets = dvti->num_targets; + + /* make changes to the targets based on the defines for these types + * NOTE: only need to make sure the ones we're using here are valid... + */ + DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { + short flags = dvti->target_flags[tarIndex]; + + /* store the flags */ + dtar->flag = flags; + + /* object ID types only, or idtype not yet initialized */ + if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0)) { + dtar->idtype = ID_OB; + } + } + DRIVER_TARGETS_LOOPER_END; +} + +/* Validate driver name (after being renamed) */ +void driver_variable_name_validate(DriverVar *dvar) +{ + /* Special character blacklist */ + const char special_char_blacklist[] = { + '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '+', '=', '-', '/', '\\', + '?', ':', ';', '<', '>', '{', '}', '[', ']', '|', ' ', '.', '\t', '\n', '\r', + }; + + /* sanity checks */ + if (dvar == NULL) { + return; + } + + /* clear all invalid-name flags */ + dvar->flag &= ~DVAR_ALL_INVALID_FLAGS; + + /* 0) Zero-length identifiers are not allowed */ + if (dvar->name[0] == '\0') { + dvar->flag |= DVAR_FLAG_INVALID_EMPTY; + } + + /* 1) Must start with a letter */ + /* XXX: We assume that valid unicode letters in other languages are ok too, + * hence the blacklisting. */ + if (IN_RANGE_INCL(dvar->name[0], '0', '9')) { + dvar->flag |= DVAR_FLAG_INVALID_START_NUM; + } + else if (dvar->name[0] == '_') { + /* NOTE: We don't allow names to start with underscores + * (i.e. it helps when ruling out security risks) */ + dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; + } + + /* 2) Must not contain invalid stuff in the middle of the string */ + if (strchr(dvar->name, ' ')) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_SPACE; + } + if (strchr(dvar->name, '.')) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_DOT; + } + + /* 3) Check for special characters - Either at start, or in the middle */ + for (int i = 0; i < sizeof(special_char_blacklist); i++) { + char *match = strchr(dvar->name, special_char_blacklist[i]); + + if (match == dvar->name) { + dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; + } + else if (match != NULL) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_SPECIAL; + } + } + + /* 4) Check if the name is a reserved keyword + * NOTE: These won't confuse Python, but it will be impossible to use the variable + * in an expression without Python misinterpreting what these are for + */ +#ifdef WITH_PYTHON + if (BPY_string_is_keyword(dvar->name)) { + dvar->flag |= DVAR_FLAG_INVALID_PY_KEYWORD; + } +#endif + + /* If any these conditions match, the name is invalid */ + if (dvar->flag & DVAR_ALL_INVALID_FLAGS) { + dvar->flag |= DVAR_FLAG_INVALID_NAME; + } +} + +/* Add a new driver variable */ +DriverVar *driver_add_new_variable(ChannelDriver *driver) +{ + DriverVar *dvar; + + /* sanity checks */ + if (driver == NULL) { + return NULL; + } + + /* make a new variable */ + dvar = MEM_callocN(sizeof(DriverVar), "DriverVar"); + BLI_addtail(&driver->variables, dvar); + + /* give the variable a 'unique' name */ + strcpy(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var")); + BLI_uniquename(&driver->variables, + dvar, + CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"), + '_', + offsetof(DriverVar, name), + sizeof(dvar->name)); + + /* set the default type to 'single prop' */ + driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP); + + /* since driver variables are cached, the expression needs re-compiling too */ + BKE_driver_invalidate_expression(driver, false, true); + + /* return the target */ + return dvar; +} + +/* This frees the driver itself */ +void fcurve_free_driver(FCurve *fcu) +{ + ChannelDriver *driver; + DriverVar *dvar, *dvarn; + + /* sanity checks */ + if (ELEM(NULL, fcu, fcu->driver)) { + return; + } + driver = fcu->driver; + + /* free driver targets */ + for (dvar = driver->variables.first; dvar; dvar = dvarn) { + dvarn = dvar->next; + driver_free_variable_ex(driver, dvar); + } + +#ifdef WITH_PYTHON + /* free compiled driver expression */ + if (driver->expr_comp) { + BPY_DECREF(driver->expr_comp); + } +#endif + + BLI_expr_pylike_free(driver->expr_simple); + + /* Free driver itself, then set F-Curve's point to this to NULL + * (as the curve may still be used). */ + MEM_freeN(driver); + fcu->driver = NULL; +} + +/* This makes a copy of the given driver */ +ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver) +{ + ChannelDriver *ndriver; + + /* sanity checks */ + if (driver == NULL) { + return NULL; + } + + /* copy all data */ + ndriver = MEM_dupallocN(driver); + ndriver->expr_comp = NULL; + ndriver->expr_simple = NULL; + + /* copy variables */ + + /* to get rid of refs to non-copied data (that's still used on original) */ + BLI_listbase_clear(&ndriver->variables); + driver_variables_copy(&ndriver->variables, &driver->variables); + + /* return the new driver */ + return ndriver; +} + +/* Driver Expression Evaluation --------------- */ + +/* Index constants for the expression parameter array. */ +enum { + /* Index of the 'frame' variable. */ + VAR_INDEX_FRAME = 0, + /* Index of the first user-defined driver variable. */ + VAR_INDEX_CUSTOM +}; + +static ExprPyLike_Parsed *driver_compile_simple_expr_impl(ChannelDriver *driver) +{ + /* Prepare parameter names. */ + int names_len = BLI_listbase_count(&driver->variables); + const char **names = BLI_array_alloca(names, names_len + VAR_INDEX_CUSTOM); + int i = VAR_INDEX_CUSTOM; + + names[VAR_INDEX_FRAME] = "frame"; + + LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { + names[i++] = dvar->name; + } + + return BLI_expr_pylike_parse(driver->expression, names, names_len + VAR_INDEX_CUSTOM); +} + +static bool driver_check_simple_expr_depends_on_time(ExprPyLike_Parsed *expr) +{ + /* Check if the 'frame' parameter is actually used. */ + return BLI_expr_pylike_is_using_param(expr, VAR_INDEX_FRAME); +} + +static bool driver_evaluate_simple_expr(ChannelDriver *driver, + ExprPyLike_Parsed *expr, + float *result, + float time) +{ + /* Prepare parameter values. */ + int vars_len = BLI_listbase_count(&driver->variables); + double *vars = BLI_array_alloca(vars, vars_len + VAR_INDEX_CUSTOM); + int i = VAR_INDEX_CUSTOM; + + vars[VAR_INDEX_FRAME] = time; + + LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { + vars[i++] = driver_get_variable_value(driver, dvar); + } + + /* Evaluate expression. */ + double result_val; + eExprPyLike_EvalStatus status = BLI_expr_pylike_eval( + expr, vars, vars_len + VAR_INDEX_CUSTOM, &result_val); + const char *message; + + switch (status) { + case EXPR_PYLIKE_SUCCESS: + if (isfinite(result_val)) { + *result = (float)result_val; + } + return true; + + case EXPR_PYLIKE_DIV_BY_ZERO: + case EXPR_PYLIKE_MATH_ERROR: + message = (status == EXPR_PYLIKE_DIV_BY_ZERO) ? "Division by Zero" : "Math Domain Error"; + CLOG_ERROR(&LOG, "%s in Driver: '%s'", message, driver->expression); + + driver->flag |= DRIVER_FLAG_INVALID; + return true; + + default: + /* arriving here means a bug, not user error */ + CLOG_ERROR(&LOG, "simple driver expression evaluation failed: '%s'", driver->expression); + return false; + } +} + +/* Compile and cache the driver expression if necessary, with thread safety. */ +static bool driver_compile_simple_expr(ChannelDriver *driver) +{ + if (driver->expr_simple != NULL) { + return true; + } + + if (driver->type != DRIVER_TYPE_PYTHON) { + return false; + } + + /* It's safe to parse in multiple threads; at worst it'll + * waste some effort, but in return avoids mutex contention. */ + ExprPyLike_Parsed *expr = driver_compile_simple_expr_impl(driver); + + /* Store the result if the field is still NULL, or discard + * it if another thread got here first. */ + if (atomic_cas_ptr((void **)&driver->expr_simple, NULL, expr) != NULL) { + BLI_expr_pylike_free(expr); + } + + return true; +} + +/* Try using the simple expression evaluator to compute the result of the driver. + * On success, stores the result and returns true; on failure result is set to 0. */ +static bool driver_try_evaluate_simple_expr(ChannelDriver *driver, + ChannelDriver *driver_orig, + float *result, + float time) +{ + *result = 0.0f; + + return driver_compile_simple_expr(driver_orig) && + BLI_expr_pylike_is_valid(driver_orig->expr_simple) && + driver_evaluate_simple_expr(driver, driver_orig->expr_simple, result, time); +} + +/* Check if the expression in the driver conforms to the simple subset. */ +bool BKE_driver_has_simple_expression(ChannelDriver *driver) +{ + return driver_compile_simple_expr(driver) && BLI_expr_pylike_is_valid(driver->expr_simple); +} + +/* TODO(sergey): This is somewhat weak, but we don't want neither false-positive + * time dependencies nor special exceptions in the depsgraph evaluation. */ +static bool python_driver_exression_depends_on_time(const char *expression) +{ + if (expression[0] == '\0') { + /* Empty expression depends on nothing. */ + return false; + } + if (strchr(expression, '(') != NULL) { + /* Function calls are considered dependent on a time. */ + return true; + } + if (strstr(expression, "frame") != NULL) { + /* Variable `frame` depends on time. */ + /* TODO(sergey): This is a bit weak, but not sure about better way of handling this. */ + return true; + } + /* Possible indirect time relation s should be handled via variable targets. */ + return false; +} + +/* Check if the expression in the driver may depend on the current frame. */ +bool BKE_driver_expression_depends_on_time(ChannelDriver *driver) +{ + if (driver->type != DRIVER_TYPE_PYTHON) { + return false; + } + + if (BKE_driver_has_simple_expression(driver)) { + /* Simple expressions can be checked exactly. */ + return driver_check_simple_expr_depends_on_time(driver->expr_simple); + } + else { + /* Otherwise, heuristically scan the expression string for certain patterns. */ + return python_driver_exression_depends_on_time(driver->expression); + } +} + +/* Reset cached compiled expression data */ +void BKE_driver_invalidate_expression(ChannelDriver *driver, + bool expr_changed, + bool varname_changed) +{ + if (expr_changed || varname_changed) { + BLI_expr_pylike_free(driver->expr_simple); + driver->expr_simple = NULL; + } + +#ifdef WITH_PYTHON + if (expr_changed) { + driver->flag |= DRIVER_FLAG_RECOMPILE; + } + + if (varname_changed) { + driver->flag |= DRIVER_FLAG_RENAMEVAR; + } +#endif +} + +/* Driver Evaluation -------------------------- */ + +/* Evaluate a Driver Variable to get a value that contributes to the final */ +float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar) +{ + const DriverVarTypeInfo *dvti; + + /* sanity check */ + if (ELEM(NULL, driver, dvar)) { + return 0.0f; + } + + /* call the relevant callbacks to get the variable value + * using the variable type info, storing the obtained value + * in dvar->curval so that drivers can be debugged + */ + dvti = get_dvar_typeinfo(dvar->type); + + if (dvti && dvti->get_value) { + dvar->curval = dvti->get_value(driver, dvar); + } + else { + dvar->curval = 0.0f; + } + + return dvar->curval; +} + +static void evaluate_driver_sum(ChannelDriver *driver) +{ + DriverVar *dvar; + + /* check how many variables there are first (i.e. just one?) */ + if (BLI_listbase_is_single(&driver->variables)) { + /* just one target, so just use that */ + dvar = driver->variables.first; + driver->curval = driver_get_variable_value(driver, dvar); + return; + } + + /* more than one target, so average the values of the targets */ + float value = 0.0f; + int tot = 0; + + /* loop through targets, adding (hopefully we don't get any overflow!) */ + for (dvar = driver->variables.first; dvar; dvar = dvar->next) { + value += driver_get_variable_value(driver, dvar); + tot++; + } + + /* perform operations on the total if appropriate */ + if (driver->type == DRIVER_TYPE_AVERAGE) { + driver->curval = tot ? (value / (float)tot) : 0.0f; + } + else { + driver->curval = value; + } +} + +static void evaluate_driver_min_max(ChannelDriver *driver) +{ + DriverVar *dvar; + float value = 0.0f; + + /* loop through the variables, getting the values and comparing them to existing ones */ + for (dvar = driver->variables.first; dvar; dvar = dvar->next) { + /* get value */ + float tmp_val = driver_get_variable_value(driver, dvar); + + /* store this value if appropriate */ + if (dvar->prev) { + /* check if greater/smaller than the baseline */ + if (driver->type == DRIVER_TYPE_MAX) { + /* max? */ + if (tmp_val > value) { + value = tmp_val; + } + } + else { + /* min? */ + if (tmp_val < value) { + value = tmp_val; + } + } + } + else { + /* first item - make this the baseline for comparisons */ + value = tmp_val; + } + } + + /* store value in driver */ + driver->curval = value; +} + +static void evaluate_driver_python(PathResolvedRNA *anim_rna, + ChannelDriver *driver, + ChannelDriver *driver_orig, + const float evaltime) +{ + /* check for empty or invalid expression */ + if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) { + driver->curval = 0.0f; + } + else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) { +#ifdef WITH_PYTHON + /* this evaluates the expression using Python, and returns its result: + * - on errors it reports, then returns 0.0f + */ + BLI_mutex_lock(&python_driver_lock); + + driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime); + + BLI_mutex_unlock(&python_driver_lock); +#else /* WITH_PYTHON*/ + UNUSED_VARS(anim_rna, evaltime); +#endif /* WITH_PYTHON*/ + } +} + +/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" + * - "evaltime" is the frame at which F-Curve is being evaluated + * - has to return a float value + * - driver_orig is where we cache Python expressions, in case of COW + */ +float evaluate_driver(PathResolvedRNA *anim_rna, + ChannelDriver *driver, + ChannelDriver *driver_orig, + const float evaltime) +{ + /* check if driver can be evaluated */ + if (driver_orig->flag & DRIVER_FLAG_INVALID) { + return 0.0f; + } + + switch (driver->type) { + case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ + case DRIVER_TYPE_SUM: /* sum values of driver targets */ + evaluate_driver_sum(driver); + break; + case DRIVER_TYPE_MIN: /* smallest value */ + case DRIVER_TYPE_MAX: /* largest value */ + evaluate_driver_min_max(driver); + break; + case DRIVER_TYPE_PYTHON: /* expression */ + evaluate_driver_python(anim_rna, driver, driver_orig, evaltime); + break; + default: + /* special 'hack' - just use stored value + * This is currently used as the mechanism which allows animated settings to be able + * to be changed via the UI. + */ + break; + } + + /* return value for driver */ + return driver->curval; +} diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 7adac2d4a4d..6e4c343eac3 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -81,6 +81,8 @@ # include "RE_shader_ext.h" +# include "CLG_log.h" + # include "manta_fluid_API.h" #endif /* WITH_FLUID */ @@ -96,6 +98,8 @@ static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *mmd, bool need #ifdef WITH_FLUID // #define DEBUG_PRINT +static CLG_LogRef LOG = {"bke.fluid"}; + /* -------------------------------------------------------------------- */ /** \name Fluid API * \{ */ @@ -346,7 +350,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map) { char temp_dir[FILE_MAX]; int flags = mds->cache_flag; - const char *relbase = modifier_path_relbase_from_global(ob); + const char *relbase = BKE_modifier_path_relbase_from_global(ob); if (cache_map & FLUID_DOMAIN_OUTDATED_DATA) { flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA); @@ -487,32 +491,6 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *mds, mds->cell_size[2] /= (float)mds->base_res[2]; } -static void manta_set_domain_gravity(Scene *scene, FluidDomainSettings *mds) -{ - const float normalization_factor = 1.0f / 9.81f; - - /* Use global gravity if enabled. */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - float gravity[3]; - copy_v3_v3(gravity, scene->physics_settings.gravity); - /* Map default value to 1.0. */ - mul_v3_fl(gravity, normalization_factor); - - /* Convert gravity to domain space. */ - float gravity_mag = len_v3(gravity); - mul_mat3_m4_v3(mds->imat, gravity); - normalize_v3(gravity); - mul_v3_fl(gravity, gravity_mag); - - copy_v3_v3(mds->gravity, gravity); - } - else { - mul_v3_fl(mds->gravity, normalization_factor); - } - - mul_v3_fl(mds->gravity, mds->effector_weights->global_gravity); -} - static bool BKE_fluid_modifier_init( FluidModifierData *mmd, Depsgraph *depsgraph, Object *ob, Scene *scene, Mesh *me) { @@ -523,8 +501,11 @@ static bool BKE_fluid_modifier_init( int res[3]; /* Set domain dimensions from mesh. */ manta_set_domain_from_mesh(mds, ob, me, true); - /* Set domain gravity. */ - manta_set_domain_gravity(scene, mds); + /* Set domain gravity, use global gravity if enabled. */ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(mds->gravity, scene->physics_settings.gravity); + } + mul_v3_fl(mds->gravity, mds->effector_weights->global_gravity); /* Reset domain values. */ zero_v3_int(mds->shift); zero_v3(mds->shift_f); @@ -552,7 +533,6 @@ static bool BKE_fluid_modifier_init( /* Initially dt is equal to frame length (dt can change with adaptive-time stepping though). */ mds->dt = mds->frame_length; mds->time_per_frame = 0; - mds->time_total = abs(scene_framenr - mds->cache_frame_start) * mds->frame_length; mmd->time = scene_framenr; @@ -948,11 +928,7 @@ static void sample_effector(FluidEffectorSettings *mes, velocity_map[index * 3 + 2] += hit_vel[2]; # ifdef DEBUG_PRINT /* Debugging: Print object velocities. */ - printf("adding effector object vel: [%f, %f, %f], dx is: %f\n", - hit_vel[0], - hit_vel[1], - hit_vel[2], - mds->dx); + printf("adding effector object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]); # endif } } @@ -1165,8 +1141,8 @@ static void update_obstacleflags(FluidDomainSettings *mds, /* Monitor active fields based on flow settings */ for (coll_index = 0; coll_index < coll_ob_array_len; coll_index++) { Object *coll_ob = coll_ob_array[coll_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(coll_ob, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(coll_ob, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -1238,8 +1214,8 @@ static void compute_obstaclesemission(Scene *scene, /* Prepare effector maps. */ for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) { Object *effecobj = effecobjs[effec_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(effecobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(effecobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -1411,8 +1387,8 @@ static void update_obstacles(Depsgraph *depsgraph, /* Prepare grids from effector objects. */ for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) { Object *effecobj = effecobjs[effec_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(effecobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(effecobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -1996,9 +1972,9 @@ static void sample_mesh(FluidFlowSettings *mfs, normalize_v3(hit_normal); /* Apply normal directional velocity. */ - velocity_map[index * 3] += hit_normal[0] * mfs->vel_normal * 0.25f; - velocity_map[index * 3 + 1] += hit_normal[1] * mfs->vel_normal * 0.25f; - velocity_map[index * 3 + 2] += hit_normal[2] * mfs->vel_normal * 0.25f; + velocity_map[index * 3] += hit_normal[0] * mfs->vel_normal; + velocity_map[index * 3 + 1] += hit_normal[1] * mfs->vel_normal; + velocity_map[index * 3 + 2] += hit_normal[2] * mfs->vel_normal; } /* Apply object velocity. */ if (has_velocity && mfs->vel_multi) { @@ -2651,8 +2627,8 @@ static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int n /* Monitor active fields based on flow settings */ for (flow_index = 0; flow_index < numflowobj; flow_index++) { Object *flow_ob = flowobjs[flow_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flow_ob, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flow_ob, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -2782,8 +2758,8 @@ static void compute_flowsemission(Scene *scene, /* Prepare flow emission maps. */ for (int flow_index = 0; flow_index < numflowobjs; flow_index++) { Object *flowobj = flowobjs[flow_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flowobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -3002,8 +2978,8 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, /* Apply emission data for every flow object. */ for (int flow_index = 0; flow_index < numflowobjs; flow_index++) { Object *flowobj = flowobjs[flow_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flowobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -3570,7 +3546,7 @@ static int manta_step( Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me, FluidModifierData *mmd, int frame) { FluidDomainSettings *mds = mmd->domain; - float dt, frame_length, time_total; + float dt, frame_length, time_total, time_total_old; float time_per_frame; bool init_resolution = true; @@ -3594,6 +3570,8 @@ static int manta_step( dt = mds->dt; time_per_frame = 0; time_total = mds->time_total; + /* Keep track of original total time to correct small errors at end of step. */ + time_total_old = mds->time_total; BLI_mutex_lock(&object_update_lock); @@ -3639,6 +3617,8 @@ static int manta_step( mds->time_per_frame = time_per_frame; mds->time_total = time_total; } + /* Total time must not exceed framecount times framelength. Correct tiny errors here. */ + CLAMP(mds->time_total, mds->time_total, time_total_old + mds->frame_length); if (mds->type == FLUID_DOMAIN_TYPE_GAS && result) { manta_smoke_calc_transparency(mds, DEG_get_evaluated_view_layer(depsgraph)); @@ -3745,7 +3725,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, } /* Ensure cache directory is not relative. */ - const char *relbase = modifier_path_relbase_from_global(ob); + const char *relbase = BKE_modifier_path_relbase_from_global(ob); BLI_path_abs(mds->cache_directory, relbase); /* Ensure that all flags are up to date before doing any baking and/or cache reading. */ @@ -3775,6 +3755,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Fluid domain init must not fail in order to continue modifier evaluation. */ if (!mds->fluid && !BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me)) { + CLOG_ERROR(&LOG, "Fluid initialization failed. Should not happen!"); return; } BLI_assert(mds->fluid); @@ -3782,7 +3763,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Guiding parent res pointer needs initialization. */ guide_parent = mds->guide_parent; if (guide_parent) { - mmd_parent = (FluidModifierData *)modifiers_findByType(guide_parent, eModifierType_Fluid); + mmd_parent = (FluidModifierData *)BKE_modifiers_findby_type(guide_parent, eModifierType_Fluid); if (mmd_parent && mmd_parent->domain) { copy_v3_v3_int(mds->guide_res, mmd_parent->domain->res); } @@ -3793,8 +3774,12 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, mds->frame_length = DT_DEFAULT * (25.0f / fps) * mds->time_scale; mds->dt = mds->frame_length; mds->time_per_frame = 0; - /* Get distance between cache start and current frame for total time. */ - mds->time_total = abs(scene_framenr - mds->cache_frame_start) * mds->frame_length; + + /* Ensure that gravity is copied over every frame (could be keyframed). */ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(mds->gravity, scene->physics_settings.gravity); + mul_v3_fl(mds->gravity, mds->effector_weights->global_gravity); + } int next_frame = scene_framenr + 1; int prev_frame = scene_framenr - 1; @@ -3821,12 +3806,13 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, with_guide = mds->flags & FLUID_DOMAIN_USE_GUIDE; with_particles = drops || bubble || floater; - bool has_data, has_noise, has_mesh, has_particles, has_guide; + bool has_data, has_noise, has_mesh, has_particles, has_guide, has_config; has_data = manta_has_data(mds->fluid, mmd, scene_framenr); has_noise = manta_has_noise(mds->fluid, mmd, scene_framenr); has_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr); has_particles = manta_has_particles(mds->fluid, mmd, scene_framenr); has_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr, guide_parent); + has_config = false; bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; baking_data = mds->cache_flag & FLUID_DOMAIN_BAKING_DATA; @@ -3937,12 +3923,16 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Read mesh cache. */ if (with_liquid && with_mesh) { + has_config = manta_read_config(mds->fluid, mmd, mesh_frame); + /* Update mesh data from file is faster than via Python (manta_read_mesh()). */ has_mesh = manta_update_mesh_structures(mds->fluid, mmd, mesh_frame); } /* Read particles cache. */ if (with_liquid && with_particles) { + has_config = manta_read_config(mds->fluid, mmd, particles_frame); + if (!baking_data && !baking_particles && next_particles) { /* Update particle data from file is faster than via Python (manta_read_particles()). */ has_particles = manta_update_particle_structures(mds->fluid, mmd, particles_frame); @@ -3960,10 +3950,10 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Read noise and data cache */ if (with_smoke && with_noise) { + has_config = manta_read_config(mds->fluid, mmd, noise_frame); /* Only reallocate when just reading cache or when resuming during bake. */ - if ((!baking_noise || (baking_noise && resume_noise)) && - manta_read_config(mds->fluid, mmd, noise_frame) && + if ((!baking_noise || (baking_noise && resume_noise)) && has_config && manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } @@ -3981,8 +3971,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, copy_v3_v3_int(o_min, mds->res_min); copy_v3_v3_int(o_max, mds->res_max); copy_v3_v3_int(o_shift, mds->shift); - if (manta_read_config(mds->fluid, mmd, data_frame) && - manta_needs_realloc(mds->fluid, mmd)) { + if (has_config && manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_copy_fluid( mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift); } @@ -3998,10 +3987,11 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, } /* Read data cache only */ else { + has_config = manta_read_config(mds->fluid, mmd, data_frame); + if (with_smoke) { /* Read config and realloc fluid object if needed. */ - if (manta_read_config(mds->fluid, mmd, data_frame) && - manta_needs_realloc(mds->fluid, mmd)) { + if (has_config && manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } /* Read data cache */ @@ -4394,7 +4384,7 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *mds, ViewLayer *v * returns fluid density or -1.0f if outside domain. */ float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3]) { - FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + FluidModifierData *mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); zero_v3(velocity); if (mmd && (mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain && mmd->domain->fluid) { @@ -4501,11 +4491,11 @@ void BKE_fluid_particle_system_create(struct Main *bmain, BLI_addtail(&ob->particlesystem, psys); /* add modifier */ - pmmd = (ParticleSystemModifierData *)modifier_new(eModifierType_ParticleSystem); + pmmd = (ParticleSystemModifierData *)BKE_modifier_new(eModifierType_ParticleSystem); BLI_strncpy(pmmd->modifier.name, psys_name, sizeof(pmmd->modifier.name)); pmmd->psys = psys; BLI_addtail(&ob->modifiers, pmmd); - modifier_unique_name(&ob->modifiers, (ModifierData *)pmmd); + BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)pmmd); } void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_type) @@ -4519,7 +4509,7 @@ void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_typ /* clear modifier */ pmmd = psys_get_modifier(ob, psys); BLI_remlink(&ob->modifiers, pmmd); - modifier_free((ModifierData *)pmmd); + BKE_modifier_free((ModifierData *)pmmd); /* clear particle system */ BLI_remlink(&ob->particlesystem, psys); @@ -4952,7 +4942,7 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd) #endif char cache_name[64]; BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name); - modifier_path_init( + BKE_modifier_path_init( mmd->domain->cache_directory, sizeof(mmd->domain->cache_directory), cache_name); /* time options */ diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c new file mode 100644 index 00000000000..8299943cc49 --- /dev/null +++ b/source/blender/blenkernel/intern/gpencil_curve.c @@ -0,0 +1,450 @@ +/* + * 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) 2008, Blender Foundation + * This is a new part of Blender + */ + +/** \file + * \ingroup bke + */ + +#include <math.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "CLG_log.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math_vector.h" + +#include "BLT_translation.h" + +#include "DNA_gpencil_types.h" + +#include "BKE_collection.h" +#include "BKE_curve.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_curve.h" +#include "BKE_gpencil_geom.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_object.h" + +#include "DEG_depsgraph_query.h" + +/* Helper: Check materials with same color. */ +static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat) +{ + Material *ma = NULL; + float color_cu[4]; + linearrgb_to_srgb_v3_v3(color_cu, color); + float hsv1[4]; + rgb_to_hsv_v(color_cu, hsv1); + hsv1[3] = color[3]; + + for (int i = 1; i <= ob_gp->totcol; i++) { + ma = BKE_object_material_get(ob_gp, i); + MaterialGPencilStyle *gp_style = ma->gp_style; + /* Check color with small tolerance (better in HSV). */ + float hsv2[4]; + rgb_to_hsv_v(gp_style->fill_rgba, hsv2); + hsv2[3] = gp_style->fill_rgba[3]; + if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) && + (compare_v4v4(hsv1, hsv2, 0.01f))) { + *r_mat = ma; + return i - 1; + } + } + + *r_mat = NULL; + return -1; +} + +/* Helper: Add gpencil material using curve material as base. */ +static Material *gpencil_add_from_curve_material(Main *bmain, + Object *ob_gp, + const float cu_color[4], + const bool gpencil_lines, + const bool fill, + int *r_idx) +{ + Material *mat_gp = BKE_gpencil_object_material_new( + bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx); + MaterialGPencilStyle *gp_style = mat_gp->gp_style; + + /* Stroke color. */ + if (gpencil_lines) { + ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f); + gp_style->flag |= GP_MATERIAL_STROKE_SHOW; + } + else { + linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color); + gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; + } + + /* Fill color. */ + linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color); + /* Fill is false if the original curve hasn't material assigned, so enable it. */ + if (fill) { + gp_style->flag |= GP_MATERIAL_FILL_SHOW; + } + + /* Check at least one is enabled. */ + if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) && + ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) { + gp_style->flag |= GP_MATERIAL_STROKE_SHOW; + } + + return mat_gp; +} + +/* Helper: Create new stroke section. */ +static void gpencil_add_new_points(bGPDstroke *gps, + float *coord_array, + float pressure, + int init, + int totpoints, + const float init_co[3], + bool last) +{ + for (int i = 0; i < totpoints; i++) { + bGPDspoint *pt = &gps->points[i + init]; + copy_v3_v3(&pt->x, &coord_array[3 * i]); + /* Be sure the last point is not on top of the first point of the curve or + * the close of the stroke will produce glitches. */ + if ((last) && (i > 0) && (i == totpoints - 1)) { + float dist = len_v3v3(init_co, &pt->x); + if (dist < 0.1f) { + /* Interpolate between previous point and current to back slightly. */ + bGPDspoint *pt_prev = &gps->points[i + init - 1]; + interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f); + } + } + + pt->pressure = pressure; + pt->strength = 1.0f; + } +} + +/* Helper: Get the first collection that includes the object. */ +static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob) +{ + Collection *mycol = NULL; + FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + if ((mycol == NULL) && (cob->ob == ob)) { + mycol = collection; + } + } + } + FOREACH_SCENE_COLLECTION_END; + + return mycol; +} + +/* Helper: Convert one spline to grease pencil stroke. */ +static void gpencil_convert_spline(Main *bmain, + Object *ob_gp, + Object *ob_cu, + const bool gpencil_lines, + const bool only_stroke, + bGPDframe *gpf, + Nurb *nu) +{ + Curve *cu = (Curve *)ob_cu->data; + bool cyclic = true; + + /* Create Stroke. */ + bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); + gps->thickness = 10.0f; + gps->fill_opacity_fac = 1.0f; + gps->hardeness = 1.0f; + gps->uv_scale = 1.0f; + + ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f); + ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND); + gps->inittime = 0.0f; + + gps->flag &= ~GP_STROKE_SELECT; + gps->flag |= GP_STROKE_3DSPACE; + + gps->mat_nr = 0; + /* Count total points + * The total of points must consider that last point of each segment is equal to the first + * point of next segment. + */ + int totpoints = 0; + int segments = 0; + int resolu = nu->resolu + 1; + segments = nu->pntsu; + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { + segments--; + cyclic = false; + } + totpoints = (resolu * segments) - (segments - 1); + + /* Materials + * Notice: The color of the material is the color of viewport and not the final shader color. + */ + Material *mat_gp = NULL; + bool fill = true; + /* Check if grease pencil has a material with same color.*/ + float color[4]; + if ((cu->mat) && (*cu->mat)) { + Material *mat_cu = *cu->mat; + copy_v4_v4(color, &mat_cu->r); + } + else { + /* Gray (unassigned from SVG add-on) */ + zero_v4(color); + add_v3_fl(color, 0.6f); + color[3] = 1.0f; + fill = false; + } + + /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and + * there is only one color, the stroke must not be closed, fill to false and use for + * stroke the fill color. + */ + bool do_stroke = false; + if (ob_cu->totcol == 1) { + Material *ma_stroke = BKE_object_material_get(ob_cu, 1); + if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) { + do_stroke = true; + } + } + + int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp); + if ((ob_cu->totcol > 0) && (r_idx < 0)) { + Material *mat_curve = BKE_object_material_get(ob_cu, 1); + mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx); + + if ((mat_curve) && (mat_curve->gp_style != NULL)) { + MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style; + MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style; + + copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba); + gp_style_gp->fill_style = gp_style_cur->fill_style; + gp_style_gp->mix_factor = gp_style_cur->mix_factor; + } + + /* If object has more than 1 material, use second material for stroke color. */ + if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) { + mat_curve = BKE_object_material_get(ob_cu, 2); + if (mat_curve) { + linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); + mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; + } + } + else if ((only_stroke) || (do_stroke)) { + /* Also use the first color if the fill is none for stroke color. */ + if (ob_cu->totcol > 0) { + mat_curve = BKE_object_material_get(ob_cu, 1); + if (mat_curve) { + copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); + mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; + /* Set fill and stroke depending of curve type (3D or 2D). */ + if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) { + mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW; + mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW; + } + else { + mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; + mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW; + } + } + } + } + } + CLAMP_MIN(r_idx, 0); + + /* Assign material index to stroke. */ + gps->mat_nr = r_idx; + + /* Add stroke to frame.*/ + BLI_addtail(&gpf->strokes, gps); + + float *coord_array = NULL; + float init_co[3]; + + switch (nu->type) { + case CU_POLY: { + /* Allocate memory for storage points. */ + gps->totpoints = nu->pntsu; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + /* Increase thickness for this type. */ + gps->thickness = 10.0f; + + /* Get all curve points */ + for (int s = 0; s < gps->totpoints; s++) { + BPoint *bp = &nu->bp[s]; + bGPDspoint *pt = &gps->points[s]; + copy_v3_v3(&pt->x, bp->vec); + pt->pressure = bp->radius; + pt->strength = 1.0f; + } + break; + } + case CU_BEZIER: { + /* Allocate memory for storage points. */ + gps->totpoints = totpoints; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + + int init = 0; + resolu = nu->resolu + 1; + segments = nu->pntsu; + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { + segments--; + } + /* Get all interpolated curve points of Beziert */ + for (int s = 0; s < segments; s++) { + int inext = (s + 1) % nu->pntsu; + BezTriple *prevbezt = &nu->bezt[s]; + BezTriple *bezt = &nu->bezt[inext]; + bool last = (bool)(s == segments - 1); + + coord_array = MEM_callocN((size_t)3 * resolu * sizeof(float), __func__); + + for (int j = 0; j < 3; j++) { + BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], + prevbezt->vec[2][j], + bezt->vec[0][j], + bezt->vec[1][j], + coord_array + j, + resolu - 1, + 3 * sizeof(float)); + } + /* Save first point coordinates. */ + if (s == 0) { + copy_v3_v3(init_co, &coord_array[0]); + } + /* Add points to the stroke */ + gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last); + /* Free memory. */ + MEM_SAFE_FREE(coord_array); + + /* As the last point of segment is the first point of next segment, back one array + * element to avoid duplicated points on the same location. + */ + init += resolu - 1; + } + break; + } + case CU_NURBS: { + if (nu->pntsv == 1) { + + int nurb_points; + if (nu->flagu & CU_NURB_CYCLIC) { + resolu++; + nurb_points = nu->pntsu * resolu; + } + else { + nurb_points = (nu->pntsu - 1) * resolu; + } + /* Get all curve points. */ + coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__); + BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3])); + + /* Allocate memory for storage points. */ + gps->totpoints = nurb_points - 1; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + + /* Add points. */ + gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false); + + MEM_SAFE_FREE(coord_array); + } + break; + } + default: { + break; + } + } + /* Cyclic curve, close stroke. */ + if ((cyclic) && (!do_stroke)) { + BKE_gpencil_stroke_close(gps); + } + + /* Recalc fill geometry. */ + BKE_gpencil_stroke_geometry_update(gps); +} + +/* Convert a curve object to grease pencil stroke. + * + * \param bmain: Main thread pointer + * \param scene: Original scene. + * \param ob_gp: Grease pencil object to add strokes. + * \param ob_cu: Curve to convert. + * \param gpencil_lines: Use lines for strokes. + * \param use_collections: Create layers using collection names. + * \param only_stroke: The material must be only stroke without fill. + */ +void BKE_gpencil_convert_curve(Main *bmain, + Scene *scene, + Object *ob_gp, + Object *ob_cu, + const bool gpencil_lines, + const bool use_collections, + const bool only_stroke) +{ + if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { + return; + } + + Curve *cu = (Curve *)ob_cu->data; + bGPdata *gpd = (bGPdata *)ob_gp->data; + bGPDlayer *gpl = NULL; + + /* If the curve is empty, cancel. */ + if (cu->nurb.first == NULL) { + return; + } + + /* Check if there is an active layer. */ + if (use_collections) { + Collection *collection = gpencil_get_parent_collection(scene, ob_cu); + if (collection != NULL) { + gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true); + } + } + } + + if (gpl == NULL) { + gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + } + } + + /* Check if there is an active frame and add if needed. */ + bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY); + + /* Read all splines of the curve and create a stroke for each. */ + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { + gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu); + } + + /* Tag for recalculation */ + DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 413e28c431b..d200e4e3a15 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -35,18 +35,12 @@ #include "BLI_math_vector.h" #include "BLI_polyfill_2d.h" -#include "BLT_translation.h" - #include "DNA_gpencil_types.h" #include "DNA_meshdata_types.h" -#include "BKE_collection.h" -#include "BKE_curve.h" #include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_main.h" -#include "BKE_material.h" #include "BKE_object.h" #include "DEG_depsgraph_query.h" @@ -1586,404 +1580,6 @@ void BKE_gpencil_stroke_merge_distance(bGPDframe *gpf, BKE_gpencil_stroke_geometry_update(gps); } -/* Helper: Check materials with same color. */ -static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat) -{ - Material *ma = NULL; - float color_cu[4]; - linearrgb_to_srgb_v3_v3(color_cu, color); - float hsv1[4]; - rgb_to_hsv_v(color_cu, hsv1); - hsv1[3] = color[3]; - - for (int i = 1; i <= ob_gp->totcol; i++) { - ma = BKE_object_material_get(ob_gp, i); - MaterialGPencilStyle *gp_style = ma->gp_style; - /* Check color with small tolerance (better in HSV). */ - float hsv2[4]; - rgb_to_hsv_v(gp_style->fill_rgba, hsv2); - hsv2[3] = gp_style->fill_rgba[3]; - if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) && - (compare_v4v4(hsv1, hsv2, 0.01f))) { - *r_mat = ma; - return i - 1; - } - } - - *r_mat = NULL; - return -1; -} - -/* Helper: Add gpencil material using curve material as base. */ -static Material *gpencil_add_from_curve_material(Main *bmain, - Object *ob_gp, - const float cu_color[4], - const bool gpencil_lines, - const bool fill, - int *r_idx) -{ - Material *mat_gp = BKE_gpencil_object_material_new( - bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx); - MaterialGPencilStyle *gp_style = mat_gp->gp_style; - - /* Stroke color. */ - if (gpencil_lines) { - ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f); - gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - } - else { - linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color); - gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; - } - - /* Fill color. */ - linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color); - /* Fill is false if the original curve hasn't material assigned, so enable it. */ - if (fill) { - gp_style->flag |= GP_MATERIAL_FILL_SHOW; - } - - /* Check at least one is enabled. */ - if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) && - ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) { - gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - } - - return mat_gp; -} - -/* Helper: Create new stroke section. */ -static void gpencil_add_new_points(bGPDstroke *gps, - float *coord_array, - float pressure, - int init, - int totpoints, - const float init_co[3], - bool last) -{ - for (int i = 0; i < totpoints; i++) { - bGPDspoint *pt = &gps->points[i + init]; - copy_v3_v3(&pt->x, &coord_array[3 * i]); - /* Be sure the last point is not on top of the first point of the curve or - * the close of the stroke will produce glitches. */ - if ((last) && (i > 0) && (i == totpoints - 1)) { - float dist = len_v3v3(init_co, &pt->x); - if (dist < 0.1f) { - /* Interpolate between previous point and current to back slightly. */ - bGPDspoint *pt_prev = &gps->points[i + init - 1]; - interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f); - } - } - - pt->pressure = pressure; - pt->strength = 1.0f; - } -} - -/* Helper: Get the first collection that includes the object. */ -static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob) -{ - Collection *mycol = NULL; - FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - if ((mycol == NULL) && (cob->ob == ob)) { - mycol = collection; - } - } - } - FOREACH_SCENE_COLLECTION_END; - - return mycol; -} - -/* Helper: Convert one spline to grease pencil stroke. */ -static void gpencil_convert_spline(Main *bmain, - Object *ob_gp, - Object *ob_cu, - const bool gpencil_lines, - const bool only_stroke, - bGPDframe *gpf, - Nurb *nu) -{ - Curve *cu = (Curve *)ob_cu->data; - bool cyclic = true; - - /* Create Stroke. */ - bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); - gps->thickness = 10.0f; - gps->fill_opacity_fac = 1.0f; - gps->hardeness = 1.0f; - gps->uv_scale = 1.0f; - - ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f); - ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND); - gps->inittime = 0.0f; - - gps->flag &= ~GP_STROKE_SELECT; - gps->flag |= GP_STROKE_3DSPACE; - - gps->mat_nr = 0; - /* Count total points - * The total of points must consider that last point of each segment is equal to the first - * point of next segment. - */ - int totpoints = 0; - int segments = 0; - int resolu = nu->resolu + 1; - segments = nu->pntsu; - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - segments--; - cyclic = false; - } - totpoints = (resolu * segments) - (segments - 1); - - /* Materials - * Notice: The color of the material is the color of viewport and not the final shader color. - */ - Material *mat_gp = NULL; - bool fill = true; - /* Check if grease pencil has a material with same color.*/ - float color[4]; - if ((cu->mat) && (*cu->mat)) { - Material *mat_cu = *cu->mat; - copy_v4_v4(color, &mat_cu->r); - } - else { - /* Gray (unassigned from SVG add-on) */ - zero_v4(color); - add_v3_fl(color, 0.6f); - color[3] = 1.0f; - fill = false; - } - - /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and - * there is only one color, the stroke must not be closed, fill to false and use for - * stroke the fill color. - */ - bool do_stroke = false; - if (ob_cu->totcol == 1) { - Material *ma_stroke = BKE_object_material_get(ob_cu, 1); - if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) { - do_stroke = true; - } - } - - int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp); - if ((ob_cu->totcol > 0) && (r_idx < 0)) { - Material *mat_curve = BKE_object_material_get(ob_cu, 1); - mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx); - - if ((mat_curve) && (mat_curve->gp_style != NULL)) { - MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style; - MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style; - - copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba); - gp_style_gp->fill_style = gp_style_cur->fill_style; - gp_style_gp->mix_factor = gp_style_cur->mix_factor; - } - - /* If object has more than 1 material, use second material for stroke color. */ - if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) { - mat_curve = BKE_object_material_get(ob_cu, 2); - if (mat_curve) { - linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); - mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; - } - } - else if ((only_stroke) || (do_stroke)) { - /* Also use the first color if the fill is none for stroke color. */ - if (ob_cu->totcol > 0) { - mat_curve = BKE_object_material_get(ob_cu, 1); - if (mat_curve) { - copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); - mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; - /* Set fill and stroke depending of curve type (3D or 2D). */ - if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) { - mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW; - } - else { - mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; - mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW; - } - } - } - } - } - CLAMP_MIN(r_idx, 0); - - /* Assign material index to stroke. */ - gps->mat_nr = r_idx; - - /* Add stroke to frame.*/ - BLI_addtail(&gpf->strokes, gps); - - float *coord_array = NULL; - float init_co[3]; - - switch (nu->type) { - case CU_POLY: { - /* Allocate memory for storage points. */ - gps->totpoints = nu->pntsu; - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - /* Increase thickness for this type. */ - gps->thickness = 10.0f; - - /* Get all curve points */ - for (int s = 0; s < gps->totpoints; s++) { - BPoint *bp = &nu->bp[s]; - bGPDspoint *pt = &gps->points[s]; - copy_v3_v3(&pt->x, bp->vec); - pt->pressure = bp->radius; - pt->strength = 1.0f; - } - break; - } - case CU_BEZIER: { - /* Allocate memory for storage points. */ - gps->totpoints = totpoints; - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - - int init = 0; - resolu = nu->resolu + 1; - segments = nu->pntsu; - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - segments--; - } - /* Get all interpolated curve points of Beziert */ - for (int s = 0; s < segments; s++) { - int inext = (s + 1) % nu->pntsu; - BezTriple *prevbezt = &nu->bezt[s]; - BezTriple *bezt = &nu->bezt[inext]; - bool last = (bool)(s == segments - 1); - - coord_array = MEM_callocN((size_t)3 * resolu * sizeof(float), __func__); - - for (int j = 0; j < 3; j++) { - BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], - prevbezt->vec[2][j], - bezt->vec[0][j], - bezt->vec[1][j], - coord_array + j, - resolu - 1, - 3 * sizeof(float)); - } - /* Save first point coordinates. */ - if (s == 0) { - copy_v3_v3(init_co, &coord_array[0]); - } - /* Add points to the stroke */ - gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last); - /* Free memory. */ - MEM_SAFE_FREE(coord_array); - - /* As the last point of segment is the first point of next segment, back one array - * element to avoid duplicated points on the same location. - */ - init += resolu - 1; - } - break; - } - case CU_NURBS: { - if (nu->pntsv == 1) { - - int nurb_points; - if (nu->flagu & CU_NURB_CYCLIC) { - resolu++; - nurb_points = nu->pntsu * resolu; - } - else { - nurb_points = (nu->pntsu - 1) * resolu; - } - /* Get all curve points. */ - coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__); - BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3])); - - /* Allocate memory for storage points. */ - gps->totpoints = nurb_points - 1; - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - - /* Add points. */ - gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false); - - MEM_SAFE_FREE(coord_array); - } - break; - } - default: { - break; - } - } - /* Cyclic curve, close stroke. */ - if ((cyclic) && (!do_stroke)) { - BKE_gpencil_stroke_close(gps); - } - - /* Recalc fill geometry. */ - BKE_gpencil_stroke_geometry_update(gps); -} - -/* Convert a curve object to grease pencil stroke. - * - * \param bmain: Main thread pointer - * \param scene: Original scene. - * \param ob_gp: Grease pencil object to add strokes. - * \param ob_cu: Curve to convert. - * \param gpencil_lines: Use lines for strokes. - * \param use_collections: Create layers using collection names. - * \param only_stroke: The material must be only stroke without fill. - */ -void BKE_gpencil_convert_curve(Main *bmain, - Scene *scene, - Object *ob_gp, - Object *ob_cu, - const bool gpencil_lines, - const bool use_collections, - const bool only_stroke) -{ - if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { - return; - } - - Curve *cu = (Curve *)ob_cu->data; - bGPdata *gpd = (bGPdata *)ob_gp->data; - bGPDlayer *gpl = NULL; - - /* If the curve is empty, cancel. */ - if (cu->nurb.first == NULL) { - return; - } - - /* Check if there is an active layer. */ - if (use_collections) { - Collection *collection = gpencil_get_parent_collection(scene, ob_cu); - if (collection != NULL) { - gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2); - if (gpl == NULL) { - gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true); - } - } - } - - if (gpl == NULL) { - gpl = BKE_gpencil_layer_active_get(gpd); - if (gpl == NULL) { - gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); - } - } - - /* Check if there is an active frame and add if needed. */ - bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY); - - /* Read all splines of the curve and create a stroke for each. */ - LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { - gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu); - } - - /* Tag for recalculation */ - DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); -} - /* Apply Transforms */ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4]) { diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index b732d9cdd4c..b889b91e366 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -318,7 +318,7 @@ bool BKE_gpencil_has_geometry_modifiers(Object *ob) { GpencilModifierData *md; for (md = ob->greasepencil_modifiers.first; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti && mti->generateStrokes) { return true; @@ -332,7 +332,7 @@ bool BKE_gpencil_has_time_modifiers(Object *ob) { GpencilModifierData *md; for (md = ob->greasepencil_modifiers.first; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti && mti->remapTime) { return true; @@ -369,7 +369,7 @@ static int gpencil_time_modifier( for (md = ob->greasepencil_modifiers.first; md; md = md->next) { if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { continue; @@ -421,7 +421,7 @@ void BKE_gpencil_modifier_init(void) GpencilModifierData *BKE_gpencil_modifier_new(int type) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(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 */ @@ -456,7 +456,7 @@ static void modifier_free_data_id_us_cb(void *UNUSED(userData), void BKE_gpencil_modifier_free_ex(GpencilModifierData *md, const int flag) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { if (mti->foreachIDLink) { @@ -487,7 +487,7 @@ void BKE_gpencil_modifier_free(GpencilModifierData *md) bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData *gmd) { if (modifiers && gmd) { - const GpencilModifierTypeInfo *gmti = BKE_gpencil_modifierType_getInfo(gmd->type); + const GpencilModifierTypeInfo *gmti = BKE_gpencil_modifier_get_info(gmd->type); return BLI_uniquename(modifiers, gmd, DATA_(gmti->name), @@ -498,14 +498,14 @@ bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData * return false; } -bool BKE_gpencil_modifier_dependsOnTime(GpencilModifierData *md) +bool BKE_gpencil_modifier_depends_ontime(GpencilModifierData *md) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); return mti->dependsOnTime && mti->dependsOnTime(md); } -const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type) +const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType type) { /* type unsigned, no need to check < 0 */ if (type < NUM_GREASEPENCIL_MODIFIER_TYPES && modifier_gpencil_types[type]->name[0] != '\0') { @@ -516,10 +516,10 @@ const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierT } } -void BKE_gpencil_modifier_copyData_generic(const GpencilModifierData *md_src, +void BKE_gpencil_modifier_copydata_generic(const GpencilModifierData *md_src, GpencilModifierData *md_dst) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md_src->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md_src->type); /* md_dst may have already be fully initialized with some extra allocated data, * we need to free it now to avoid memleak. */ @@ -545,11 +545,11 @@ static void gpencil_modifier_copy_data_id_us_cb(void *UNUSED(userData), } } -void BKE_gpencil_modifier_copyData_ex(GpencilModifierData *md, +void BKE_gpencil_modifier_copydata_ex(GpencilModifierData *md, GpencilModifierData *target, const int flag) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); target->mode = md->mode; target->flag = md->flag; @@ -569,12 +569,12 @@ void BKE_gpencil_modifier_copyData_ex(GpencilModifierData *md, } } -void BKE_gpencil_modifier_copyData(GpencilModifierData *md, GpencilModifierData *target) +void BKE_gpencil_modifier_copydata(GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_ex(md, target, 0); + BKE_gpencil_modifier_copydata_ex(md, target, 0); } -GpencilModifierData *BKE_gpencil_modifiers_findByType(Object *ob, GpencilModifierType type) +GpencilModifierData *BKE_gpencil_modifiers_findby_type(Object *ob, GpencilModifierType type) { GpencilModifierData *md = ob->greasepencil_modifiers.first; @@ -587,12 +587,12 @@ GpencilModifierData *BKE_gpencil_modifiers_findByType(Object *ob, GpencilModifie return md; } -void BKE_gpencil_modifiers_foreachIDLink(Object *ob, GreasePencilIDWalkFunc walk, void *userData) +void BKE_gpencil_modifiers_foreach_ID_link(Object *ob, GreasePencilIDWalkFunc walk, void *userData) { GpencilModifierData *md = ob->greasepencil_modifiers.first; for (; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->foreachIDLink) { mti->foreachIDLink(md, ob, walk, userData); @@ -605,12 +605,14 @@ void BKE_gpencil_modifiers_foreachIDLink(Object *ob, GreasePencilIDWalkFunc walk } } -void BKE_gpencil_modifiers_foreachTexLink(Object *ob, GreasePencilTexWalkFunc walk, void *userData) +void BKE_gpencil_modifiers_foreach_tex_link(Object *ob, + GreasePencilTexWalkFunc walk, + void *userData) { GpencilModifierData *md = ob->greasepencil_modifiers.first; for (; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->foreachTexLink) { mti->foreachTexLink(md, ob, walk, userData); @@ -618,7 +620,7 @@ void BKE_gpencil_modifiers_foreachTexLink(Object *ob, GreasePencilTexWalkFunc wa } } -GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *name) +GpencilModifierData *BKE_gpencil_modifiers_findby_name(Object *ob, const char *name) { return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name)); } @@ -881,7 +883,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) { if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { continue; diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 5cdb7761540..808c0347a37 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -247,12 +247,65 @@ Hair *BKE_hair_copy_for_eval(Hair *hair_src, bool reference) return result; } -static Hair *hair_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph), - struct Scene *UNUSED(scene), - Object *UNUSED(object), +static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph, + struct Scene *scene, + Object *object, Hair *hair_input) { - return hair_input; + Hair *hair = hair_input; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; + const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); + + /* Evaluate modifiers. */ + for (; md; md = md->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if ((mti->type == eModifierTypeType_OnlyDeform) && + (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { + /* Ensure we are not modifying the input. */ + if (hair == hair_input) { + hair = BKE_hair_copy_for_eval(hair, true); + } + + /* Ensure we are not overwriting referenced data. */ + CustomData_duplicate_referenced_layer(&hair->pdata, CD_LOCATION, hair->totpoint); + BKE_hair_update_customdata_pointers(hair); + + /* Created deformed coordinates array on demand. */ + mti->deformVerts(md, &mectx, NULL, hair->co, hair->totpoint); + } + else if (mti->modifyHair) { + /* Ensure we are not modifying the input. */ + if (hair == hair_input) { + hair = BKE_hair_copy_for_eval(hair, true); + } + + Hair *hair_next = mti->modifyHair(md, &mectx, hair); + + if (hair_next && hair_next != hair) { + /* If the modifier returned a new hair, release the old one. */ + if (hair != hair_input) { + BKE_id_free(NULL, hair); + } + hair = hair_next; + } + } + } + + return hair; } void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object) diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c index 5a6e8f532c9..fcd3bc9c5b4 100644 --- a/source/blender/blenkernel/intern/idtype.c +++ b/source/blender/blenkernel/intern/idtype.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -92,6 +92,7 @@ static void id_type_init(void) INIT_TYPE(ID_HA); INIT_TYPE(ID_PT); INIT_TYPE(ID_VO); + INIT_TYPE(ID_SIM); /* Special naughty boy... */ BLI_assert(IDType_ID_LINK_PLACEHOLDER.main_listbase_index == INDEX_ID_NULL); @@ -251,6 +252,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode) CASE_IDFILTER(PT); CASE_IDFILTER(LP); CASE_IDFILTER(SCE); + CASE_IDFILTER(SIM); CASE_IDFILTER(SPK); CASE_IDFILTER(SO); CASE_IDFILTER(TE); @@ -302,6 +304,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter) CASE_IDFILTER(PT); CASE_IDFILTER(LP); CASE_IDFILTER(SCE); + CASE_IDFILTER(SIM); CASE_IDFILTER(SPK); CASE_IDFILTER(SO); CASE_IDFILTER(TE); @@ -356,6 +359,7 @@ int BKE_idtype_idcode_to_index(const short idcode) CASE_IDINDEX(LP); CASE_IDINDEX(SCE); CASE_IDINDEX(SCR); + CASE_IDINDEX(SIM); CASE_IDINDEX(SPK); CASE_IDINDEX(SO); CASE_IDINDEX(TE); @@ -417,6 +421,7 @@ short BKE_idtype_idcode_from_index(const int index) CASE_IDCODE(LP); CASE_IDCODE(SCE); CASE_IDCODE(SCR); + CASE_IDCODE(SIM); CASE_IDCODE(SPK); CASE_IDCODE(SO); CASE_IDCODE(TE); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ee1bd5afa61..f5b28355d85 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -571,7 +571,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number) return NULL; } -ImageTile *BKE_image_get_tile_from_iuser(Image *ima, ImageUser *iuser) +ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser) { return BKE_image_get_tile(ima, (iuser && iuser->tile) ? iuser->tile : 1001); } @@ -4796,7 +4796,7 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_entry, return ibuf; } -BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser) +BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser) { if (ima == NULL) { return false; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index b0b88a13a75..12c1cf6bafa 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -60,6 +60,7 @@ #include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_ipo.h" diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index d371af93bb7..e7a2421a625 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -52,6 +52,7 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -121,6 +122,12 @@ static void lattice_free_data(ID *id) } } +static void lattice_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Lattice *lattice = (Lattice *)id; + BKE_LIB_FOREACHID_PROCESS(data, lattice->key, IDWALK_CB_USER); +} + IDTypeInfo IDType_ID_LT = { .id_code = ID_LT, .id_filter = FILTER_ID_LT, @@ -135,6 +142,7 @@ IDTypeInfo IDType_ID_LT = { .copy_data = lattice_copy_data, .free_data = lattice_free_data, .make_local = NULL, + .foreach_id = lattice_foreach_id, }; int BKE_lattice_index_from_uvw(Lattice *lt, const int u, const int v, const int w) @@ -1119,7 +1127,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec * otherwise we get already-modified coordinates. */ Object *ob_orig = DEG_get_original_object(ob); VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); float(*vert_coords)[3] = NULL; int numVerts, editmode = (lt->editlatt != NULL); const ModifierEvalContext mectx = {depsgraph, ob, 0}; @@ -1132,9 +1140,9 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec } for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!(mti->flags & eModifierTypeFlag_AcceptsLattice)) { + if (!(mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { continue; } if (!(md->mode & eModifierMode_Realtime)) { diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index d1337620de8..fe25016344e 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -36,38 +36,12 @@ #include "MEM_guardedalloc.h" /* all types are needed here, in order to do memory operations */ +#include "DNA_ID.h" #include "DNA_anim_types.h" -#include "DNA_armature_types.h" -#include "DNA_brush_types.h" -#include "DNA_cachefile_types.h" -#include "DNA_camera_types.h" -#include "DNA_collection_types.h" #include "DNA_gpencil_types.h" -#include "DNA_hair_types.h" -#include "DNA_ipo_types.h" #include "DNA_key_types.h" -#include "DNA_lattice_types.h" -#include "DNA_light_types.h" -#include "DNA_lightprobe_types.h" -#include "DNA_linestyle_types.h" -#include "DNA_mask_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meta_types.h" -#include "DNA_movieclip_types.h" #include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_pointcloud_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_sound_types.h" -#include "DNA_speaker_types.h" -#include "DNA_text_types.h" -#include "DNA_vfont_types.h" -#include "DNA_volume_types.h" -#include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" -#include "DNA_world_types.h" #include "BLI_utildefines.h" @@ -80,50 +54,21 @@ #include "BLT_translation.h" -#include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_armature.h" #include "BKE_bpath.h" -#include "BKE_brush.h" -#include "BKE_cachefile.h" -#include "BKE_camera.h" -#include "BKE_collection.h" #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_font.h" #include "BKE_global.h" #include "BKE_gpencil.h" -#include "BKE_hair.h" #include "BKE_idprop.h" #include "BKE_idtype.h" -#include "BKE_image.h" #include "BKE_key.h" -#include "BKE_lattice.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_lib_remap.h" -#include "BKE_light.h" -#include "BKE_lightprobe.h" -#include "BKE_linestyle.h" #include "BKE_main.h" -#include "BKE_mask.h" -#include "BKE_material.h" -#include "BKE_mball.h" -#include "BKE_mesh.h" -#include "BKE_movieclip.h" #include "BKE_node.h" -#include "BKE_object.h" -#include "BKE_paint.h" -#include "BKE_particle.h" -#include "BKE_pointcloud.h" #include "BKE_rigidbody.h" -#include "BKE_scene.h" -#include "BKE_sound.h" -#include "BKE_speaker.h" -#include "BKE_text.h" -#include "BKE_texture.h" -#include "BKE_volume.h" -#include "BKE_world.h" #include "DEG_depsgraph.h" @@ -663,7 +608,7 @@ static void id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_full_id) * Does a mere memory swap over the whole IDs data (including type-specific memory). * \note Most internal ID data itself is not swapped (only IDProperties are). * - * \param bmain May be NULL, in which case there will be no remapping of internal pointers to + * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to * itself. */ void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b) @@ -675,7 +620,7 @@ void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b) * Does a mere memory swap over the whole IDs data (including type-specific memory). * \note All internal ID data itself is also swapped. * - * \param bmain May be NULL, in which case there will be no remapping of internal pointers to + * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to * itself. */ void BKE_lib_id_swap_full(Main *bmain, ID *id_a, ID *id_b) @@ -1260,7 +1205,7 @@ ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *nam * * \note All other IDs beside given one are assumed already properly sorted in the list. * - * \param id_sorting_hint Ignored if NULL. Otherwise, used to check if we can insert \a id + * \param id_sorting_hint: Ignored if NULL. Otherwise, used to check if we can insert \a id * immediately before or after that pointer. It must always be into given \a lb list. */ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index 245e4f43452..fdee5500fbd 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -23,80 +23,20 @@ #include "MEM_guardedalloc.h" /* all types are needed here, in order to do memory operations */ -#include "DNA_armature_types.h" -#include "DNA_brush_types.h" -#include "DNA_cachefile_types.h" -#include "DNA_camera_types.h" -#include "DNA_collection_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_ipo_types.h" -#include "DNA_key_types.h" -#include "DNA_lattice_types.h" -#include "DNA_light_types.h" -#include "DNA_lightprobe_types.h" -#include "DNA_linestyle_types.h" -#include "DNA_mask_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meta_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_sound_types.h" -#include "DNA_speaker_types.h" -#include "DNA_text_types.h" -#include "DNA_vfont_types.h" -#include "DNA_windowmanager_types.h" -#include "DNA_workspace_types.h" -#include "DNA_world_types.h" +#include "DNA_ID.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" -#include "BKE_action.h" #include "BKE_anim_data.h" -#include "BKE_armature.h" -#include "BKE_brush.h" -#include "BKE_cachefile.h" -#include "BKE_camera.h" -#include "BKE_collection.h" -#include "BKE_curve.h" -#include "BKE_font.h" -#include "BKE_gpencil.h" #include "BKE_idprop.h" #include "BKE_idtype.h" -#include "BKE_image.h" -#include "BKE_ipo.h" -#include "BKE_key.h" -#include "BKE_lattice.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_remap.h" #include "BKE_library.h" -#include "BKE_light.h" -#include "BKE_lightprobe.h" -#include "BKE_linestyle.h" #include "BKE_main.h" -#include "BKE_mask.h" -#include "BKE_material.h" -#include "BKE_mball.h" -#include "BKE_mesh.h" -#include "BKE_movieclip.h" -#include "BKE_node.h" -#include "BKE_object.h" -#include "BKE_paint.h" -#include "BKE_particle.h" -#include "BKE_scene.h" -#include "BKE_screen.h" -#include "BKE_sound.h" -#include "BKE_speaker.h" -#include "BKE_text.h" -#include "BKE_texture.h" -#include "BKE_workspace.h" -#include "BKE_world.h" #include "lib_intern.h" diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index 2ca03fd5d7e..8c29209f29d 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -49,6 +49,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" @@ -67,9 +68,10 @@ #include "BKE_anim_data.h" #include "BKE_collection.h" #include "BKE_constraint.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil_modifier.h" #include "BKE_idprop.h" +#include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_main.h" @@ -164,6 +166,38 @@ typedef struct LibraryForeachIDData { BLI_LINKSTACK_DECLARE(ids_todo, ID *); } LibraryForeachIDData; +bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag) +{ + if (!(data->status & IDWALK_STOP)) { + const int flag = data->flag; + ID *old_id = *id_pp; + const int callback_return = data->callback(&(struct LibraryIDLinkCallbackData){ + .user_data = data->user_data, + .id_owner = data->owner_id, + .id_self = data->self_id, + .id_pointer = id_pp, + .cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear)}); + if (flag & IDWALK_READONLY) { + BLI_assert(*(id_pp) == old_id); + } + if (old_id && (flag & IDWALK_RECURSE)) { + if (BLI_gset_add((data)->ids_handled, old_id)) { + if (!(callback_return & IDWALK_RET_STOP_RECURSION)) { + BLI_LINKSTACK_PUSH(data->ids_todo, old_id); + } + } + } + if (callback_return & IDWALK_RET_STOP_ITER) { + data->status |= IDWALK_STOP; + return false; + } + return true; + } + else { + return false; + } +} + static void library_foreach_ID_link(Main *bmain, ID *id_owner, ID *id, @@ -172,14 +206,12 @@ static void library_foreach_ID_link(Main *bmain, int flag, LibraryForeachIDData *inherit_data); -static void library_foreach_idpropertiesForeachIDLink(IDProperty *id_prop, void *user_data) +void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void *user_data) { BLI_assert(id_prop->type == IDP_ID); LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - FOREACH_CALLBACK_INVOKE_ID(data, id_prop->data.pointer, IDWALK_CB_USER); - - FOREACH_FINALIZE_VOID; + BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, IDWALK_CB_USER); } static void library_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw), @@ -305,18 +337,6 @@ static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) FOREACH_FINALIZE_VOID; } -static void library_foreach_bone(LibraryForeachIDData *data, Bone *bone) -{ - IDP_foreach_property( - bone->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, data); - - LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) { - library_foreach_bone(data, curbone); - } - - FOREACH_FINALIZE_VOID; -} - static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb) { LISTBASE_FOREACH (LayerCollection *, lc, lb) { @@ -499,17 +519,21 @@ static void library_foreach_screen_area(LibraryForeachIDData *data, ScrArea *are FOREACH_FINALIZE_VOID; } -static void library_foreach_ID_as_subdata_link(ID **id_pp, - LibraryIDLinkCallback callback, - void *user_data, - int flag, - LibraryForeachIDData *data) +bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp) { /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */ ID *id = *id_pp; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pp, IDWALK_CB_EMBEDDED); + const int flag = data->flag; + + if (!BKE_lib_query_foreachid_process(data, id_pp, IDWALK_CB_EMBEDDED)) { + return false; + } BLI_assert(id == *id_pp); + if (id == NULL) { + return true; + } + if (flag & IDWALK_IGNORE_EMBEDDED_ID) { /* Do Nothing. */ } @@ -523,10 +547,11 @@ static void library_foreach_ID_as_subdata_link(ID **id_pp, } } else { - library_foreach_ID_link(data->bmain, data->owner_id, id, callback, user_data, flag, data); + library_foreach_ID_link( + data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data); } - FOREACH_FINALIZE_VOID; + return true; } static void library_foreach_ID_link(Main *bmain, @@ -613,18 +638,33 @@ static void library_foreach_ID_link(Main *bmain, IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE); } - IDP_foreach_property( - id->properties, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); + IDP_foreach_property(id->properties, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + &data); AnimData *adt = BKE_animdata_from_id(id); if (adt) { library_foreach_animationData(&data, adt); } + const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); + + /* Note: this is temp logic until all code has been ported to IDTypeInfo... */ + if (id_type->foreach_id != NULL) { + id_type->foreach_id(id, &data); + + if (data.status & IDWALK_STOP) { + break; + } + else { + continue; + } + } + switch ((ID_Type)GS(id->name)) { case ID_LI: { - Library *lib = (Library *)id; - CALLBACK_INVOKE(lib->parent, IDWALK_CB_NEVER_SELF); + BLI_assert(0); break; } case ID_SCE: { @@ -639,8 +679,7 @@ static void library_foreach_ID_link(Main *bmain, CALLBACK_INVOKE(scene->r.bake.cage_object, IDWALK_CB_NOP); if (scene->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&scene->nodetree, callback, user_data, flag, &data); + BKE_library_foreach_ID_embedded(&data, (ID **)&scene->nodetree); } if (scene->ed) { Sequence *seq; @@ -650,8 +689,10 @@ static void library_foreach_ID_link(Main *bmain, CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER); CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER); CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER); - IDP_foreach_property( - seq->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); + IDP_foreach_property(seq->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + &data); LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER); } @@ -805,8 +846,10 @@ static void library_foreach_ID_link(Main *bmain, if (object->pose) { data.cb_flag |= proxy_cb_flag; LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - IDP_foreach_property( - pchan->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); + IDP_foreach_property(pchan->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + &data); CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER); BKE_constraints_id_loop( &pchan->constraints, library_foreach_constraintObjectLooper, &data); @@ -825,12 +868,12 @@ static void library_foreach_ID_link(Main *bmain, } } - modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data); - BKE_gpencil_modifiers_foreachIDLink( + BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, &data); + BKE_gpencil_modifiers_foreach_ID_link( object, library_foreach_gpencil_modifiersForeachIDLink, &data); BKE_constraints_id_loop( &object->constraints, library_foreach_constraintObjectLooper, &data); - BKE_shaderfx_foreachIDLink(object, library_foreach_shaderfxForeachIDLink, &data); + BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, &data); LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data); @@ -847,89 +890,42 @@ static void library_foreach_ID_link(Main *bmain, } case ID_AR: { - bArmature *arm = (bArmature *)id; - - LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { - library_foreach_bone(&data, bone); - } + BLI_assert(0); break; } case ID_ME: { - Mesh *mesh = (Mesh *)id; - CALLBACK_INVOKE(mesh->texcomesh, IDWALK_CB_NEVER_SELF); - CALLBACK_INVOKE(mesh->key, IDWALK_CB_USER); - for (i = 0; i < mesh->totcol; i++) { - CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER); - } + BLI_assert(0); break; } case ID_CU: { - Curve *curve = (Curve *)id; - CALLBACK_INVOKE(curve->bevobj, IDWALK_CB_NOP); - CALLBACK_INVOKE(curve->taperobj, IDWALK_CB_NOP); - CALLBACK_INVOKE(curve->textoncurve, IDWALK_CB_NOP); - CALLBACK_INVOKE(curve->key, IDWALK_CB_USER); - for (i = 0; i < curve->totcol; i++) { - CALLBACK_INVOKE(curve->mat[i], IDWALK_CB_USER); - } - CALLBACK_INVOKE(curve->vfont, IDWALK_CB_USER); - CALLBACK_INVOKE(curve->vfontb, IDWALK_CB_USER); - CALLBACK_INVOKE(curve->vfonti, IDWALK_CB_USER); - CALLBACK_INVOKE(curve->vfontbi, IDWALK_CB_USER); + BLI_assert(0); break; } case ID_MB: { - MetaBall *metaball = (MetaBall *)id; - for (i = 0; i < metaball->totcol; i++) { - CALLBACK_INVOKE(metaball->mat[i], IDWALK_CB_USER); - } + BLI_assert(0); break; } case ID_MA: { - Material *material = (Material *)id; - if (material->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&material->nodetree, callback, user_data, flag, &data); - } - if (material->texpaintslot != NULL) { - CALLBACK_INVOKE(material->texpaintslot->ima, IDWALK_CB_NOP); - } - if (material->gp_style != NULL) { - CALLBACK_INVOKE(material->gp_style->sima, IDWALK_CB_USER); - CALLBACK_INVOKE(material->gp_style->ima, IDWALK_CB_USER); - } + BLI_assert(0); break; } case ID_TE: { - Tex *texture = (Tex *)id; - if (texture->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&texture->nodetree, callback, user_data, flag, &data); - } - CALLBACK_INVOKE(texture->ima, IDWALK_CB_USER); + BLI_assert(0); break; } case ID_LT: { - Lattice *lattice = (Lattice *)id; - CALLBACK_INVOKE(lattice->key, IDWALK_CB_USER); + BLI_assert(0); break; } case ID_LA: { - Light *lamp = (Light *)id; - if (lamp->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&lamp->nodetree, callback, user_data, flag, &data); - } + BLI_assert(0); break; } @@ -958,8 +954,7 @@ static void library_foreach_ID_link(Main *bmain, World *world = (World *)id; if (world->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&world->nodetree, callback, user_data, flag, &data); + BKE_library_foreach_ID_embedded(&data, (ID **)&world->nodetree); } break; } @@ -984,33 +979,7 @@ static void library_foreach_ID_link(Main *bmain, } case ID_NT: { - bNodeTree *ntree = (bNodeTree *)id; - - CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER); - - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER); - - IDP_foreach_property( - node->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } - } - - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } + BLI_assert(0); break; } @@ -1119,8 +1088,7 @@ static void library_foreach_ID_link(Main *bmain, } if (linestyle->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&linestyle->nodetree, callback, user_data, flag, &data); + BKE_library_foreach_ID_embedded(&data, (ID **)&linestyle->nodetree); } LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->color_modifiers) { @@ -1246,6 +1214,14 @@ static void library_foreach_ID_link(Main *bmain, } break; } + case ID_SIM: { + Simulation *simulation = (Simulation *)id; + if (simulation->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(&data, (ID **)&simulation->nodetree); + } + break; + } /* Nothing needed for those... */ case ID_IM: @@ -1300,14 +1276,11 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag) } /** - * Say whether given \a id_type_owner can use (in any way) a data-block of \a id_type_used. + * Say whether given \a id_owner may use (in any way) a data-block of \a id_type_used. * * This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above, - * quite useful to reduce* useless iterations in some cases. + * quite useful to reduce useless iterations in some cases. */ -/* XXX This has to be fully rethink, basing check on ID type is not really working anymore - * (and even worth once IDProps will support ID pointers), - * we'll have to do some quick checks on IDs themselves... */ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) { /* any type of ID can be used in custom props. */ @@ -1417,6 +1390,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) case ID_PAL: case ID_PC: case ID_CF: + case ID_SIM: /* Those types never use/reference other IDs... */ return false; case ID_IP: diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index 72ae4629dba..ba986b1661b 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -334,7 +334,7 @@ static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *o default: break; } - test_object_modifiers(ob); + BKE_modifiers_test_object(ob); BKE_object_materials_test(bmain, ob, new_id); } } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index e3ed21aa536..64ffea22363 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -38,6 +38,7 @@ #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_packedFile.h" @@ -53,6 +54,12 @@ static void library_free_data(ID *id) } } +static void library_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Library *lib = (Library *)id; + BKE_LIB_FOREACHID_PROCESS(data, lib->parent, IDWALK_CB_NEVER_SELF); +} + IDTypeInfo IDType_ID_LI = { .id_code = ID_LI, .id_filter = 0, @@ -67,6 +74,7 @@ IDTypeInfo IDType_ID_LI = { .copy_data = NULL, .free_data = library_free_data, .make_local = NULL, + .foreach_id = library_foreach_id, }; void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath) diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index 3d0503b2e70..9dc338ce580 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -41,6 +41,7 @@ #include "BKE_icons.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_light.h" #include "BKE_main.h" #include "BKE_node.h" @@ -97,7 +98,7 @@ static void light_free_data(ID *id) /* is no lib link block, but light extension */ if (la->nodetree) { - ntreeFreeNestedTree(la->nodetree); + ntreeFreeEmbeddedTree(la->nodetree); MEM_freeN(la->nodetree); la->nodetree = NULL; } @@ -107,6 +108,15 @@ static void light_free_data(ID *id) la->id.icon_id = 0; } +static void light_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Light *lamp = (Light *)id; + if (lamp->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&lamp->nodetree); + } +} + IDTypeInfo IDType_ID_LA = { .id_code = ID_LA, .id_filter = FILTER_ID_LA, @@ -121,6 +131,7 @@ IDTypeInfo IDType_ID_LA = { .copy_data = light_copy_data, .free_data = light_free_data, .make_local = NULL, + .foreach_id = light_foreach_id, }; Light *BKE_light_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 42506e0d7c8..0401ae48b5c 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -125,7 +125,7 @@ static void linestyle_free_data(ID *id) /* is no lib link block, but linestyle extension */ if (linestyle->nodetree) { - ntreeFreeNestedTree(linestyle->nodetree); + ntreeFreeEmbeddedTree(linestyle->nodetree); MEM_freeN(linestyle->nodetree); linestyle->nodetree = NULL; } diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c index caa29f7817a..ea3bee8b2f6 100644 --- a/source/blender/blenkernel/intern/main.c +++ b/source/blender/blenkernel/intern/main.c @@ -479,6 +479,8 @@ ListBase *which_libbase(Main *bmain, short type) return &(bmain->pointclouds); case ID_VO: return &(bmain->volumes); + case ID_SIM: + return &(bmain->simulations); } return NULL; } @@ -554,6 +556,7 @@ int set_listbasepointers(Main *bmain, ListBase **lb) lb[INDEX_ID_WS] = &(bmain->workspaces); /* before wm, so it's freed after it! */ lb[INDEX_ID_WM] = &(bmain->wm); lb[INDEX_ID_MSK] = &(bmain->masks); + lb[INDEX_ID_SIM] = &(bmain->simulations); lb[INDEX_ID_NULL] = NULL; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 1b21ff9b36e..d4de04a9e98 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -64,6 +64,7 @@ #include "BKE_idtype.h" #include "BKE_image.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -130,7 +131,7 @@ static void material_free_data(ID *id) /* is no lib link block, but material extension */ if (material->nodetree) { - ntreeFreeNestedTree(material->nodetree); + ntreeFreeEmbeddedTree(material->nodetree); MEM_freeN(material->nodetree); material->nodetree = NULL; } @@ -143,6 +144,22 @@ static void material_free_data(ID *id) BKE_previewimg_free(&material->preview); } +static void material_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Material *material = (Material *)id; + /* Nodetrees **are owned by IDs**, treat them as mere sub-data and not real ID! */ + if (!BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree)) { + return; + } + if (material->texpaintslot != NULL) { + BKE_LIB_FOREACHID_PROCESS(data, material->texpaintslot->ima, IDWALK_CB_NOP); + } + if (material->gp_style != NULL) { + BKE_LIB_FOREACHID_PROCESS(data, material->gp_style->sima, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, material->gp_style->ima, IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_MA = { .id_code = ID_MA, .id_filter = FILTER_ID_MA, @@ -157,6 +174,7 @@ IDTypeInfo IDType_ID_MA = { .copy_data = material_copy_data, .free_data = material_free_data, .make_local = NULL, + .foreach_id = material_foreach_id, }; void BKE_gpencil_material_attr_init(Material *ma) @@ -1601,7 +1619,7 @@ void BKE_material_copybuf_paste(Main *bmain, Material *ma) GPU_material_free(&ma->gpumaterial); if (ma->nodetree) { - ntreeFreeNestedTree(ma->nodetree); + ntreeFreeEmbeddedTree(ma->nodetree); MEM_freeN(ma->nodetree); } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 4294d279c36..94e5f435a43 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -54,6 +54,7 @@ #include "BKE_displist.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_material.h" #include "BKE_mball.h" #include "BKE_object.h" @@ -101,6 +102,14 @@ static void metaball_free_data(ID *id) } } +static void metaball_foreach_id(ID *id, LibraryForeachIDData *data) +{ + MetaBall *metaball = (MetaBall *)id; + for (int i = 0; i < metaball->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, metaball->mat[i], IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_MB = { .id_code = ID_MB, .id_filter = FILTER_ID_MB, @@ -115,6 +124,7 @@ IDTypeInfo IDType_ID_MB = { .copy_data = metaball_copy_data, .free_data = metaball_free_data, .make_local = NULL, + .foreach_id = metaball_foreach_id, }; /* Functions */ diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 2a86b899290..aeef287bb87 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -25,6 +25,7 @@ #include "DNA_defaults.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -47,6 +48,7 @@ #include "BKE_idtype.h" #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -142,6 +144,16 @@ static void mesh_free_data(ID *id) MEM_SAFE_FREE(mesh->mat); } +static void mesh_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Mesh *mesh = (Mesh *)id; + BKE_LIB_FOREACHID_PROCESS(data, mesh->texcomesh, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, mesh->key, IDWALK_CB_USER); + for (int i = 0; i < mesh->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, mesh->mat[i], IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_ME = { .id_code = ID_ME, .id_filter = FILTER_ID_ME, @@ -156,6 +168,7 @@ IDTypeInfo IDType_ID_ME = { .copy_data = mesh_copy_data, .free_data = mesh_free_data, .make_local = NULL, + .foreach_id = mesh_foreach_id, }; enum { @@ -1128,7 +1141,7 @@ void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me) BKE_object_materials_test(bmain, ob, (ID *)me); - test_object_modifiers(ob); + BKE_modifiers_test_object(ob); } void BKE_mesh_material_index_remove(Mesh *me, short index) diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 28a32e1573b..655c70bcf61 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1313,7 +1313,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, int build_shapekey_layers) { Mesh *me = ob_eval->runtime.data_orig ? ob_eval->runtime.data_orig : ob_eval->data; - const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type); Mesh *result; KeyBlock *kb; ModifierEvalContext mectx = {depsgraph, ob_eval, MOD_APPLY_TO_BASE_MESH}; @@ -1353,7 +1353,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, add_shapekey_layers(mesh_temp, me); } - result = mti->applyModifier(md_eval, &mectx, mesh_temp); + result = mti->modifyMesh(md_eval, &mectx, mesh_temp); ASSERT_IS_VALID_MESH(result); if (mesh_temp != result) { diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index e5be85b5ec7..f0d19f01aab 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1300,9 +1300,9 @@ static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data, } } -static void loop_split_worker(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) +static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) { - LoopSplitTaskDataCommon *common_data = BLI_task_pool_userdata(pool); + LoopSplitTaskDataCommon *common_data = BLI_task_pool_user_data(pool); LoopSplitTaskData *data = taskdata; /* Temp edge vectors stack, only used when computing lnor spacearr. */ @@ -1704,11 +1704,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts, loop_split_generator(NULL, &common_data); } else { - TaskScheduler *task_scheduler; - TaskPool *task_pool; - - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, &common_data, TASK_PRIORITY_HIGH); + TaskPool *task_pool = BLI_task_pool_create(&common_data, TASK_PRIORITY_HIGH); loop_split_generator(task_pool, &common_data); diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c index a2a198cdb0d..d6f945cf34f 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.c +++ b/source/blender/blenkernel/intern/mesh_tangent.c @@ -452,9 +452,7 @@ finally: pRes[3] = fSign; } -static void DM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void DM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata) { struct SGLSLMeshToTangent *mesh2tangent = taskdata; /* new computation method */ @@ -658,9 +656,7 @@ void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert, /* Calculation */ if (looptri_len != 0) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool; - task_pool = BLI_task_pool_create(scheduler, NULL, TASK_PRIORITY_LOW); + TaskPool *task_pool = BLI_task_pool_create(NULL, TASK_PRIORITY_LOW); tangent_mask_curr = 0; /* Calculate tangent layers */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 0a76b61cdb1..e872edf0784 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -59,7 +59,7 @@ #include "BKE_multires.h" #include "BKE_object.h" -/* may move these, only for modifier_path_relbase */ +/* may move these, only for BKE_modifier_path_relbase */ #include "BKE_main.h" /* end */ @@ -82,21 +82,21 @@ void BKE_modifier_init(void) modifier_type_init(modifier_types); /* MOD_utils.c */ /* Initialize global cmmon storage used for virtual modifier list */ - md = modifier_new(eModifierType_Armature); + md = BKE_modifier_new(eModifierType_Armature); virtualModifierCommonData.amd = *((ArmatureModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); - md = modifier_new(eModifierType_Curve); + md = BKE_modifier_new(eModifierType_Curve); virtualModifierCommonData.cmd = *((CurveModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); - md = modifier_new(eModifierType_Lattice); + md = BKE_modifier_new(eModifierType_Lattice); virtualModifierCommonData.lmd = *((LatticeModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); - md = modifier_new(eModifierType_ShapeKey); + md = BKE_modifier_new(eModifierType_ShapeKey); virtualModifierCommonData.smd = *((ShapeKeyModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual; virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual; @@ -104,7 +104,7 @@ void BKE_modifier_init(void) virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual; } -const ModifierTypeInfo *modifierType_getInfo(ModifierType type) +const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type) { /* type unsigned, no need to check < 0 */ if (type < NUM_MODIFIER_TYPES && modifier_types[type] && modifier_types[type]->name[0] != '\0') { @@ -117,9 +117,9 @@ const ModifierTypeInfo *modifierType_getInfo(ModifierType type) /***/ -ModifierData *modifier_new(int type) +ModifierData *BKE_modifier_new(int type) { - const ModifierTypeInfo *mti = modifierType_getInfo(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 */ @@ -151,9 +151,9 @@ static void modifier_free_data_id_us_cb(void *UNUSED(userData), } } -void modifier_free_ex(ModifierData *md, const int flag) +void BKE_modifier_free_ex(ModifierData *md, const int flag) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { if (mti->foreachIDLink) { @@ -174,15 +174,15 @@ void modifier_free_ex(ModifierData *md, const int flag) MEM_freeN(md); } -void modifier_free(ModifierData *md) +void BKE_modifier_free(ModifierData *md) { - modifier_free_ex(md, 0); + BKE_modifier_free_ex(md, 0); } -bool modifier_unique_name(ListBase *modifiers, ModifierData *md) +bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md) { if (modifiers && md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return BLI_uniquename( modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name)); @@ -190,24 +190,24 @@ bool modifier_unique_name(ListBase *modifiers, ModifierData *md) return false; } -bool modifier_dependsOnTime(ModifierData *md) +bool BKE_modifier_depends_ontime(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return mti->dependsOnTime && mti->dependsOnTime(md); } -bool modifier_supportsMapping(ModifierData *md) +bool BKE_modifier_supports_mapping(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_OnlyDeform || (mti->flags & eModifierTypeFlag_SupportsMapping)); } -bool modifier_isPreview(ModifierData *md) +bool BKE_modifier_is_preview(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */ if (!((mti->flags & eModifierTypeFlag_UsesPreview) || @@ -222,7 +222,7 @@ bool modifier_isPreview(ModifierData *md) return false; } -ModifierData *modifiers_findByType(Object *ob, ModifierType type) +ModifierData *BKE_modifiers_findby_type(Object *ob, ModifierType type) { ModifierData *md = ob->modifiers.first; @@ -235,12 +235,12 @@ ModifierData *modifiers_findByType(Object *ob, ModifierType type) return md; } -ModifierData *modifiers_findByName(Object *ob, const char *name) +ModifierData *BKE_modifiers_findny_name(Object *ob, const char *name) { return BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name)); } -void modifiers_clearErrors(Object *ob) +void BKE_modifiers_clear_errors(Object *ob) { ModifierData *md = ob->modifiers.first; /* int qRedraw = 0; */ @@ -255,12 +255,12 @@ void modifiers_clearErrors(Object *ob) } } -void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, void *userData) +void BKE_modifiers_foreach_object_link(Object *ob, ObjectWalkFunc walk, void *userData) { ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->foreachObjectLink) { mti->foreachObjectLink(md, ob, walk, userData); @@ -268,12 +268,12 @@ void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, void *userData } } -void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData) +void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *userData) { ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->foreachIDLink) { mti->foreachIDLink(md, ob, walk, userData); @@ -286,12 +286,12 @@ void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData) } } -void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData) +void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *userData) { ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->foreachTexLink) { mti->foreachTexLink(md, ob, walk, userData); @@ -302,11 +302,11 @@ void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData) /* callback's can use this * to avoid copying every member. */ -void modifier_copyData_generic(const ModifierData *md_src, - ModifierData *md_dst, - const int UNUSED(flag)) +void BKE_modifier_copydata_generic(const ModifierData *md_src, + ModifierData *md_dst, + const int UNUSED(flag)) { - const ModifierTypeInfo *mti = modifierType_getInfo(md_src->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_src->type); /* md_dst may have already be fully initialized with some extra allocated data, * we need to free it now to avoid memleak. */ @@ -335,9 +335,9 @@ static void modifier_copy_data_id_us_cb(void *UNUSED(userData), } } -void modifier_copyData_ex(ModifierData *md, ModifierData *target, const int flag) +void BKE_modifier_copydata_ex(ModifierData *md, ModifierData *target, const int flag) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); target->mode = md->mode; target->flag = md->flag; @@ -356,40 +356,41 @@ void modifier_copyData_ex(ModifierData *md, ModifierData *target, const int flag } } -void modifier_copyData(ModifierData *md, ModifierData *target) +void BKE_modifier_copydata(ModifierData *md, ModifierData *target) { - modifier_copyData_ex(md, target, 0); + BKE_modifier_copydata_ex(md, target, 0); } -bool modifier_supportsCage(struct Scene *scene, ModifierData *md) +bool BKE_modifier_supports_cage(struct Scene *scene, ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return ((!mti->isDisabled || !mti->isDisabled(scene, md, 0)) && - (mti->flags & eModifierTypeFlag_SupportsEditmode) && modifier_supportsMapping(md)); + (mti->flags & eModifierTypeFlag_SupportsEditmode) && BKE_modifier_supports_mapping(md)); } -bool modifier_couldBeCage(struct Scene *scene, ModifierData *md) +bool BKE_modifier_couldbe_cage(struct Scene *scene, ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return ((md->mode & eModifierMode_Realtime) && (md->mode & eModifierMode_Editmode) && - (!mti->isDisabled || !mti->isDisabled(scene, md, 0)) && modifier_supportsMapping(md)); + (!mti->isDisabled || !mti->isDisabled(scene, md, 0)) && + BKE_modifier_supports_mapping(md)); } -bool modifier_isSameTopology(ModifierData *md) +bool BKE_modifier_is_same_topology(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical); } -bool modifier_isNonGeometrical(ModifierData *md) +bool BKE_modifier_is_non_geometrical(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_NonGeometrical); } -void modifier_setError(ModifierData *md, const char *_format, ...) +void BKE_modifier_set_error(ModifierData *md, const char *_format, ...) { char buffer[512]; va_list ap; @@ -416,14 +417,15 @@ void modifier_setError(ModifierData *md, const char *_format, ...) * then is NULL) * also used for some mesh tools to give warnings */ -int modifiers_getCageIndex(struct Scene *scene, - Object *ob, - int *r_lastPossibleCageIndex, - bool is_virtual) +int BKE_modifiers_get_cage_index(struct Scene *scene, + Object *ob, + int *r_lastPossibleCageIndex, + bool is_virtual) { VirtualModifierData virtualModifierData; - ModifierData *md = (is_virtual) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : - ob->modifiers.first; + ModifierData *md = (is_virtual) ? + BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData) : + ob->modifiers.first; int i, cageIndex = -1; if (r_lastPossibleCageIndex) { @@ -433,7 +435,7 @@ int modifiers_getCageIndex(struct Scene *scene, /* Find the last modifier acting on the cage. */ for (i = 0; md; i++, md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); bool supports_mapping; if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { @@ -446,7 +448,7 @@ int modifiers_getCageIndex(struct Scene *scene, continue; } - supports_mapping = modifier_supportsMapping(md); + supports_mapping = BKE_modifier_supports_mapping(md); if (r_lastPossibleCageIndex && supports_mapping) { *r_lastPossibleCageIndex = i; } @@ -470,30 +472,30 @@ int modifiers_getCageIndex(struct Scene *scene, return cageIndex; } -bool modifiers_isSoftbodyEnabled(Object *ob) +bool BKE_modifiers_is_softbody_enabled(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Softbody); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -bool modifiers_isClothEnabled(Object *ob) +bool BKE_modifiers_is_cloth_enabled(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -bool modifiers_isModifierEnabled(Object *ob, int modifierType) +bool BKE_modifiers_is_modifier_enabled(Object *ob, int modifierType) { - ModifierData *md = modifiers_findByType(ob, modifierType); + ModifierData *md = BKE_modifiers_findby_type(ob, modifierType); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -bool modifiers_isParticleEnabled(Object *ob) +bool BKE_modifiers_is_particle_enabled(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_ParticleSystem); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } @@ -504,9 +506,9 @@ bool modifiers_isParticleEnabled(Object *ob) * \param scene: Current scene, may be NULL, * in which case isDisabled callback of the modifier is never called. */ -bool modifier_isEnabled(const struct Scene *scene, ModifierData *md, int required_mode) +bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int required_mode) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if ((md->mode & required_mode) != required_mode) { return false; @@ -526,13 +528,13 @@ bool modifier_isEnabled(const struct Scene *scene, ModifierData *md, int require return true; } -CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, - Object *ob, - ModifierData *md, - CustomData_MeshMasks *final_datamask, - int required_mode, - ModifierData *previewmd, - const CustomData_MeshMasks *previewmask) +CDMaskLink *BKE_modifier_calc_data_masks(struct Scene *scene, + Object *ob, + ModifierData *md, + CustomData_MeshMasks *final_datamask, + int required_mode, + ModifierData *previewmd, + const CustomData_MeshMasks *previewmask) { CDMaskLink *dataMasks = NULL; CDMaskLink *curr, *prev; @@ -540,11 +542,11 @@ CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, /* build a list of modifier data requirements in reverse order */ for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); curr = MEM_callocN(sizeof(CDMaskLink), "CDMaskLink"); - if (modifier_isEnabled(scene, md, required_mode)) { + if (BKE_modifier_is_enabled(scene, md, required_mode)) { if (mti->type == eModifierTypeType_OnlyDeform) { have_deform_modifier = true; } @@ -594,7 +596,9 @@ CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, return dataMasks; } -ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode) +ModifierData *BKE_modifier_get_last_preview(struct Scene *scene, + ModifierData *md, + int required_mode) { ModifierData *tmp_md = NULL; @@ -604,7 +608,7 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in /* Find the latest modifier in stack generating preview. */ for (; md; md = md->next) { - if (modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md)) { + if (BKE_modifier_is_enabled(scene, md, required_mode) && BKE_modifier_is_preview(md)) { tmp_md = md; } } @@ -613,8 +617,8 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in /* This is to include things that are not modifiers in the evaluation of the modifier stack, for * example parenting to an armature. */ -ModifierData *modifiers_getVirtualModifierList(const Object *ob, - VirtualModifierData *virtualModifierData) +ModifierData *BKE_modifiers_get_virtual_modifierlist(const Object *ob, + VirtualModifierData *virtualModifierData) { ModifierData *md; @@ -661,10 +665,10 @@ ModifierData *modifiers_getVirtualModifierList(const Object *ob, /* Takes an object and returns its first selected armature, else just its armature * This should work for multiple armatures per object */ -Object *modifiers_isDeformedByArmature(Object *ob) +Object *BKE_modifiers_is_deformed_by_armature(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ArmatureModifierData *amd = NULL; /* return the first selected armature, this lets us use multiple armatures */ @@ -684,10 +688,10 @@ Object *modifiers_isDeformedByArmature(Object *ob) return NULL; } -Object *modifiers_isDeformedByMeshDeform(Object *ob) +Object *BKE_modifiers_is_deformed_by_meshdeform(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); MeshDeformModifierData *mdmd = NULL; /* return the first selected armature, this lets us use multiple armatures */ @@ -710,10 +714,10 @@ Object *modifiers_isDeformedByMeshDeform(Object *ob) /* Takes an object and returns its first selected lattice, else just its lattice * This should work for multiple lattices per object */ -Object *modifiers_isDeformedByLattice(Object *ob) +Object *BKE_modifiers_is_deformed_by_lattice(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); LatticeModifierData *lmd = NULL; /* return the first selected lattice, this lets us use multiple lattices */ @@ -736,10 +740,10 @@ Object *modifiers_isDeformedByLattice(Object *ob) /* Takes an object and returns its first selected curve, else just its curve * This should work for multiple curves per object */ -Object *modifiers_isDeformedByCurve(Object *ob) +Object *BKE_modifiers_is_deformed_by_curve(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); CurveModifierData *cmd = NULL; /* return the first selected curve, this lets us use multiple curves */ @@ -759,10 +763,10 @@ Object *modifiers_isDeformedByCurve(Object *ob) return NULL; } -bool modifiers_usesMultires(Object *ob) +bool BKE_modifiers_uses_multires(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); MultiresModifierData *mmd = NULL; for (; md; md = md->next) { @@ -776,10 +780,10 @@ bool modifiers_usesMultires(Object *ob) return false; } -bool modifiers_usesArmature(Object *ob, bArmature *arm) +bool BKE_modifiers_uses_armature(Object *ob, bArmature *arm) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); for (; md; md = md->next) { if (md->type == eModifierType_Armature) { @@ -793,13 +797,13 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm) return false; } -bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob) +bool BKE_modifiers_uses_subsurf_facedots(struct Scene *scene, Object *ob) { /* Search (backward) in the modifier stack to find if we have a subsurf modifier (enabled) before * the last modifier displayed on cage (or if the subsurf is the last). */ VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); - int cage_index = modifiers_getCageIndex(scene, ob, NULL, 1); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); + int cage_index = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); if (cage_index == -1) { return false; } @@ -809,10 +813,10 @@ bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob) } /* Now from this point, search for subsurf modifier. */ for (; md; md = md->prev) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (md->type == eModifierType_Subsurf) { ModifierMode mode = eModifierMode_Realtime | eModifierMode_Editmode; - if (modifier_isEnabled(scene, md, mode)) { + if (BKE_modifier_is_enabled(scene, md, mode)) { return true; } } @@ -828,48 +832,33 @@ bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob) return false; } -bool modifier_isCorrectableDeformed(ModifierData *md) +bool BKE_modifier_is_correctable_deformed(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return mti->deformMatricesEM != NULL; } -bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob) +bool BKE_modifiers_is_correctable_deformed(struct Scene *scene, Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); int required_mode = eModifierMode_Realtime; if (ob->mode == OB_MODE_EDIT) { required_mode |= eModifierMode_Editmode; } for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { /* pass */ } - else if (modifier_isCorrectableDeformed(md)) { + else if (BKE_modifier_is_correctable_deformed(md)) { return true; } } return false; } -/* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer - * to preview something... Used by DynamicPaint and WeightVG currently. */ -bool modifiers_isPreview(Object *ob) -{ - ModifierData *md = ob->modifiers.first; - - for (; md; md = md->next) { - if (modifier_isPreview(md)) { - return true; - } - } - - return false; -} - -void modifier_freeTemporaryData(ModifierData *md) +void BKE_modifier_free_temporary_data(ModifierData *md) { if (md->type == eModifierType_Armature) { ArmatureModifierData *amd = (ArmatureModifierData *)md; @@ -882,7 +871,7 @@ void modifier_freeTemporaryData(ModifierData *md) } /* ensure modifier correctness when changing ob->data */ -void test_object_modifiers(Object *ob) +void BKE_modifiers_test_object(Object *ob) { ModifierData *md; @@ -913,7 +902,7 @@ void test_object_modifiers(Object *ob) * - else if the file has been saved return the blend file path. * - else if the file isn't saved and the ID isn't from a library, return the temp dir. */ -const char *modifier_path_relbase(Main *bmain, Object *ob) +const char *BKE_modifier_path_relbase(Main *bmain, Object *ob) { if (G.relbase_valid || ID_IS_LINKED(ob)) { return ID_BLEND_PATH(bmain, &ob->id); @@ -925,7 +914,7 @@ const char *modifier_path_relbase(Main *bmain, Object *ob) } } -const char *modifier_path_relbase_from_global(Object *ob) +const char *BKE_modifier_path_relbase_from_global(Object *ob) { if (G.relbase_valid || ID_IS_LINKED(ob)) { return ID_BLEND_PATH_FROM_GLOBAL(&ob->id); @@ -938,35 +927,35 @@ const char *modifier_path_relbase_from_global(Object *ob) } /* initializes the path with either */ -void modifier_path_init(char *path, int path_maxlen, const char *name) +void BKE_modifier_path_init(char *path, int path_maxlen, const char *name) { /* elubie: changed this to default to the same dir as the render output * to prevent saving to C:\ on Windows */ BLI_join_dirfile(path, path_maxlen, G.relbase_valid ? "//" : BKE_tempdir_session(), name); } -/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */ +/* wrapper around ModifierTypeInfo.modifyMesh that ensures valid normals */ -struct Mesh *modwrap_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - struct Mesh *me) +struct Mesh *BKE_modifier_modify_mesh(ModifierData *md, + const ModifierEvalContext *ctx, + struct Mesh *me) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); BLI_assert(CustomData_has_layer(&me->pdata, CD_NORMAL) == false); if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { BKE_mesh_calc_normals(me); } - return mti->applyModifier(md, ctx, me); + return mti->modifyMesh(md, ctx, me); } -void modwrap_deformVerts(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *me, - float (*vertexCos)[3], - int numVerts) +void BKE_modifier_deform_verts(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *me, + float (*vertexCos)[3], + int numVerts) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false); if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -975,14 +964,14 @@ void modwrap_deformVerts(ModifierData *md, mti->deformVerts(md, ctx, me, vertexCos, numVerts); } -void modwrap_deformVertsEM(ModifierData *md, - const ModifierEvalContext *ctx, - struct BMEditMesh *em, - Mesh *me, - float (*vertexCos)[3], - int numVerts) +void BKE_modifier_deform_vertsEM(ModifierData *md, + const ModifierEvalContext *ctx, + struct BMEditMesh *em, + Mesh *me, + float (*vertexCos)[3], + int numVerts) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false); if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -1025,7 +1014,7 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval, return me; } -ModifierData *modifier_get_original(ModifierData *md) +ModifierData *BKE_modifier_get_original(ModifierData *md) { if (md->orig_modifier_data == NULL) { return md; @@ -1033,11 +1022,13 @@ ModifierData *modifier_get_original(ModifierData *md) return md->orig_modifier_data; } -struct ModifierData *modifier_get_evaluated(Depsgraph *depsgraph, Object *object, ModifierData *md) +struct ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph, + Object *object, + ModifierData *md) { Object *object_eval = DEG_get_evaluated_object(depsgraph, object); if (object_eval == object) { return md; } - return modifiers_findByName(object_eval, md->name); + return BKE_modifiers_findny_name(object_eval, md->name); } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 193fe859def..4c7b791f103 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -460,6 +460,7 @@ typedef struct MovieClipCache { float principal[2]; float polynomial_k[3]; float division_k[2]; + float nuke_k[2]; short distortion_model; bool undistortion_used; @@ -908,6 +909,9 @@ static bool check_undistortion_cache_flags(const MovieClip *clip) if (!equals_v2v2(&camera->division_k1, cache->postprocessed.division_k)) { return false; } + if (!equals_v2v2(&camera->nuke_k1, cache->postprocessed.nuke_k)) { + return false; + } return true; } @@ -1010,6 +1014,7 @@ static void put_postprocessed_frame_to_cache( copy_v2_v2(cache->postprocessed.principal, camera->principal); copy_v3_v3(cache->postprocessed.polynomial_k, &camera->k1); copy_v2_v2(cache->postprocessed.division_k, &camera->division_k1); + copy_v2_v2(cache->postprocessed.nuke_k, &camera->nuke_k1); cache->postprocessed.undistortion_used = true; } else { @@ -1512,7 +1517,8 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip undist_marker.pos[0] *= width; undist_marker.pos[1] *= height * aspy; - BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos); + BKE_tracking_undistort_v2( + &clip->tracking, width, height, undist_marker.pos, undist_marker.pos); undist_marker.pos[0] /= width; undist_marker.pos[1] /= height * aspy; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 69cd338e15f..7e78be6d66e 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -10,7 +10,7 @@ * 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, + * 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) 2007 by Nicholas Bishop @@ -289,8 +289,8 @@ Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph, .flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY, }; - const ModifierTypeInfo *mti = modifierType_getInfo(mmd->modifier.type); - Mesh *result = mti->applyModifier(&mmd->modifier, &modifier_ctx, deformed_mesh); + const ModifierTypeInfo *mti = BKE_modifier_get_info(mmd->modifier.type); + Mesh *result = mti->modifyMesh(&mmd->modifier, &modifier_ctx, deformed_mesh); if (result == deformed_mesh) { result = BKE_mesh_copy_for_eval(deformed_mesh, true); @@ -318,8 +318,8 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *dep const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; VirtualModifierData virtual_modifier_data; - ModifierData *first_md = modifiers_getVirtualModifierList(&object_for_eval, - &virtual_modifier_data); + ModifierData *first_md = BKE_modifiers_get_virtual_modifierlist(&object_for_eval, + &virtual_modifier_data); Mesh *base_mesh = object->data; @@ -327,13 +327,13 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *dep float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(base_mesh, &num_deformed_verts); for (ModifierData *md = first_md; md != NULL; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (md == &mmd->modifier) { break; } - if (!modifier_isEnabled(scene_eval, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene_eval, md, required_mode)) { continue; } @@ -341,7 +341,8 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *dep break; } - modwrap_deformVerts(md, &mesh_eval_context, base_mesh, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts( + md, &mesh_eval_context, base_mesh, deformed_verts, num_deformed_verts); } if (r_num_deformed_verts != NULL) { @@ -356,7 +357,7 @@ MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData * for (md = lastmd; md; md = md->prev) { if (md->type == eModifierType_Multires) { - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { return (MultiresModifierData *)md; } } @@ -380,7 +381,7 @@ MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, bool use_f firstmmd = (MultiresModifierData *)md; } - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { mmd = (MultiresModifierData *)md; break; } @@ -407,7 +408,7 @@ int multires_get_level(const Scene *scene, mmd->renderlvl; } else if (ob->mode == OB_MODE_SCULPT) { - return BKE_multires_sculpt_level_get(mmd); + return mmd->sculptlvl; } else if (ignore_simplify) { return mmd->lvl; @@ -2193,10 +2194,10 @@ void multires_load_old(Object *ob, Mesh *me) /* Add a multires modifier to the object */ md = ob->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } - mmd = (MultiresModifierData *)modifier_new(eModifierType_Multires); + mmd = (MultiresModifierData *)BKE_modifier_new(eModifierType_Multires); BLI_insertlinkbefore(&ob->modifiers, md, mmd); for (i = 0; i < me->mr->level_count - 1; i++) { @@ -2234,7 +2235,14 @@ void multiresModifier_sync_levels_ex(Object *ob_dst, } if (mmd_src->totlvl > mmd_dst->totlvl) { - multiresModifier_subdivide_to_level(ob_dst, mmd_dst, mmd_src->totlvl); + if (mmd_dst->simple) { + multiresModifier_subdivide_to_level( + ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_SIMPLE); + } + else { + multiresModifier_subdivide_to_level( + ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_CATMULL_CLARK); + } } else { multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl); @@ -2516,12 +2524,3 @@ int mdisp_rot_face_to_crn(struct MVert *UNUSED(mvert), return S; } - -/* This is a workaround for T58473. - * Force sculpting on the highest level for until the root of the issue is solved. - * - * When that issue is solved simple replace call of this function with mmd->sculptlvl. */ -int BKE_multires_sculpt_level_get(const struct MultiresModifierData *mmd) -{ - return mmd->totlvl; -} diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index 02cd5f094a6..c5184881b7c 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -28,8 +28,6 @@ #include "DNA_modifier_types.h" #include "DNA_scene_types.h" -#include "BLI_math_vector.h" - #include "BKE_customdata.h" #include "BKE_lib_id.h" #include "BKE_mesh.h" @@ -37,14 +35,16 @@ #include "BKE_modifier.h" #include "BKE_multires.h" #include "BKE_subdiv.h" +#include "BKE_subsurf.h" +#include "BLI_math_vector.h" #include "DEG_depsgraph_query.h" #include "multires_reshape.h" -/* ================================================================================================ - * Reshape from object. - */ +/* -------------------------------------------------------------------- */ +/** \name Reshape from object + * \{ */ bool multiresModifier_reshapeFromVertcos(struct Depsgraph *depsgraph, struct Object *object, @@ -93,9 +93,11 @@ bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph, return result; } -/* ================================================================================================ - * Reshape from modifier. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reshape from modifier + * \{ */ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph, struct Object *object, @@ -119,7 +121,7 @@ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph, .object = object, .flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY, }; - modwrap_deformVerts( + BKE_modifier_deform_verts( deform_md, &modifier_ctx, multires_mesh, deformed_verts, multires_mesh->totvert); BKE_id_free(NULL, multires_mesh); @@ -133,9 +135,11 @@ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph, return result; } -/* ================================================================================================ - * Reshape from grids. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reshape from grids + * \{ */ bool multiresModifier_reshapeFromCCG(const int tot_level, Mesh *coarse_mesh, @@ -161,19 +165,24 @@ bool multiresModifier_reshapeFromCCG(const int tot_level, return true; } -/* ================================================================================================ - * Subdivision. - */ +/** \} */ -void multiresModifier_subdivide(Object *object, MultiresModifierData *mmd) +/* -------------------------------------------------------------------- */ +/** \name Subdivision + * \{ */ + +void multiresModifier_subdivide(Object *object, + MultiresModifierData *mmd, + const eMultiresSubdivideModeType mode) { const int top_level = mmd->totlvl + 1; - multiresModifier_subdivide_to_level(object, mmd, top_level); + multiresModifier_subdivide_to_level(object, mmd, top_level, mode); } void multiresModifier_subdivide_to_level(struct Object *object, struct MultiresModifierData *mmd, - const int top_level) + const int top_level, + const eMultiresSubdivideModeType mode) { if (top_level <= mmd->totlvl) { return; @@ -190,7 +199,12 @@ void multiresModifier_subdivide_to_level(struct Object *object, } if (!has_mdisps || top_level == 1) { multires_reshape_ensure_grids(coarse_mesh, top_level); - multires_set_tot_level(object, mmd, top_level); + if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) { + multires_subdivide_create_tangent_displacement_linear_grids(object, mmd); + } + else { + multires_set_tot_level(object, mmd, top_level); + } return; } @@ -199,25 +213,33 @@ void multiresModifier_subdivide_to_level(struct Object *object, if (!multires_reshape_context_create_from_subdivide(&reshape_context, object, mmd, top_level)) { return; } + multires_reshape_store_original_grids(&reshape_context); multires_reshape_ensure_grids(coarse_mesh, reshape_context.top.level); multires_reshape_assign_final_coords_from_orig_mdisps(&reshape_context); - /* Free original grids which makes it so smoothing with details thinks all the details were - * added against base mesh's limit surface. This is similar behavior to as if we've done all - * displacement in sculpt mode at the old top level and then propagated to the new top level. */ - multires_reshape_free_original_grids(&reshape_context); + if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) { + multires_reshape_smooth_object_grids(&reshape_context, mode); + } + else { + /* Free original grids which makes it so smoothing with details thinks all the details were + * added against base mesh's limit surface. This is similar behavior to as if we've done all + * displacement in sculpt mode at the old top level and then propagated to the new top level.*/ + multires_reshape_free_original_grids(&reshape_context); - multires_reshape_smooth_object_grids_with_details(&reshape_context); + multires_reshape_smooth_object_grids_with_details(&reshape_context); + } multires_reshape_object_grids_to_tangent_displacement(&reshape_context); multires_reshape_context_free(&reshape_context); multires_set_tot_level(object, mmd, top_level); } -/* ================================================================================================ - * Apply base. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Apply base + * \{ */ void multiresModifier_base_apply(struct Depsgraph *depsgraph, Object *object, @@ -263,3 +285,5 @@ void multiresModifier_base_apply(struct Depsgraph *depsgraph, multires_reshape_context_free(&reshape_context); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h index adfa2659661..8eb90809c31 100644 --- a/source/blender/blenkernel/intern/multires_reshape.h +++ b/source/blender/blenkernel/intern/multires_reshape.h @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -26,6 +26,8 @@ #include "BLI_sys_types.h" +#include "BKE_multires.h" + struct Depsgraph; struct GridPaintMask; struct MDisps; @@ -138,7 +140,7 @@ typedef struct ReshapeConstGridElement { float mask; } ReshapeConstGridElement; -/* ================================================================================================ +/* -------------------------------------------------------------------- * Construct/destruct reshape context. */ @@ -156,6 +158,11 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape struct Object *object, struct MultiresModifierData *mmd); +bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context, + struct Depsgraph *depsgraph, + struct Object *object, + struct MultiresModifierData *mmd); + bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_context, struct SubdivCCG *subdiv_ccg, struct Mesh *base_mesh, @@ -169,7 +176,7 @@ bool multires_reshape_context_create_from_subdivide(MultiresReshapeContext *resh void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_context); void multires_reshape_context_free(MultiresReshapeContext *reshape_context); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Helper accessors. */ @@ -214,7 +221,7 @@ ReshapeGridElement multires_reshape_grid_element_for_ptex_coord( ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord( const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Sample limit surface of the base mesh. */ @@ -225,14 +232,14 @@ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *resha float r_P[3], float r_tangent_matrix[3][3]); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Custom data preparation. */ /* Make sure custom data is allocated for the given level. */ void multires_reshape_ensure_grids(struct Mesh *mesh, const int level); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Functions specific to reshaping from a set of vertices in a object position. */ @@ -245,17 +252,21 @@ bool multires_reshape_assign_final_coords_from_vertcos( const float (*vert_coords)[3], const int num_vert_coords); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Functions specific to reshaping from CCG. */ -/* NOTE: Displacement grids to be at least at a reshape level. +/* Store final object-space coordinates in the displacement grids. + * The reason why displacement grids are used for storage is based on memory + * footprint optimization. + * + * NOTE: Displacement grids to be at least at a reshape level. * * Return truth if all coordinates have been updated. */ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext *reshape_context, struct SubdivCCG *subdiv_ccg); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Functions specific to reshaping from MDISPS. */ @@ -267,7 +278,7 @@ void multires_reshape_assign_final_coords_from_mdisps( void multires_reshape_assign_final_coords_from_orig_mdisps( const MultiresReshapeContext *reshape_context); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Displacement smooth. */ @@ -284,9 +295,10 @@ void multires_reshape_smooth_object_grids_with_details( * * Makes it so surface on top level looks smooth. Details are not preserved */ -void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context); +void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context, + const enum eMultiresSubdivideModeType mode); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Displacement, space conversion. */ @@ -297,7 +309,7 @@ void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_conte void multires_reshape_object_grids_to_tangent_displacement( const MultiresReshapeContext *reshape_context); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Apply base. */ @@ -319,5 +331,4 @@ void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshap * * NOTE: Will re-evaluate all leading modifiers, so it's not cheap. */ void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context); - #endif /* __BKE_INTERN_MULTIRES_RESHAPE_H__ */ diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.c b/source/blender/blenkernel/intern/multires_reshape_apply_base.c index e67e553e8ed..105e56e4219 100644 --- a/source/blender/blenkernel/intern/multires_reshape_apply_base.c +++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_reshape_ccg.c b/source/blender/blenkernel/intern/multires_reshape_ccg.c index 1f8c782ed46..8273845e820 100644 --- a/source/blender/blenkernel/intern/multires_reshape_ccg.c +++ b/source/blender/blenkernel/intern/multires_reshape_ccg.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index d99e27ad9dd..3f312960448 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -48,6 +48,10 @@ #include "atomic_ops.h" #include "subdiv_converter.h" +/* -------------------------------------------------------------------- */ +/** \name Local Structs + * \{ */ + typedef struct SurfacePoint { float P[3]; float tangent_matrix[3][3]; @@ -114,12 +118,24 @@ typedef struct MultiresReshapeSmoothContext { /* Subdivision surface created for geometry at a reshape level. */ Subdiv *reshape_subdiv; + /* Grids allocated at the top level storing state of the base mesh, + * Basically, lower memory footprint version of the base mesh limit surface. */ SurfaceGrid *base_surface_grids; + + /* Defines how displacement is interpolated on the higher levels (for example, whether + * displacement is smoothed in Catmull-Clark mode or interpolated linearly preserving sharp edges + * of the current sculpt level). + * + * NOTE: Uses same enumerator type as Subdivide operator, since the values are the same and + * decoupling type just adds extra headache to convert one enumerator to another. */ + eMultiresSubdivideModeType smoothing_type; } MultiresReshapeSmoothContext; -/* ================================================================================================ - * Masks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Masks + * \{ */ /* Interpolate mask grid at a reshape level. * Will return 0 if there is no masks custom data layer. */ @@ -165,9 +181,11 @@ static float interpolate_masks_grid(const MultiresReshapeSmoothContext *reshape_ mask_elements[2] * weights[2] + mask_elements[3] * weights[3]; } -/* ================================================================================================ - * Surface. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Surface + * \{ */ static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_smooth_context) { @@ -227,9 +245,11 @@ static void base_surface_grids_write(const MultiresReshapeSmoothContext *reshape copy_m3_m3(point->tangent_matrix, tangent_matrix); } -/* ================================================================================================ - * Evaluation of subdivision surface at a reshape level. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation of subdivision surface at a reshape level + * \{ */ typedef void (*ForeachTopLevelGridCoordCallback)( const MultiresReshapeSmoothContext *reshape_smooth_context, @@ -383,11 +403,14 @@ static void foreach_toplevel_grid_coord(const MultiresReshapeSmoothContext *resh 0, num_faces, &data, foreach_toplevel_grid_coord_task, ¶llel_range_settings); } -/* ================================================================================================ - * Generation of a topology information for OpenSubdiv converter. +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generation of a topology information for OpenSubdiv converter * * Calculates vertices, their coordinates in the original grids, and connections of them so then - * it's easy to create OpenSubdiv's topology refiner. */ + * it's easy to create OpenSubdiv's topology refiner. + * \{ */ static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_context) { @@ -399,15 +422,17 @@ static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_co static char get_effective_edge_crease_char( const MultiresReshapeSmoothContext *reshape_smooth_context, const MEdge *base_edge) { - const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - if (reshape_context->subdiv->settings.is_simple) { + if (ELEM(reshape_smooth_context->smoothing_type, + MULTIRES_SUBDIVIDE_LINEAR, + MULTIRES_SUBDIVIDE_SIMPLE)) { return 255; } return base_edge->crease; } static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, - const MultiresReshapeContext *reshape_context) + const MultiresReshapeContext *reshape_context, + const eMultiresSubdivideModeType mode) { reshape_smooth_context->reshape_context = reshape_context; @@ -427,6 +452,8 @@ static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, reshape_smooth_context->non_loose_base_edge_map = NULL; reshape_smooth_context->reshape_subdiv = NULL; reshape_smooth_context->base_surface_grids = NULL; + + reshape_smooth_context->smoothing_type = mode; } static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context) @@ -461,12 +488,14 @@ static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context) static bool foreach_topology_info(const SubdivForeachContext *foreach_context, const int num_vertices, - const int UNUSED(num_edges), + const int num_edges, const int num_loops, const int num_polygons) { MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data; - const int max_edges = reshape_smooth_context->geometry.max_edges; + const int max_edges = reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR ? + num_edges : + reshape_smooth_context->geometry.max_edges; /* NOTE: Calloc so the counters are re-set to 0 "for free". */ reshape_smooth_context->geometry.num_vertices = num_vertices; @@ -659,6 +688,22 @@ static void foreach_vertex_of_loose_edge(const struct SubdivForeachContext *fore } } +static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context, + const int subdiv_v1, + const int subdiv_v2, + const char crease) +{ + /* This is a bit overhead to use atomics in such a simple function called from many threads, + * but this allows to save quite measurable amount of memory. */ + const int edge_index = atomic_fetch_and_add_z(&reshape_smooth_context->geometry.num_edges, 1); + BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges); + + Edge *edge = &reshape_smooth_context->geometry.edges[edge_index]; + edge->v1 = subdiv_v1; + edge->v2 = subdiv_v2; + edge->sharpness = BKE_subdiv_edge_crease_to_sharpness_char(crease); +} + static void foreach_edge(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_edge_index, @@ -669,8 +714,15 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context, MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data; const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - /* Ignore all inner face edges as they have sharpness of zero. */ - if (coarse_edge_index == ORIGINDEX_NONE) { + if (reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR) { + store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, (char)255); + return; + } + + /* Ignore all inner face edges as they have sharpness of zero when using Catmull-Clark mode. In + * simple mode, all edges have maximum sharpness, so they can't be skipped. */ + if (coarse_edge_index == ORIGINDEX_NONE && + reshape_smooth_context->smoothing_type != MULTIRES_SUBDIVIDE_SIMPLE) { return; } /* Ignore all loose edges as well, as they are not communicated to the OpenSubdiv. */ @@ -684,16 +736,7 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context, if (crease == 0) { return; } - - /* This is a bit overhead to use atomics in such a simple function called from many threads, - * but this allows to save quite measurable amount of memory. */ - const int edge_index = atomic_fetch_and_add_z(&reshape_smooth_context->geometry.num_edges, 1); - BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges); - - Edge *edge = &reshape_smooth_context->geometry.edges[edge_index]; - edge->v1 = subdiv_v1; - edge->v2 = subdiv_v2; - edge->sharpness = BKE_subdiv_edge_crease_to_sharpness_char(crease); + store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, crease); } static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshape_smooth_context) @@ -757,9 +800,11 @@ static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context reshape_context->subdiv, &foreach_context, &mesh_settings, reshape_context->base_mesh); } -/* ================================================================================================ - * Generation of OpenSubdiv evaluator for topology created form reshape level. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generation of OpenSubdiv evaluator for topology created form reshape level + * \{ */ static OpenSubdiv_SchemeType get_scheme_type(const OpenSubdiv_Converter *UNUSED(converter)) { @@ -1037,9 +1082,11 @@ static void reshape_subdiv_evaluate_limit_at_grid( BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, corner); } -/* ================================================================================================ - * Evaluation of base surface. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation of base surface + * \{ */ static void evaluate_base_surface_grids_callback( const MultiresReshapeSmoothContext *reshape_smooth_context, @@ -1060,9 +1107,11 @@ static void evaluate_base_surface_grids(const MultiresReshapeSmoothContext *resh foreach_toplevel_grid_coord(reshape_smooth_context, evaluate_base_surface_grids_callback, NULL); } -/* ================================================================================================ - * Evaluation of new surface. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation of new surface + * \{ */ /* Evaluate final position of the original (pre-sculpt-edit) point position at a given grid * coordinate. */ @@ -1176,9 +1225,12 @@ static void evaluate_higher_grid_positions( foreach_toplevel_grid_coord( reshape_smooth_context, evaluate_higher_grid_positions_callback, NULL); } -/* ================================================================================================ - * Entry point. - */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Entry point + * \{ */ void multires_reshape_smooth_object_grids_with_details( const MultiresReshapeContext *reshape_context) @@ -1190,7 +1242,12 @@ void multires_reshape_smooth_object_grids_with_details( } MultiresReshapeSmoothContext reshape_smooth_context; - context_init(&reshape_smooth_context, reshape_context); + if (reshape_context->subdiv->settings.is_simple) { + context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_SIMPLE); + } + else { + context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_CATMULL_CLARK); + } geometry_create(&reshape_smooth_context); @@ -1206,7 +1263,8 @@ void multires_reshape_smooth_object_grids_with_details( context_free(&reshape_smooth_context); } -void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context) +void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context, + const eMultiresSubdivideModeType mode) { const int level_difference = (reshape_context->top.level - reshape_context->reshape.level); if (level_difference == 0) { @@ -1215,7 +1273,7 @@ void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_ } MultiresReshapeSmoothContext reshape_smooth_context; - context_init(&reshape_smooth_context, reshape_context); + context_init(&reshape_smooth_context, reshape_context, mode); geometry_create(&reshape_smooth_context); @@ -1226,3 +1284,5 @@ void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_ context_free(&reshape_smooth_context); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/multires_reshape_subdivide.c b/source/blender/blenkernel/intern/multires_reshape_subdivide.c new file mode 100644 index 00000000000..7b7c1efc533 --- /dev/null +++ b/source/blender/blenkernel/intern/multires_reshape_subdivide.c @@ -0,0 +1,106 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" + +#include "BKE_customdata.h" +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_subdiv.h" +#include "BKE_subsurf.h" +#include "BLI_math_vector.h" + +#include "DEG_depsgraph_query.h" + +#include "multires_reshape.h" + +static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh) +{ + MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS); + const int totpoly = mesh->totpoly; + for (int p = 0; p < totpoly; p++) { + MPoly *poly = &mesh->mpoly[p]; + float poly_center[3]; + BKE_mesh_calc_poly_center(poly, &mesh->mloop[poly->loopstart], mesh->mvert, poly_center); + for (int l = 0; l < poly->totloop; l++) { + const int loop_index = poly->loopstart + l; + + float(*disps)[3] = mdisps[loop_index].disps; + mdisps[loop_index].totdisp = 4; + mdisps[loop_index].level = 1; + + int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly->totloop - 1; + int next_loop_index = l + 1 < poly->totloop ? loop_index + 1 : poly->loopstart; + + MLoop *loop = &mesh->mloop[loop_index]; + MLoop *loop_next = &mesh->mloop[next_loop_index]; + MLoop *loop_prev = &mesh->mloop[prev_loop_index]; + + copy_v3_v3(disps[0], poly_center); + mid_v3_v3v3(disps[1], mesh->mvert[loop->v].co, mesh->mvert[loop_next->v].co); + mid_v3_v3v3(disps[2], mesh->mvert[loop->v].co, mesh->mvert[loop_prev->v].co); + copy_v3_v3(disps[3], mesh->mvert[loop->v].co); + } + } +} + +void multires_subdivide_create_tangent_displacement_linear_grids(Object *object, + MultiresModifierData *mmd) +{ + Mesh *coarse_mesh = object->data; + multires_force_sculpt_rebuild(object); + + MultiresReshapeContext reshape_context; + + const int new_top_level = mmd->totlvl + 1; + + const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS); + if (!has_mdisps) { + CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_CALLOC, NULL, coarse_mesh->totloop); + } + + if (new_top_level == 1) { + /* No MDISPS. Create new grids for level 1 using the edges mid point and poly centers. */ + multires_reshape_ensure_grids(coarse_mesh, 1); + multires_subdivide_create_object_space_linear_grids(coarse_mesh); + } + + /* Convert the new grids to tangent displacement. */ + multires_set_tot_level(object, mmd, new_top_level); + + if (!multires_reshape_context_create_from_subdivide( + &reshape_context, object, mmd, new_top_level)) { + return; + } + + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); + multires_reshape_context_free(&reshape_context); +} diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c index 57d790d2c34..fcee98da1c5 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.c +++ b/source/blender/blenkernel/intern/multires_reshape_util.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -43,9 +43,9 @@ #include "DEG_depsgraph_query.h" -/* ================================================================================================ - * Construct/destruct reshape context. - */ +/* -------------------------------------------------------------------- */ +/** \name Construct/destruct reshape context + * \{ */ /* Create subdivision surface descriptor which is configured for surface evaluation at a given * multires modifier. */ @@ -152,6 +152,39 @@ static bool context_verify_or_free(MultiresReshapeContext *reshape_context) return is_valid; } +bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context, + Depsgraph *depsgraph, + Object *object, + MultiresModifierData *mmd) +{ + context_zero(reshape_context); + + const bool use_render_params = false; + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Mesh *base_mesh = (Mesh *)object->data; + + reshape_context->depsgraph = depsgraph; + reshape_context->object = object; + reshape_context->mmd = mmd; + + reshape_context->base_mesh = base_mesh; + + reshape_context->subdiv = multires_reshape_create_subdiv(NULL, object, mmd); + reshape_context->need_free_subdiv = true; + + reshape_context->reshape.level = multires_get_level( + scene_eval, object, mmd, use_render_params, true); + reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level( + reshape_context->reshape.level); + + reshape_context->top.level = mmd->totlvl; + reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level); + + context_init_commoon(reshape_context); + + return context_verify_or_free(reshape_context); +} + bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context, Depsgraph *depsgraph, Object *object, @@ -272,14 +305,16 @@ void multires_reshape_context_free(MultiresReshapeContext *reshape_context) multires_reshape_free_original_grids(reshape_context); - MEM_freeN(reshape_context->face_start_grid_index); - MEM_freeN(reshape_context->ptex_start_grid_index); - MEM_freeN(reshape_context->grid_to_face_index); + MEM_SAFE_FREE(reshape_context->face_start_grid_index); + MEM_SAFE_FREE(reshape_context->ptex_start_grid_index); + MEM_SAFE_FREE(reshape_context->grid_to_face_index); } -/* ================================================================================================ - * Helper accessors. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Helper accessors + * \{ */ /* For the given grid index get index of face it was created for. */ int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context, @@ -453,9 +488,11 @@ ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord( return grid_element; } -/* ================================================================================================ - * Sample limit surface of the base mesh. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sample limit surface of the base mesh + * \{ */ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, @@ -475,9 +512,11 @@ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *resha reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix); } -/* ================================================================================================ - * Custom data preparation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Custom data preparation + * \{ */ static void allocate_displacement_grid(MDisps *displacement_grid, const int level) { @@ -539,9 +578,11 @@ void multires_reshape_ensure_grids(Mesh *mesh, const int level) ensure_mask_grids(mesh, level); } -/* ================================================================================================ - * Displacement, space conversion. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Displacement, space conversion + * \{ */ void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_context) { @@ -678,10 +719,13 @@ void multires_reshape_object_grids_to_tangent_displacement( NULL); } -/* ================================================================================================ - * MDISPS - * - * TODO(sergey): Make foreach_grid_coordinate more accessible and move this functionality to +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name MDISPS + * \{ */ + +/* TODO(sergey): Make foreach_grid_coordinate more accessible and move this functionality to * own file. */ static void assign_final_coords_from_mdisps(const MultiresReshapeContext *reshape_context, @@ -732,3 +776,5 @@ void multires_reshape_assign_final_coords_from_orig_mdisps( foreach_grid_coordinate( reshape_context, reshape_context->top.level, assign_final_coords_from_orig_mdisps, NULL); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/multires_reshape_vertcos.c b/source/blender/blenkernel/intern/multires_reshape_vertcos.c index 1ece7344f37..04df5698cf9 100644 --- a/source/blender/blenkernel/intern/multires_reshape_vertcos.c +++ b/source/blender/blenkernel/intern/multires_reshape_vertcos.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_subdiv.c b/source/blender/blenkernel/intern/multires_subdiv.c index f7e42942f3e..fc092d3ccce 100644 --- a/source/blender/blenkernel/intern/multires_subdiv.c +++ b/source/blender/blenkernel/intern/multires_subdiv.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c new file mode 100644 index 00000000000..e5000e7774f --- /dev/null +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -0,0 +1,1297 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + * + * This implements the un-subdivide algorithm, which generates a lower resolution base mesh and + * its corresponding grids to match a given original mesh. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" + +#include "BLI_gsqueue.h" +#include "BLI_math_vector.h" + +#include "BKE_customdata.h" +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_subdiv.h" +#include "BKE_subsurf.h" + +#include "bmesh.h" + +#include "DEG_depsgraph_query.h" + +#include "multires_reshape.h" +#include "multires_unsubdivide.h" + +/* This is done in the following steps: + * + * - If there are already grids in the original mesh, + * convert them from tangent displacement to object space coordinates. + * - Assign data-layers to the original mesh to map vertices to a new base mesh. + * These data-layers store the indices of the elements in the original mesh. + * This way the original indices are + * preserved when doing mesh modifications (removing and dissolving vertices) + * when building the new base mesh. + * - Try to find a lower resolution base mesh. This is done by flood fill operation that tags the + * center vertices of the lower level grid. + * If the algorithm can tag all vertices correctly, + * the lower level base mesh is generated by dissolving the tagged vertices. + * - Use the data-layers to map vertices from the base mesh to the original mesh and original to + * base mesh. + * - Find two adjacent vertices on the base mesh to a given vertex to map that loop from base mesh + * to original mesh + * - Extract the grid from the original mesh from that loop. If there are no grids in the original + * mesh, build the new grid directly from the vertex coordinates by iterating in a grid pattern + * over them. If there are grids in the original mesh, iterate in a grid pattern over the polys, + * reorder all the coordinates of the grid in that poly and copy those coordinates to the new + * base mesh grid. + * - Copy the new grid data over to a new allocated MDISP layer with the appropriate size to store + * the new levels. + * - Convert the grid data from object space to tangent displacement. + */ + +/** + * Used to check if a vertex is in a disconnected element ID. + */ +static bool is_vertex_in_id(BMVert *v, int *elem_id, int elem) +{ + const int v_index = BM_elem_index_get(v); + return elem_id[v_index] == elem; +} + +static bool is_vertex_pole_three(BMVert *v) +{ + return !BM_vert_is_boundary(v) && (BM_vert_edge_count(v) == 3); +} + +static bool is_vertex_pole(BMVert *v) +{ + return !BM_vert_is_boundary(v) && (BM_vert_edge_count(v) == 3 || BM_vert_edge_count(v) >= 5); +} + +/** + * Returns the first pole that is found in an element ID. + * + * Tries to give priority to 3 vert poles as they generally generate better results in cases were + * the un-subdivide solution is ambiguous. + */ +static BMVert *unsubdivide_find_any_pole(BMesh *bm, int *elem_id, int elem) +{ + BMIter iter; + BMVert *v; + BMVert *pole = NULL; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (is_vertex_in_id(v, elem_id, elem) && is_vertex_pole_three(v)) { + return v; + } + else if (is_vertex_in_id(v, elem_id, elem) && is_vertex_pole(v)) { + pole = v; + } + } + return pole; +} + +/** + * Checks if the mesh is all quads. + * + * TODO(pablodp606): This can perform additional checks if they are faster than trying to search + * for an un-subdivide solution. This way it is possible to cancel the operation faster. + */ +static bool unsubdivide_is_all_quads(BMesh *bm) +{ + BMIter iter; + BMIter iter_a; + BMFace *f; + BMVert *v; + int count = 0; + if (bm->totface < 3) { + return false; + } + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + count = 0; + BM_ITER_ELEM (v, &iter_a, f, BM_VERTS_OF_FACE) { + count++; + } + + if (count != 4) { + return false; + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_vert_is_wire(v)) { + return false; + } + if (BM_vert_edge_count(v) == 0) { + return false; + } + } + + return true; +} + +/** + * Returns true if from_v and to_v, which should be part of the same quad face, are diagonals. + */ +static bool is_vertex_diagonal(BMVert *from_v, BMVert *to_v) +{ + return !BM_edge_exists(from_v, to_v); +} + +/** + * Generates a possible solution for un-subdivision by tagging the (0,0) + * vertices of the possible grids. + * + * This works using a flood fill operation using the quads diagonals to jump to the next vertex. + * + * If initial_vertex is part of the base mesh solution, the flood fill should tag only the (0.0) + * vertices of the grids that need to be dissolved, and nothing else. + */ +static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex) +{ + bool *visited_vertices = MEM_calloc_arrayN(sizeof(bool), bm->totvert, "visited vertices"); + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(BMVert *)); + + /* Add and tag the vertices connected by a diagonal to initial_vertex to the flood fill queue. If + * initial_vertex is a pole and there is a valid solution, those vertices should be the (0,0) of + * the grids for the loops of initial_vertex. */ + BMIter iter; + BMIter iter_a; + BMFace *f; + BMVert *neighbor_v; + BM_ITER_ELEM (f, &iter, initial_vertex, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_a, f, BM_VERTS_OF_FACE) { + int neighbor_vertex_index = BM_elem_index_get(neighbor_v); + if (neighbor_v != initial_vertex && is_vertex_diagonal(neighbor_v, initial_vertex)) { + BLI_gsqueue_push(queue, &neighbor_v); + visited_vertices[neighbor_vertex_index] = true; + BM_elem_flag_set(neighbor_v, BM_ELEM_TAG, true); + } + } + } + + /* Repeat a similar operation for all vertices in the queue. */ + /* In this case, add to the queue the vertices connected by 2 steps using the diagonals in any + * direction. If a solution exists and intial_vertex was a pole, this is guaranteed that will tag + * all the (0,0) vertices of the grids, and nothing else. */ + /* If it was not a pole, it may or may not find a solution, even if the solution exists. */ + while (!BLI_gsqueue_is_empty(queue)) { + BMVert *from_v; + BLI_gsqueue_pop(queue, &from_v); + + /* Get the diagonals (first connected step) */ + GSQueue *diagonals; + diagonals = BLI_gsqueue_new(sizeof(BMVert *)); + BM_ITER_ELEM (f, &iter, from_v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_a, f, BM_VERTS_OF_FACE) { + if (neighbor_v != from_v && is_vertex_diagonal(neighbor_v, from_v)) { + BLI_gsqueue_push(diagonals, &neighbor_v); + } + } + } + + /* Do the second connected step. This vertices are the ones that are added to the flood fill + * queue. */ + while (!BLI_gsqueue_is_empty(diagonals)) { + BMVert *diagonal_v; + BLI_gsqueue_pop(diagonals, &diagonal_v); + BM_ITER_ELEM (f, &iter, diagonal_v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_a, f, BM_VERTS_OF_FACE) { + int neighbor_vertex_index = BM_elem_index_get(neighbor_v); + if (!visited_vertices[neighbor_vertex_index] && neighbor_v != diagonal_v && + is_vertex_diagonal(neighbor_v, diagonal_v)) { + BLI_gsqueue_push(queue, &neighbor_v); + visited_vertices[neighbor_vertex_index] = true; + BM_elem_flag_set(neighbor_v, BM_ELEM_TAG, true); + } + } + } + } + BLI_gsqueue_free(diagonals); + } + + BLI_gsqueue_free(queue); + MEM_freeN(visited_vertices); +} + +/** + * This function checks if the current status of the #BMVert tags + * corresponds to a valid un-subdivide solution. + * + * This means that all vertices corresponding to the (0,0) grid coordinate should be tagged. + * + * On a valid solution, the following things should happen: + * - No boundary vertices should be tagged + * - No vertices connected by an edge or a quad diagonal to a tagged vertex should be tagged + * - All boundary vertices should have one vertex connected by an edge or a diagonal tagged + */ +static bool unsubdivide_is_center_vertex_tag_valid(BMesh *bm, int *elem_id, int elem) +{ + BMVert *v, *neighbor_v; + BMIter iter, iter_a, iter_b; + BMFace *f; + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (is_vertex_in_id(v, elem_id, elem)) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + /* Tagged vertex in boundary */ + if (BM_vert_is_boundary(v)) { + return false; + } + /* Tagged vertex with connected tagged vertex. */ + BM_ITER_ELEM (f, &iter_a, v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_b, f, BM_VERTS_OF_FACE) { + if (neighbor_v != v && BM_elem_flag_test(neighbor_v, BM_ELEM_TAG)) { + return false; + } + } + } + } + if (BM_vert_is_boundary(v)) { + /* Un-tagged vertex in boundary without connected tagged vertices. */ + bool any_tagged = false; + BM_ITER_ELEM (f, &iter_a, v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_b, f, BM_VERTS_OF_FACE) { + if (neighbor_v != v && BM_elem_flag_test(neighbor_v, BM_ELEM_TAG)) { + any_tagged = true; + } + } + } + if (!any_tagged) { + return false; + } + } + } + } + + return true; +} + +/** + * Search and validates an un-subdivide solution for a given element ID. + */ +static bool unsubdivide_tag_disconnected_mesh_element(BMesh *bm, int *elem_id, int elem) +{ + /* First, get vertex candidates to try to generate possible un-subdivide solution. */ + /* Find a vertex pole. If there is a solution on an all quad base mesh, this vertex should be + * part of the base mesh. If it isn't, then there is no solution. */ + GSQueue *initial_vertex = BLI_gsqueue_new(sizeof(BMVert *)); + BMVert *initial_vertex_pole = unsubdivide_find_any_pole(bm, elem_id, elem); + if (initial_vertex_pole != NULL) { + BLI_gsqueue_push(initial_vertex, &initial_vertex_pole); + } + + /* Also try from the different 4 vertices of a quad in the current + * disconnected element ID. If a solution exists the search should return a valid solution from + * one of these vertices.*/ + BMFace *f, *init_face = NULL; + BMVert *v; + BMIter iter_a, iter_b; + BM_ITER_MESH (f, &iter_a, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) { + if (is_vertex_in_id(v, elem_id, elem)) { + init_face = f; + break; + } + } + if (init_face != NULL) { + break; + } + } + + BM_ITER_ELEM (v, &iter_a, init_face, BM_VERTS_OF_FACE) { + BLI_gsqueue_push(initial_vertex, &v); + } + + bool valid_tag_found = false; + + /* Check all vertex candidates to a solution. */ + while (!BLI_gsqueue_is_empty(initial_vertex)) { + + BMVert *iv; + BLI_gsqueue_pop(initial_vertex, &iv); + + /* Generate a possible solution. */ + unsubdivide_face_center_vertex_tag(bm, iv); + + /* Check if the solution is valid. If it is, stop searching. */ + if (unsubdivide_is_center_vertex_tag_valid(bm, elem_id, elem)) { + valid_tag_found = true; + break; + } + + /* If the solution is not valid, reset the state of all tags in this disconnected element ID + * and try again. */ + BMVert *v_reset; + BMIter iter; + BM_ITER_MESH (v_reset, &iter, bm, BM_VERTS_OF_MESH) { + if (is_vertex_in_id(v_reset, elem_id, elem)) { + BM_elem_flag_set(v_reset, BM_ELEM_TAG, false); + } + } + } + BLI_gsqueue_free(initial_vertex); + return valid_tag_found; +} + +/** + * Uses a flood fill operation to generate a different ID for each disconnected mesh element. + */ +static int unsubdivide_init_elem_ids(BMesh *bm, int *elem_id) +{ + bool *visited_vertices = MEM_calloc_arrayN(sizeof(bool), bm->totvert, "visited vertices"); + int current_id = 0; + for (int i = 0; i < bm->totvert; i++) { + if (!visited_vertices[i]) { + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(BMVert *)); + + visited_vertices[i] = true; + elem_id[i] = current_id; + BMVert *iv = BM_vert_at_index(bm, i); + BLI_gsqueue_push(queue, &iv); + + while (!BLI_gsqueue_is_empty(queue)) { + BMIter iter; + BMVert *current_v, *neighbor_v; + BMEdge *ed; + BLI_gsqueue_pop(queue, ¤t_v); + BM_ITER_ELEM (ed, &iter, current_v, BM_EDGES_OF_VERT) { + neighbor_v = BM_edge_other_vert(ed, current_v); + const int neighbor_index = BM_elem_index_get(neighbor_v); + if (!visited_vertices[neighbor_index]) { + visited_vertices[neighbor_index] = true; + elem_id[neighbor_index] = current_id; + BLI_gsqueue_push(queue, &neighbor_v); + } + } + } + current_id++; + BLI_gsqueue_free(queue); + } + } + MEM_freeN(visited_vertices); + return current_id; +} + +/** + * Builds a base mesh one subdivision level down from the current original mesh if the original + * mesh has a valid solution stored in the #BMVert tags. + */ +static void unsubdivide_build_base_mesh_from_tags(BMesh *bm) +{ + BMVert *v; + BMIter iter; + + /* Stores the vertices which correspond to (1, 0) and (0, 1) of the grids in the select flag. */ + BM_mesh_elem_hflag_enable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + BMVert *v_neighbor; + BMIter iter_a; + BMEdge *ed; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_ELEM (ed, &iter_a, v, BM_EDGES_OF_VERT) { + v_neighbor = BM_edge_other_vert(ed, v); + if (BM_elem_flag_test(v_neighbor, BM_ELEM_TAG)) { + BM_elem_flag_set(v, BM_ELEM_SELECT, false); + } + } + } + + /* Dissolves the (0,0) vertices of the grids. */ + BMO_op_callf(bm, + (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_TAG, + false, + true); + + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + + /* Copy the select flag to the tag flag. */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BM_elem_flag_set(v, BM_ELEM_TAG, true); + } + } + + /* Dissolves the (1,0) and (0,1) vertices of the grids. */ + BMO_op_callf(bm, + (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_TAG, + false, + true); +} + +/** + * Main function to get a base mesh one level down from the current original mesh if it exists. + * + * This searches for different un-subdivide solutions and stores them as a combination of #BMVert + * flags for each disconnected mesh element. + * + * If the solution for all elements are valid, it builds a new base mesh based on those tags by + * dissolving and merging vertices. + */ +static bool multires_unsubdivide_single_level(BMesh *bm) +{ + + /* Do a first check to make sure that it makes sense to search for un-subdivision in this mesh. + */ + if (!unsubdivide_is_all_quads(bm)) { + return false; + }; + + /* Initialize the vertex table. */ + BM_mesh_elem_table_init(bm, BM_VERT); + BM_mesh_elem_table_ensure(bm, BM_VERT); + + /* Build disconnected elements IDs. Each disconnected mesh element is evaluated separately. */ + int *elem_id = MEM_calloc_arrayN(sizeof(int), bm->totvert, " ELEM ID"); + const int tot_ids = unsubdivide_init_elem_ids(bm, elem_id); + + bool valid_tag_found = true; + + /* Reset the #BMesh flags as they are used to store data during the un-subdivide process. */ + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + + /* For each disconnected mesh element ID, search if an un-subdivide solution is possible. The + * whole un-subdivide process fails if a single disconnected mesh element fails. */ + for (int id = 0; id < tot_ids; id++) { + /* Try to the #BMesh vertex flag tags corresponding to an un-subdivide solution. */ + if (!unsubdivide_tag_disconnected_mesh_element(bm, elem_id, id)) { + valid_tag_found = false; + break; + } + } + + /* If a solution was found for all elements IDs, build the new base mesh using the solution + * stored in the BMVert tags. */ + if (valid_tag_found) { + unsubdivide_build_base_mesh_from_tags(bm); + } + + MEM_freeN(elem_id); + return valid_tag_found; +} + +/** + * Returns the next edge and vertex in the direction of a given edge. + */ +static BMEdge *edge_step(BMVert *v, BMEdge *edge, BMVert **r_next_vertex) +{ + BMIter iter; + BMEdge *test_edge; + if (edge == NULL) { + (*r_next_vertex) = v; + return edge; + } + (*r_next_vertex) = BM_edge_other_vert(edge, v); + BM_ITER_ELEM (test_edge, &iter, (*r_next_vertex), BM_EDGES_OF_VERT) { + if (!BM_edge_share_quad_check(test_edge, edge)) { + return test_edge; + } + } + return NULL; +} + +static BMFace *face_step(BMEdge *edge, BMFace *f) +{ + BMIter iter; + BMFace *face_iter; + + BM_ITER_ELEM (face_iter, &iter, edge, BM_FACES_OF_EDGE) { + if (BM_face_share_edge_check(face_iter, f)) { + return face_iter; + } + } + return f; +} + +/** + * Returns the other edge which belongs to the face f which is different from edge_x and shares + * initial_vertex. + */ +static BMEdge *get_initial_edge_y(BMFace *f, BMEdge *edge_x, BMVert *initial_vertex) +{ + BMIter iter; + BMEdge *test_edge; + BM_ITER_ELEM (test_edge, &iter, f, BM_EDGES_OF_FACE) { + if (edge_x != test_edge) { + if (test_edge->v1 != initial_vertex && test_edge->v2 == initial_vertex) { + return test_edge; + } + if (test_edge->v2 != initial_vertex && test_edge->v1 == initial_vertex) { + return test_edge; + } + } + } + return NULL; +} + +/** + * Writes the current mdisp data into the corresponding area of quad poly giving its corner's loop. + */ +static void write_loop_in_face_grid( + float (*face_grid)[3], MDisps *mdisp, int face_grid_size, int orig_grid_size, int loop) +{ + int origin[2]; + int step_x[2]; + int step_y[2]; + + const int grid_offset = orig_grid_size - 1; + origin[0] = grid_offset; + origin[1] = grid_offset; + + switch (loop) { + case 0: + step_x[0] = -1; + step_x[1] = 0; + + step_y[0] = 0; + step_y[1] = -1; + + break; + case 1: + step_x[0] = 0; + step_x[1] = 1; + + step_y[0] = -1; + step_y[1] = -0; + break; + case 2: + step_x[0] = 1; + step_x[1] = 0; + + step_y[0] = 0; + step_y[1] = 1; + break; + case 3: + step_x[0] = 0; + step_x[1] = -1; + + step_y[0] = 1; + step_y[1] = 0; + break; + default: + BLI_assert(!"Should never happen"); + break; + } + + for (int y = 0; y < orig_grid_size; y++) { + for (int x = 0; x < orig_grid_size; x++) { + const int remap_x = origin[1] + (step_x[1] * x) + (step_y[1] * y); + const int remap_y = origin[0] + (step_x[0] * x) + (step_y[0] * y); + + const int final_index = remap_x + remap_y * face_grid_size; + copy_v3_v3(face_grid[final_index], mdisp->disps[x + y * orig_grid_size]); + } + } +} + +/** + * Writes a buffer containing the 4 grids in the correct orientation of the 4 loops of a face into + * the main #MultiresUnsubdivideGrid that is being extracted. + */ +static void write_face_grid_in_unsubdivide_grid(MultiresUnsubdivideGrid *grid, + float (*face_grid)[3], + int face_grid_size, + int gunsub_x, + int gunsub_y) +{ + const int grid_it = face_grid_size - 1; + for (int y = 0; y < face_grid_size; y++) { + for (int x = 0; x < face_grid_size; x++) { + const int remap_x = (grid_it * gunsub_x) + x; + const int remap_y = (grid_it * gunsub_y) + y; + + const int remap_index_y = grid->grid_size - remap_x - 1; + const int remap_index_x = grid->grid_size - remap_y - 1; + const int grid_index = remap_index_x + (remap_index_y * grid->grid_size); + copy_v3_v3(grid->grid_co[grid_index], face_grid[x + y * face_grid_size]); + } + } +} + +/** + * Stores the data from the mdisps grids of the loops of the face f + * into the new grid for the new base mesh. + * + * Used when there are already grids in the original mesh. + */ +static void store_grid_data(MultiresUnsubdivideContext *context, + MultiresUnsubdivideGrid *grid, + BMVert *v, + BMFace *f, + int grid_x, + int grid_y) +{ + + Mesh *original_mesh = context->original_mesh; + MPoly *poly = &original_mesh->mpoly[BM_elem_index_get(f)]; + + const int corner_vertex_index = BM_elem_index_get(v); + + /* Calculates an offset to write the grids correctly oriented in the main + * #MultiresUnsubdivideGrid. */ + int loop_offset = 0; + for (int i = 0; i < poly->totloop; i++) { + const int loop_index = poly->loopstart + i; + MLoop *l = &original_mesh->mloop[loop_index]; + if (l->v == corner_vertex_index) { + loop_offset = i; + break; + } + } + + /* Write the 4 grids of the current quad with the right orientation into the face_grid buffer. */ + const int grid_size = BKE_ccg_gridsize(context->num_original_levels); + const int face_grid_size = BKE_ccg_gridsize(context->num_original_levels + 1); + const int face_grid_area = face_grid_size * face_grid_size; + float(*face_grid)[3] = MEM_calloc_arrayN(face_grid_area, 3 * sizeof(float), "face_grid"); + + for (int i = 0; i < poly->totloop; i++) { + const int loop_index = poly->loopstart + i; + MDisps *mdisp = &context->original_mdisp[loop_index]; + int quad_loop = i - loop_offset; + if (quad_loop < 0) { + quad_loop += 4; + } + if (quad_loop >= 4) { + quad_loop -= 4; + } + write_loop_in_face_grid(face_grid, mdisp, face_grid_size, grid_size, quad_loop); + } + + /* Write the face_grid buffer in the correct position in the #MultiresUnsubdivideGrids that is + * being extracted. */ + write_face_grid_in_unsubdivide_grid(grid, face_grid, face_grid_size, grid_x, grid_y); + + MEM_freeN(face_grid); +} + +/** + * Stores the data into the new grid from a #BMVert. + * Used when there are no grids in the original mesh. + */ +static void store_vertex_data(MultiresUnsubdivideGrid *grid, BMVert *v, int grid_x, int grid_y) +{ + const int remap_index_y = grid->grid_size - 1 - grid_x; + const int remap_index_x = grid->grid_size - 1 - grid_y; + + const int grid_index = remap_index_x + (remap_index_y * grid->grid_size); + + copy_v3_v3(grid->grid_co[grid_index], v->co); +} + +/** + * Main function to extract data from the original bmesh and MDISPS as grids for the new base mesh. + */ +static void multires_unsubdivide_extract_single_grid_from_face_edge( + MultiresUnsubdivideContext *context, + BMFace *f1, + BMEdge *e1, + bool flip_grid, + MultiresUnsubdivideGrid *grid) +{ + BMVert *initial_vertex; + BMEdge *initial_edge_x; + BMEdge *initial_edge_y; + + const int grid_size = BKE_ccg_gridsize(context->num_new_levels); + const int unsubdiv_grid_size = grid->grid_size = BKE_ccg_gridsize(context->num_total_levels); + grid->grid_size = unsubdiv_grid_size; + grid->grid_co = MEM_calloc_arrayN( + unsubdiv_grid_size * unsubdiv_grid_size, 3 * sizeof(float), "grids coordinates"); + + /* Get the vertex on the corner of the grid. This vertex was tagged previously as it also exist + * on the base mesh. */ + initial_edge_x = e1; + if (BM_elem_flag_test(initial_edge_x->v1, BM_ELEM_TAG)) { + initial_vertex = initial_edge_x->v1; + } + else { + initial_vertex = initial_edge_x->v2; + } + + /* From that vertex, get the edge that defines the grid Y axis for extraction. */ + initial_edge_y = get_initial_edge_y(f1, initial_edge_x, initial_vertex); + + if (flip_grid) { + BMEdge *edge_temp; + edge_temp = initial_edge_x; + initial_edge_x = initial_edge_y; + initial_edge_y = edge_temp; + } + + int grid_x = 0; + int grid_y = 0; + + BMVert *current_vertex_x = initial_vertex; + BMEdge *edge_x = initial_edge_x; + + BMVert *current_vertex_y = initial_vertex; + BMEdge *edge_y = initial_edge_y; + BMEdge *prev_edge_y = initial_edge_y; + + BMFace *current_face = f1; + BMFace *grid_face = f1; + + /* If the data is going to be extracted from the already existing grids, there is no need to go + * to the last vertex of the iteration as that coordinate is also included in the grids + * corresponding to the loop of the face of the previous iteration. */ + int grid_iteration_max_steps = grid_size; + if (context->num_original_levels > 0) { + grid_iteration_max_steps = grid_size - 1; + } + + /* Iterate over the mesh vertices in a grid pattern using the axis defined by the two initial + * edges. */ + while (grid_y < grid_iteration_max_steps) { + + grid_face = current_face; + + while (grid_x < grid_iteration_max_steps) { + if (context->num_original_levels == 0) { + /* If there were no grids on the original mesh, extract the data directly from the + * vertices. */ + store_vertex_data(grid, current_vertex_x, grid_x, grid_y); + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + } + else { + /* If there were grids in the original mesh, extract the data from the grids and iterate + * over the faces. */ + store_grid_data(context, grid, current_vertex_x, grid_face, grid_x, grid_y); + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + grid_face = face_step(edge_x, grid_face); + } + + grid_x++; + } + grid_x = 0; + + edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y); + current_vertex_x = current_vertex_y; + + /* Get the next edge_x to extract the next row of the grid. This needs to be done because there + * may be two edges connected to current_vertex_x that belong to two different grids. */ + BMIter iter; + BMEdge *ed; + BMFace *f; + BM_ITER_ELEM (ed, &iter, current_vertex_x, BM_EDGES_OF_VERT) { + if (ed != prev_edge_y && BM_edge_in_face(ed, current_face)) { + edge_x = ed; + break; + } + } + BM_ITER_ELEM (f, &iter, edge_x, BM_FACES_OF_EDGE) { + if (f != current_face) { + current_face = f; + break; + } + } + + prev_edge_y = edge_y; + grid_y++; + } +} + +/** + * Returns the l+1 and l-1 vertices of the base mesh poly were the grid from the face f1 and edge + * e1 is going to be extracted. + * + * These vertices should always have an corresponding existing vertex on the base mesh. + */ +static void multires_unsubdivide_get_grid_corners_on_base_mesh(BMFace *f1, + BMEdge *e1, + BMVert **r_corner_x, + BMVert **r_corner_y) +{ + BMVert *initial_vertex; + BMEdge *initial_edge_x; + BMEdge *initial_edge_y; + + initial_edge_x = e1; + if (BM_elem_flag_test(initial_edge_x->v1, BM_ELEM_TAG)) { + initial_vertex = initial_edge_x->v1; + } + else { + initial_vertex = initial_edge_x->v2; + } + + /* From that vertex, get the edge that defines the grid Y axis for extraction. */ + initial_edge_y = get_initial_edge_y(f1, initial_edge_x, initial_vertex); + + BMVert *current_vertex_x = initial_vertex; + BMEdge *edge_x = initial_edge_x; + + BMVert *current_vertex_y = initial_vertex; + BMEdge *edge_y = initial_edge_y; + + /* Do an edge step until it finds a tagged vertex, which is part of the base mesh. */ + /* x axis */ + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + while (!BM_elem_flag_test(current_vertex_x, BM_ELEM_TAG)) { + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + } + (*r_corner_x) = current_vertex_x; + + /* Same for y axis */ + edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y); + while (!BM_elem_flag_test(current_vertex_y, BM_ELEM_TAG)) { + edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y); + } + (*r_corner_y) = current_vertex_y; +} + +static BMesh *get_bmesh_from_mesh(Mesh *mesh) +{ + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); + BMesh *bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + BM_mesh_bm_from_me(bm, + mesh, + (&(struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + return bm; +} + +/* Data-layer names to store the original indices of the elements before modifying the mesh. */ +static const char lname[] = "l_remap_index"; +static const char vname[] = "v_remap_index"; + +static void multires_unsubdivide_free_original_datalayers(Mesh *mesh) +{ + const int l_layer_index = CustomData_get_named_layer_index(&mesh->ldata, CD_PROP_INT, lname); + if (l_layer_index != -1) { + CustomData_free_layer(&mesh->ldata, CD_PROP_INT, mesh->totloop, l_layer_index); + } + + const int v_layer_index = CustomData_get_named_layer_index(&mesh->vdata, CD_PROP_INT, vname); + if (v_layer_index != -1) { + CustomData_free_layer(&mesh->vdata, CD_PROP_INT, mesh->totvert, v_layer_index); + } +} + +/** + * Generates two data-layers to map loops and vertices from base mesh to original mesh after + * dissolving the vertices. + */ +static void multires_unsubdivide_add_original_index_datalayers(Mesh *mesh) +{ + multires_unsubdivide_free_original_datalayers(mesh); + + int *l_index = CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT, CD_CALLOC, NULL, mesh->totloop, lname); + + int *v_index = CustomData_add_layer_named( + &mesh->vdata, CD_PROP_INT, CD_CALLOC, NULL, mesh->totvert, vname); + + /* Initialize these data-layer with the indices in the current mesh. */ + for (int i = 0; i < mesh->totloop; i++) { + l_index[i] = i; + } + for (int i = 0; i < mesh->totvert; i++) { + v_index[i] = i; + } +} + +static void multires_unsubdivide_prepare_original_bmesh_for_extract( + MultiresUnsubdivideContext *context) +{ + + Mesh *original_mesh = context->original_mesh; + Mesh *base_mesh = context->base_mesh; + + BMesh *bm_original_mesh = context->bm_original_mesh = get_bmesh_from_mesh(original_mesh); + + /* Initialize the elem tables. */ + BM_mesh_elem_table_ensure(bm_original_mesh, BM_EDGE); + BM_mesh_elem_table_ensure(bm_original_mesh, BM_FACE); + BM_mesh_elem_table_ensure(bm_original_mesh, BM_VERT); + + /* Disable all flags. */ + BM_mesh_elem_hflag_disable_all( + bm_original_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BM_mesh_elem_hflag_disable_all( + bm_original_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + + /* Get the mapping data-layer. */ + context->base_to_orig_vmap = CustomData_get_layer_named(&base_mesh->vdata, CD_PROP_INT, vname); + + /* Tag the base mesh vertices in the original mesh. */ + for (int i = 0; i < base_mesh->totvert; i++) { + int vert_basemesh_index = context->base_to_orig_vmap[i]; + BMVert *v = BM_vert_at_index(bm_original_mesh, vert_basemesh_index); + BM_elem_flag_set(v, BM_ELEM_TAG, true); + } + + /* Create a map from loop index to poly index for the original mesh. */ + context->loop_to_face_map = MEM_calloc_arrayN(sizeof(int), original_mesh->totloop, "loop map"); + + for (int i = 0; i < original_mesh->totpoly; i++) { + MPoly *poly = &original_mesh->mpoly[i]; + for (int l = 0; l < poly->totloop; l++) { + int original_loop_index = l + poly->loopstart; + context->loop_to_face_map[original_loop_index] = i; + } + } +} + +/** + * Checks the orientation of the loops to flip the x and y axis when extracting the grid if + * necessary. + */ +static bool multires_unsubdivide_flip_grid_x_axis(Mesh *mesh, int poly, int loop, int v_x) +{ + MPoly *p = &mesh->mpoly[poly]; + + MLoop *l_first = &mesh->mloop[p->loopstart]; + if ((loop == (p->loopstart + (p->totloop - 1))) && l_first->v == v_x) { + return true; + } + + int next_l_index = loop + 1; + if (next_l_index < p->loopstart + p->totloop) { + MLoop *l_next = &mesh->mloop[next_l_index]; + if (l_next->v == v_x) { + return true; + } + } + + return false; +} + +static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *context) +{ + Mesh *original_mesh = context->original_mesh; + Mesh *base_mesh = context->base_mesh; + + BMesh *bm_original_mesh = context->bm_original_mesh; + + context->num_grids = base_mesh->totloop; + context->base_mesh_grids = MEM_calloc_arrayN( + sizeof(MultiresUnsubdivideGrid), base_mesh->totloop, "grids"); + + /* Based on the existing indices in the data-layers, generate two vertex indices maps. */ + /* From vertex index in original to vertex index in base and from vertex index in base to vertex + * index in original. */ + int *orig_to_base_vmap = MEM_calloc_arrayN(sizeof(int), bm_original_mesh->totvert, "orig vmap"); + int *base_to_orig_vmap = MEM_calloc_arrayN(sizeof(int), base_mesh->totvert, "base vmap"); + + context->base_to_orig_vmap = CustomData_get_layer_named(&base_mesh->vdata, CD_PROP_INT, vname); + for (int i = 0; i < base_mesh->totvert; i++) { + base_to_orig_vmap[i] = context->base_to_orig_vmap[i]; + } + + /* If an index in original does not exist in base (it was dissolved when creating the new base + * mesh, return -1. */ + for (int i = 0; i < original_mesh->totvert; i++) { + orig_to_base_vmap[i] = -1; + } + + for (int i = 0; i < base_mesh->totvert; i++) { + const int orig_vertex_index = context->base_to_orig_vmap[i]; + orig_to_base_vmap[orig_vertex_index] = i; + } + + /* Add the original data-layers to the base mesh to have the loop indices stored in a data-layer, + * so they can be used from #BMesh. */ + multires_unsubdivide_add_original_index_datalayers(base_mesh); + + const int base_l_layer_index = CustomData_get_named_layer_index( + &base_mesh->ldata, CD_PROP_INT, lname); + BMesh *bm_base_mesh = get_bmesh_from_mesh(base_mesh); + BMIter iter, iter_a, iter_b; + BMVert *v; + BMLoop *l, *lb; + + BM_mesh_elem_table_ensure(bm_base_mesh, BM_VERT); + BM_mesh_elem_table_ensure(bm_base_mesh, BM_FACE); + + /* Get the data-layer that contains the loops indices. */ + const int base_l_offset = CustomData_get_n_offset( + &bm_base_mesh->ldata, CD_PROP_INT, base_l_layer_index); + + /* Main loop for extracting the grids. Iterates over the base mesh vertices. */ + BM_ITER_MESH (v, &iter, bm_base_mesh, BM_VERTS_OF_MESH) { + + /* For each base mesh vertex, get the corresponding #BMVert of the original mesh using the + * vertex map. */ + const int orig_vertex_index = base_to_orig_vmap[BM_elem_index_get(v)]; + BMVert *vert_original = BM_vert_at_index(bm_original_mesh, orig_vertex_index); + + /* Iterate over the loops of that vertex in the original mesh. */ + BM_ITER_ELEM (l, &iter_a, vert_original, BM_LOOPS_OF_VERT) { + /* For each loop, get the two vertices that should map to the l+1 and l-1 vertices in the + * base mesh of the poly of grid that is going to be extracted. */ + BMVert *corner_x, *corner_y; + multires_unsubdivide_get_grid_corners_on_base_mesh(l->f, l->e, &corner_x, &corner_y); + + /* Map the two obtained vertices to the base mesh. */ + const int corner_x_index = orig_to_base_vmap[BM_elem_index_get(corner_x)]; + const int corner_y_index = orig_to_base_vmap[BM_elem_index_get(corner_y)]; + + /* Iterate over the loops of the same vertex in the base mesh. With the previously obtained + * vertices and the current vertex it is possible to get the index of the loop in the base + * mesh the grid that is going to be extracted belongs to. */ + BM_ITER_ELEM (lb, &iter_b, v, BM_LOOPS_OF_VERT) { + BMFace *base_face = lb->f; + BMVert *base_corner_x = BM_vert_at_index(bm_base_mesh, corner_x_index); + BMVert *base_corner_y = BM_vert_at_index(bm_base_mesh, corner_y_index); + /* If this is the correct loop in the base mesh, the original vertex and the two corners + * should be in the loop's face. */ + if (BM_vert_in_face(base_corner_x, base_face) && + BM_vert_in_face(base_corner_y, base_face)) { + /* Get the index of the loop. */ + const int base_mesh_loop_index = BM_ELEM_CD_GET_INT(lb, base_l_offset); + const int base_mesh_face_index = BM_elem_index_get(base_face); + + /* Check the orientation of the loops in case that is needed to flip the x and y axis + * when extracting the grid. */ + const bool flip_grid = multires_unsubdivide_flip_grid_x_axis( + base_mesh, base_mesh_face_index, base_mesh_loop_index, corner_x_index); + + /* Extract the grid for that loop. */ + context->base_mesh_grids[base_mesh_loop_index].grid_index = base_mesh_loop_index; + multires_unsubdivide_extract_single_grid_from_face_edge( + context, l->f, l->e, !flip_grid, &context->base_mesh_grids[base_mesh_loop_index]); + + break; + } + } + } + } + + MEM_freeN(orig_to_base_vmap); + MEM_freeN(base_to_orig_vmap); + + BM_mesh_free(bm_base_mesh); + multires_unsubdivide_free_original_datalayers(base_mesh); +} + +static void multires_unsubdivide_private_extract_data_free(MultiresUnsubdivideContext *context) +{ + if (context->bm_original_mesh != NULL) { + BM_mesh_free(context->bm_original_mesh); + } + MEM_SAFE_FREE(context->loop_to_face_map); +} + +void multires_unsubdivide_context_init(MultiresUnsubdivideContext *context, + Mesh *original_mesh, + struct MultiresModifierData *mmd) +{ + context->original_mesh = original_mesh; + context->num_new_levels = 0; + context->num_total_levels = 0; + context->num_original_levels = mmd->totlvl; +} + +bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context) +{ + Mesh *original_mesh = context->original_mesh; + + /* Prepare the data-layers to map base to original. */ + multires_unsubdivide_add_original_index_datalayers(original_mesh); + BMesh *bm_base_mesh = get_bmesh_from_mesh(original_mesh); + + /* Un-subdivide as many iterations as possible. */ + context->num_new_levels = 0; + int num_levels_left = context->max_new_levels; + while (num_levels_left > 0 && multires_unsubdivide_single_level(bm_base_mesh)) { + context->num_new_levels++; + num_levels_left--; + } + + /* If no un-subdivide steps were possible, free the bmesh, the map data-layers and stop. */ + if (context->num_new_levels == 0) { + multires_unsubdivide_free_original_datalayers(original_mesh); + BM_mesh_free(bm_base_mesh); + return false; + } + + /* Calculate the final levels for the new grids over base mesh. */ + context->num_total_levels = context->num_new_levels + context->num_original_levels; + + /* Store the new base-mesh as a mesh in context, free bmesh. */ + context->base_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0); + BM_mesh_bm_to_me(NULL, + bm_base_mesh, + context->base_mesh, + (&(struct BMeshToMeshParams){ + .calc_object_remap = true, + })); + BM_mesh_free(bm_base_mesh); + + /* Initialize bmesh and maps for the original mesh and extract the grids. */ + + multires_unsubdivide_prepare_original_bmesh_for_extract(context); + multires_unsubdivide_extract_grids(context); + + return true; +} + +void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context) +{ + multires_unsubdivide_private_extract_data_free(context); + for (int i = 0; i < context->num_grids; i++) { + if (context->base_mesh_grids[i].grid_size > 0) { + MEM_SAFE_FREE(context->base_mesh_grids[i].grid_co); + } + } + MEM_SAFE_FREE(context->base_mesh_grids); +} + +/** + * This function allocates new mdisps with the right size to fit the new extracted grids from the + * base mesh and copies the data to them. + */ +static void multires_create_grids_in_unsubdivided_base_mesh(MultiresUnsubdivideContext *context, + Mesh *base_mesh) +{ + /* Free the current MDISPS and create a new ones. */ + if (CustomData_has_layer(&base_mesh->ldata, CD_MDISPS)) { + CustomData_free_layers(&base_mesh->ldata, CD_MDISPS, base_mesh->totloop); + } + MDisps *mdisps = CustomData_add_layer( + &base_mesh->ldata, CD_MDISPS, CD_CALLOC, NULL, base_mesh->totloop); + + const int totdisp = pow_i(BKE_ccg_gridsize(context->num_total_levels), 2); + const int totloop = base_mesh->totloop; + + BLI_assert(base_mesh->totloop == context->num_grids); + + /* Allocate the MDISPS grids and copy the extracted data from context. */ + for (int i = 0; i < totloop; i++) { + float(*disps)[3] = MEM_calloc_arrayN(totdisp, 3 * sizeof(float), "multires disps"); + + if (mdisps[i].disps) { + MEM_freeN(mdisps[i].disps); + } + + for (int j = 0; j < totdisp; j++) { + if (context->base_mesh_grids[i].grid_co) { + copy_v3_v3(disps[j], context->base_mesh_grids[i].grid_co[j]); + } + } + + mdisps[i].disps = disps; + mdisps[i].totdisp = totdisp; + mdisps[i].level = context->num_total_levels; + } +} + +int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph, + struct Object *object, + struct MultiresModifierData *mmd, + int rebuild_limit, + bool switch_view_to_lower_level) +{ + Mesh *mesh = object->data; + + multires_force_sculpt_rebuild(object); + + MultiresUnsubdivideContext unsubdiv_context = {0}; + MultiresReshapeContext reshape_context = {0}; + + multires_unsubdivide_context_init(&unsubdiv_context, mesh, mmd); + + /* Convert and store the existing grids in object space if available. */ + if (mmd->totlvl != 0) { + if (!multires_reshape_context_create_from_object(&reshape_context, depsgraph, object, mmd)) { + return 0; + } + + multires_reshape_store_original_grids(&reshape_context); + multires_reshape_assign_final_coords_from_mdisps(&reshape_context); + unsubdiv_context.original_mdisp = reshape_context.mdisps; + } + + /* Set the limit for the levels that should be rebuild. */ + unsubdiv_context.max_new_levels = rebuild_limit; + + /* Un-subdivide and create the data for the new grids. */ + if (multires_unsubdivide_to_basemesh(&unsubdiv_context) == 0) { + /* If there was no possible to rebuild any level, free the data and return. */ + if (mmd->totlvl != 0) { + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); + multires_unsubdivide_context_free(&unsubdiv_context); + } + multires_reshape_context_free(&reshape_context); + return 0; + } + + /* Free the reshape context used to convert the data from the original grids to object space. */ + if (mmd->totlvl != 0) { + multires_reshape_context_free(&reshape_context); + } + + /* Copy the new base mesh to the original mesh. */ + BKE_mesh_nomain_to_mesh(unsubdiv_context.base_mesh, object->data, object, &CD_MASK_MESH, true); + Mesh *base_mesh = object->data; + multires_create_grids_in_unsubdivided_base_mesh(&unsubdiv_context, base_mesh); + + /* Update the levels in the modifier. Force always to display at level 0 as it contains the new + * created level. */ + mmd->totlvl = (char)unsubdiv_context.num_total_levels; + + if (switch_view_to_lower_level) { + mmd->sculptlvl = 0; + mmd->lvl = 0; + } + else { + mmd->sculptlvl = (char)(mmd->sculptlvl + unsubdiv_context.num_new_levels); + mmd->lvl = (char)(mmd->lvl + unsubdiv_context.num_new_levels); + } + + mmd->renderlvl = (char)(mmd->renderlvl + unsubdiv_context.num_new_levels); + + /* Create a reshape context to convert the MDISPS data to tangent displacement. It can be the + * same as the previous one as a new Subdivision needs to be created for the new base mesh. */ + if (!multires_reshape_context_create_from_base_mesh(&reshape_context, depsgraph, object, mmd)) { + return 0; + } + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); + multires_reshape_context_free(&reshape_context); + + /* Free the un-subdivide context and return the total number of levels that were rebuild. */ + const int rebuild_subdvis = unsubdiv_context.num_new_levels; + multires_unsubdivide_context_free(&unsubdiv_context); + + return rebuild_subdvis; +} diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.h b/source/blender/blenkernel/intern/multires_unsubdivide.h new file mode 100644 index 00000000000..e00a1ae6d8b --- /dev/null +++ b/source/blender/blenkernel/intern/multires_unsubdivide.h @@ -0,0 +1,94 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#ifndef __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ +#define __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ + +#include "BLI_sys_types.h" + +struct BMesh; +struct Depsgraph; +struct Mesh; +struct MultiresModifierData; +struct Object; + +typedef struct MultiresUnsubdivideGrid { + /* For sanity checks. */ + int grid_index; + int grid_size; + + /** Grid coordinates in object space. */ + float (*grid_co)[3]; + +} MultiresUnsubdivideGrid; + +typedef struct MultiresUnsubdivideContext { + /* Input Mesh to un-subdivide. */ + struct Mesh *original_mesh; + struct MDisps *original_mdisp; + + /** Number of subdivision in the grids of the input mesh. */ + int num_original_levels; + + /** Level 0 base mesh after applying the maximum amount of unsubdivisions. */ + struct Mesh *base_mesh; + + /** Limit on how many levels down the unsubdivide operation should create, if possible. */ + int max_new_levels; + + /** New levels that were created after unsubdividing. */ + int num_new_levels; + + /** + * Number of subdivisions that should be applied to the base mesh. + * (num_new_levels + num_original_levels). + */ + int num_total_levels; + + /** Data for the new grids, indexed by base mesh loop index. */ + int num_grids; + struct MultiresUnsubdivideGrid *base_mesh_grids; + + /* Private data. */ + struct BMesh *bm_original_mesh; + int *loop_to_face_map; + int *base_to_orig_vmap; +} MultiresUnsubdivideContext; + +/* -------------------------------------------------------------------- + * Construct/destruct reshape context. + */ + +void multires_unsubdivide_context_init(MultiresUnsubdivideContext *context, + struct Mesh *original_mesh, + struct MultiresModifierData *mmd); +void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context); + +/* -------------------------------------------------------------------- + * Rebuild Lower Subdivisions. + */ + +/* Rebuilds all subdivision to the level 0 base mesh. */ +bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context); + +#endif /* __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 5ae44247e13..48c6727add5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -32,11 +32,13 @@ #include "DNA_action_types.h" #include "DNA_anim_types.h" +#include "DNA_gpencil_types.h" #include "DNA_light_types.h" #include "DNA_linestyle_types.h" #include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" +#include "DNA_simulation_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" @@ -56,6 +58,7 @@ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_node.h" @@ -66,7 +69,9 @@ #include "NOD_common.h" #include "NOD_composite.h" +#include "NOD_function.h" #include "NOD_shader.h" +#include "NOD_simulation.h" #include "NOD_socket.h" #include "NOD_texture.h" @@ -86,7 +91,9 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo); static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag); static void free_localized_node_groups(bNodeTree *ntree); static void node_free_node(bNodeTree *ntree, bNode *node); -static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock); +static void node_socket_interface_free(bNodeTree *UNUSED(ntree), + bNodeSocket *sock, + const bool do_id_user); static void ntree_init_data(ID *id) { @@ -229,12 +236,12 @@ static void ntree_free_data(ID *id) /* free interface sockets */ for (sock = ntree->inputs.first; sock; sock = nextsock) { nextsock = sock->next; - node_socket_interface_free(ntree, sock); + node_socket_interface_free(ntree, sock, false); MEM_freeN(sock); } for (sock = ntree->outputs.first; sock; sock = nextsock) { nextsock = sock->next; - node_socket_interface_free(ntree, sock); + node_socket_interface_free(ntree, sock, false); MEM_freeN(sock); } @@ -248,6 +255,66 @@ static void ntree_free_data(ID *id) } } +static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock) +{ + IDP_foreach_property( + sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + +static void node_foreach_id(ID *id, LibraryForeachIDData *data) +{ + bNodeTree *ntree = (bNodeTree *)id; + + BKE_LIB_FOREACHID_PROCESS(data, ntree->gpd, IDWALK_CB_USER); + + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER); + + IDP_foreach_property( + node->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + library_foreach_node_socket(data, sock); + } + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + library_foreach_node_socket(data, sock); + } + } + + LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { + library_foreach_node_socket(data, sock); + } + LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { + library_foreach_node_socket(data, sock); + } +} + IDTypeInfo IDType_ID_NT = { .id_code = ID_NT, .id_filter = FILTER_ID_NT, @@ -262,6 +329,7 @@ IDTypeInfo IDType_ID_NT = { .copy_data = ntree_copy_data, .free_data = ntree_free_data, .make_local = NULL, + .foreach_id = node_foreach_id, }; static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) @@ -744,6 +812,66 @@ static bNodeSocket *make_socket(bNodeTree *ntree, return sock; } +static void socket_id_user_increment(bNodeSocket *sock) +{ + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + id_us_plus(&default_value->value->id); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + id_us_plus(&default_value->value->id); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + +static void socket_id_user_decrement(bNodeSocket *sock) +{ + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + id_us_min(&default_value->value->id); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + id_us_min(&default_value->value->id); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + void nodeModifySocketType( bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, int type, int subtype) { @@ -755,6 +883,7 @@ void nodeModifySocketType( } if (sock->default_value) { + socket_id_user_decrement(sock); MEM_freeN(sock->default_value); sock->default_value = NULL; } @@ -862,6 +991,18 @@ const char *nodeStaticSocketType(int type, int subtype) return "NodeSocketString"; case SOCK_SHADER: return "NodeSocketShader"; + case SOCK_OBJECT: + return "NodeSocketObject"; + case SOCK_IMAGE: + return "NodeSocketImage"; + case SOCK_EMITTERS: + return "NodeSocketEmitters"; + case SOCK_EVENTS: + return "NodeSocketEvents"; + case SOCK_FORCES: + return "NodeSocketForces"; + case SOCK_CONTROL_FLOW: + return "NodeSocketControlFlow"; } return NULL; } @@ -923,6 +1064,18 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype) return "NodeSocketInterfaceString"; case SOCK_SHADER: return "NodeSocketInterfaceShader"; + case SOCK_OBJECT: + return "NodeSocketInterfaceObject"; + case SOCK_IMAGE: + return "NodeSocketInterfaceImage"; + case SOCK_EMITTERS: + return "NodeSocketInterfaceEmitters"; + case SOCK_EVENTS: + return "NodeSocketInterfaceEvents"; + case SOCK_FORCES: + return "NodeSocketInterfaceForces"; + case SOCK_CONTROL_FLOW: + return "NodeSocketInterfaceControlFlow"; } return NULL; } @@ -981,6 +1134,9 @@ static void node_socket_free(bNodeTree *UNUSED(ntree), } if (sock->default_value) { + if (do_id_user) { + socket_id_user_decrement(sock); + } MEM_freeN(sock->default_value); } } @@ -1267,6 +1423,10 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, if (sock_src->default_value) { sock_dst->default_value = MEM_dupallocN(sock_src->default_value); + + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + socket_id_user_increment(sock_dst); + } } sock_dst->stack_index = 0; @@ -2087,6 +2247,13 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user) if (node->id) { id_us_min(node->id); } + + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + socket_id_user_decrement(sock); + } + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + socket_id_user_decrement(sock); + } } /* Remove animation data. */ @@ -2106,13 +2273,18 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user) node_free_node(ntree, node); } -static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock) +static void node_socket_interface_free(bNodeTree *UNUSED(ntree), + bNodeSocket *sock, + const bool do_id_user) { if (sock->prop) { - IDP_FreeProperty(sock->prop); + IDP_FreeProperty_ex(sock->prop, do_id_user); } if (sock->default_value) { + if (do_id_user) { + socket_id_user_decrement(sock); + } MEM_freeN(sock->default_value); } } @@ -2147,7 +2319,7 @@ void ntreeFreeTree(bNodeTree *ntree) BKE_animdata_free(&ntree->id, false); } -void ntreeFreeNestedTree(bNodeTree *ntree) +void ntreeFreeEmbeddedTree(bNodeTree *ntree) { ntreeFreeTree(ntree); BKE_libblock_free_data(&ntree->id, true); @@ -2270,6 +2442,8 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id) return &((Scene *)id)->nodetree; case ID_LS: return &((FreestyleLineStyle *)id)->nodetree; + case ID_SIM: + return &((Simulation *)id)->nodetree; default: return NULL; } @@ -2533,7 +2707,7 @@ void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock) BLI_remlink(&ntree->inputs, sock); BLI_remlink(&ntree->outputs, sock); - node_socket_interface_free(ntree, sock); + node_socket_interface_free(ntree, sock, true); MEM_freeN(sock); ntree->update |= NTREE_UPDATE_GROUP; @@ -4118,6 +4292,33 @@ static void registerTextureNodes(void) register_node_type_tex_proc_distnoise(); } +static void registerSimulationNodes(void) +{ + register_node_type_sim_group(); + + register_node_type_sim_particle_simulation(); + register_node_type_sim_force(); + register_node_type_sim_set_particle_attribute(); + register_node_type_sim_particle_birth_event(); + register_node_type_sim_particle_time_step_event(); + register_node_type_sim_execute_condition(); + register_node_type_sim_multi_execute(); + register_node_type_sim_particle_mesh_emitter(); + register_node_type_sim_particle_mesh_collision_event(); + register_node_type_sim_emit_particles(); + register_node_type_sim_time(); + register_node_type_sim_particle_attribute(); +} + +static void registerFunctionNodes(void) +{ + register_node_type_fn_boolean_math(); + register_node_type_fn_float_compare(); + register_node_type_fn_switch(); + register_node_type_fn_group_instance_id(); + register_node_type_fn_combine_strings(); +} + void init_nodesystem(void) { nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh"); @@ -4131,6 +4332,7 @@ void init_nodesystem(void) register_node_tree_type_cmp(); register_node_tree_type_sh(); register_node_tree_type_tex(); + register_node_tree_type_sim(); register_node_type_frame(); register_node_type_reroute(); @@ -4140,6 +4342,8 @@ void init_nodesystem(void) registerCompositNodes(); registerShaderNodes(); registerTextureNodes(); + registerSimulationNodes(); + registerFunctionNodes(); } void free_nodesystem(void) @@ -4196,6 +4400,7 @@ void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *b ntreeiter->light = bmain->lights.first; ntreeiter->world = bmain->worlds.first; ntreeiter->linestyle = bmain->linestyles.first; + ntreeiter->simulation = bmain->simulations.first; } bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, @@ -4236,6 +4441,11 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, *r_id = (ID *)ntreeiter->linestyle; ntreeiter->linestyle = ntreeiter->linestyle->id.next; } + else if (ntreeiter->simulation) { + *r_nodetree = ntreeiter->simulation->nodetree; + *r_id = (ID *)ntreeiter->simulation; + ntreeiter->simulation = ntreeiter->simulation->id.next; + } else { return false; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index de34b0cba69..6bd841ca8e5 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -83,6 +83,7 @@ #include "BKE_editmesh.h" #include "BKE_effect.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_font.h" #include "BKE_global.h" #include "BKE_gpencil.h" @@ -205,9 +206,9 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in BLI_listbase_clear(&ob_dst->modifiers); LISTBASE_FOREACH (ModifierData *, md, &ob_src->modifiers) { - ModifierData *nmd = modifier_new(md->type); + ModifierData *nmd = BKE_modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); - modifier_copyData_ex(md, nmd, flag_subdata); + BKE_modifier_copydata_ex(md, nmd, flag_subdata); BLI_addtail(&ob_dst->modifiers, nmd); } @@ -216,7 +217,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in LISTBASE_FOREACH (GpencilModifierData *, gmd, &ob_src->greasepencil_modifiers) { GpencilModifierData *nmd = BKE_gpencil_modifier_new(gmd->type); BLI_strncpy(nmd->name, gmd->name, sizeof(nmd->name)); - BKE_gpencil_modifier_copyData_ex(gmd, nmd, flag_subdata); + BKE_gpencil_modifier_copydata_ex(gmd, nmd, flag_subdata); BLI_addtail(&ob_dst->greasepencil_modifiers, nmd); } @@ -225,7 +226,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in LISTBASE_FOREACH (ShaderFxData *, fx, &ob_src->shader_fx) { ShaderFxData *nfx = BKE_shaderfx_new(fx->type); BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); - BKE_shaderfx_copyData_ex(fx, nfx, flag_subdata); + BKE_shaderfx_copydata_ex(fx, nfx, flag_subdata); BLI_addtail(&ob_dst->shader_fx, nfx); } @@ -433,7 +434,7 @@ void BKE_object_free_modifiers(Object *ob, const int flag) GpencilModifierData *gp_md; while ((md = BLI_pophead(&ob->modifiers))) { - modifier_free_ex(md, flag); + BKE_modifier_free_ex(md, flag); } while ((gp_md = BLI_pophead(&ob->greasepencil_modifiers))) { @@ -509,23 +510,33 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type) { const ModifierTypeInfo *mti; - mti = modifierType_getInfo(modifier_type); + mti = BKE_modifier_get_info(modifier_type); - /* only geometry objects should be able to get modifiers [#25291] */ - if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { - return false; + /* Only geometry objects should be able to get modifiers [#25291] */ + if (ob->type == OB_HAIR) { + return (mti->modifyHair != NULL) || (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly); } - - if (ob->type == OB_LATTICE && (mti->flags & eModifierTypeFlag_AcceptsLattice) == 0) { - return false; + else if (ob->type == OB_POINTCLOUD) { + return (mti->modifyPointCloud != NULL) || + (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly); + } + else if (ob->type == OB_VOLUME) { + return (mti->modifyVolume != NULL); } + else if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (ob->type == OB_LATTICE && (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly) == 0) { + return false; + } - if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) || - (ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh)))) { - return false; + if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) || + (ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh)))) { + return false; + } + + return true; } - return true; + return false; } void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src) @@ -561,7 +572,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr break; } - nmd = modifier_new(md->type); + nmd = BKE_modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); if (md->type == eModifierType_Multires) { @@ -570,9 +581,9 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd); } - modifier_copyData(md, nmd); + BKE_modifier_copydata(md, nmd); BLI_addtail(&ob_dst->modifiers, nmd); - modifier_unique_name(&ob_dst->modifiers, nmd); + BKE_modifier_unique_name(&ob_dst->modifiers, nmd); } } @@ -584,7 +595,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr nmd = BKE_gpencil_modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); mti->copyData(md, nmd); BLI_addtail(&ob_dst->greasepencil_modifiers, nmd); @@ -1297,8 +1308,8 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f psys_copy_particles(psysn, psys); if (psys->clmd) { - psysn->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); - modifier_copyData_ex((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd, flag); + psysn->clmd = (ClothModifierData *)BKE_modifier_new(eModifierType_Cloth); + BKE_modifier_copydata_ex((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd, flag); psys->hair_in_mesh = psys->hair_out_mesh = NULL; } @@ -1451,7 +1462,7 @@ Object *BKE_object_pose_armature_get(Object *ob) return ob; } - ob = modifiers_isDeformedByArmature(ob); + ob = BKE_modifiers_is_deformed_by_armature(ob); /* Only use selected check when non-active. */ if (BKE_object_pose_context_check(ob)) { @@ -2692,7 +2703,7 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o { /* Execute drivers and animation. */ const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL); } @@ -3885,16 +3896,16 @@ int BKE_object_is_modified(Scene *scene, Object *ob) ModifierData *md; VirtualModifierData virtualModifierData; /* cloth */ - for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); md = md->next) { if ((flag & eModifierMode_Render) == 0 && - modifier_isEnabled(scene, md, eModifierMode_Render)) { + BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) { flag |= eModifierMode_Render; } if ((flag & eModifierMode_Realtime) == 0 && - modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { flag |= eModifierMode_Realtime; } } @@ -4023,10 +4034,10 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) } /* cloth */ - for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); bool can_deform = mti->type == eModifierTypeType_OnlyDeform || is_modifier_animated; if (!can_deform) { @@ -4034,12 +4045,13 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) } if (can_deform) { - if (!(flag & eModifierMode_Render) && modifier_isEnabled(scene, md, eModifierMode_Render)) { + if (!(flag & eModifierMode_Render) && + BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) { flag |= eModifierMode_Render; } if (!(flag & eModifierMode_Realtime) && - modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { flag |= eModifierMode_Realtime; } } @@ -4374,7 +4386,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) bool BKE_object_modifier_use_time(Object *ob, ModifierData *md) { - if (modifier_dependsOnTime(md)) { + if (BKE_modifier_depends_ontime(md)) { return true; } @@ -4417,7 +4429,7 @@ bool BKE_object_modifier_use_time(Object *ob, ModifierData *md) bool BKE_object_modifier_gpencil_use_time(Object *ob, GpencilModifierData *md) { - if (BKE_gpencil_modifier_dependsOnTime(md)) { + if (BKE_gpencil_modifier_depends_ontime(md)) { return true; } @@ -4452,7 +4464,7 @@ bool BKE_object_modifier_gpencil_use_time(Object *ob, GpencilModifierData *md) bool BKE_object_shaderfx_use_time(Object *ob, ShaderFxData *fx) { - if (BKE_shaderfx_dependsOnTime(fx)) { + if (BKE_shaderfx_depends_ontime(fx)) { return true; } @@ -4518,7 +4530,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, int type) { const bool flush_to_original = DEG_is_active(depsgraph); - ModifierData *md = modifiers_findByType(ob, (ModifierType)type); + ModifierData *md = BKE_modifiers_findby_type(ob, (ModifierType)type); bConstraint *con; if (type == eModifierType_DynamicPaint) { @@ -4582,8 +4594,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* TODO(sergey): What about animation? */ ob->id.recalc |= ID_RECALC_ALL; if (update_mesh) { - BKE_animsys_evaluate_animdata( - scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); /* ignore cache clear during subframe updates * to not mess up cache validity */ object_cacheIgnoreClear(ob, 1); @@ -4597,14 +4608,12 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* for curve following objects, parented curve has to be updated too */ if (ob->type == OB_CURVE) { Curve *cu = ob->data; - BKE_animsys_evaluate_animdata( - scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); } /* and armatures... */ if (ob->type == OB_ARMATURE) { bArmature *arm = ob->data; - BKE_animsys_evaluate_animdata( - scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); BKE_pose_where_is(depsgraph, scene, ob); } diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index a75180867cb..6ca1442497a 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -620,7 +620,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot) /* now loop through the armature modifiers and identify deform bones */ for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), - modifiers_getVirtualModifierList(ob, &virtualModifierData) : + BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData) : md->next) { if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) { continue; diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 2683d384bc7..8957628c76a 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -453,21 +453,17 @@ static void ocean_compute_htilda(void *__restrict userdata, } } -static void ocean_compute_displacement_y(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_displacement_y(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; fftw_execute(o->_disp_y_plan); } -static void ocean_compute_displacement_x(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_displacement_x(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float scale = osd->scale; const float chop_amount = osd->chop_amount; @@ -494,11 +490,9 @@ static void ocean_compute_displacement_x(TaskPool *__restrict pool, fftw_execute(o->_disp_x_plan); } -static void ocean_compute_displacement_z(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_displacement_z(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float scale = osd->scale; const float chop_amount = osd->chop_amount; @@ -525,11 +519,9 @@ static void ocean_compute_displacement_z(TaskPool *__restrict pool, fftw_execute(o->_disp_z_plan); } -static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float chop_amount = osd->chop_amount; int i, j; @@ -560,11 +552,9 @@ static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, } } -static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float chop_amount = osd->chop_amount; int i, j; @@ -595,11 +585,9 @@ static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, } } -static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float chop_amount = osd->chop_amount; int i, j; @@ -624,11 +612,9 @@ static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, fftw_execute(o->_Jxz_plan); } -static void ocean_compute_normal_x(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_normal_x(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; int i, j; @@ -645,11 +631,9 @@ static void ocean_compute_normal_x(TaskPool *__restrict pool, fftw_execute(o->_N_x_plan); } -static void ocean_compute_normal_z(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; int i, j; @@ -668,7 +652,6 @@ static void ocean_compute_normal_z(TaskPool *__restrict pool, void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); TaskPool *pool; OceanSimulateData osd; @@ -680,7 +663,7 @@ void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount osd.scale = scale; osd.chop_amount = chop_amount; - pool = BLI_task_pool_create(scheduler, &osd, TASK_PRIORITY_HIGH); + pool = BLI_task_pool_create(&osd, TASK_PRIORITY_HIGH); BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 4bbbae7081d..5b608d579e8 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -10,7 +10,7 @@ * 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, + * 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 by Nicholas Bishop @@ -1406,15 +1406,15 @@ MultiresModifierData *BKE_sculpt_multires_active(Scene *scene, Object *ob) return NULL; } - for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) { + for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); md; md = md->next) { if (md->type == eModifierType_Multires) { MultiresModifierData *mmd = (MultiresModifierData *)md; - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } - if (BKE_multires_sculpt_level_get(mmd) > 0) { + if (mmd->sculptlvl > 0) { return mmd; } else { @@ -1443,12 +1443,12 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) return true; } - md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* exception for shape keys because we can edit those */ for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } if (md->type == eModifierType_Multires && (ob->mode & OB_MODE_SCULPT)) { @@ -1686,7 +1686,7 @@ int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) * isn't one already */ if (mmd && !CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) { GridPaintMask *gmask; - int level = max_ii(1, BKE_multires_sculpt_level_get(mmd)); + int level = max_ii(1, mmd->sculptlvl); int gridsize = BKE_ccg_gridsize(level); int gridarea = gridsize * gridsize; int i, j; diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c index ea5cb168b12..df7feed3a53 100644 --- a/source/blender/blenkernel/intern/paint_toolslots.c +++ b/source/blender/blenkernel/intern/paint_toolslots.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 0e35fa5d19f..19342090eb7 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -583,7 +583,7 @@ void free_hair(Object *object, ParticleSystem *psys, int dynamics) if (psys->clmd) { if (dynamics) { - modifier_free((ModifierData *)psys->clmd); + BKE_modifier_free((ModifierData *)psys->clmd); psys->clmd = NULL; PTCacheID pid; BKE_ptcache_id_from_particles(&pid, object, psys); @@ -735,7 +735,7 @@ void psys_free(Object *ob, ParticleSystem *psys) */ free_hair(ob, psys, 0); if (psys->clmd != NULL) { - modifier_free((ModifierData *)psys->clmd); + BKE_modifier_free((ModifierData *)psys->clmd); } psys_free_particles(psys); @@ -2787,9 +2787,7 @@ static void psys_thread_create_path(ParticleTask *task, } } -static void exec_child_path_cache(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void exec_child_path_cache(TaskPool *__restrict UNUSED(pool), void *taskdata) { ParticleTask *task = taskdata; ParticleThreadContext *ctx = task->ctx; @@ -2810,7 +2808,6 @@ void psys_cache_child_paths(ParticleSimulationData *sim, const bool editupdate, const bool use_render_params) { - TaskScheduler *task_scheduler; TaskPool *task_pool; ParticleThreadContext ctx; ParticleTask *tasks_parent, *tasks_child; @@ -2826,8 +2823,7 @@ void psys_cache_child_paths(ParticleSimulationData *sim, return; } - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, &ctx, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&ctx, TASK_PRIORITY_LOW); totchild = ctx.totchild; totparent = ctx.totparent; @@ -3377,7 +3373,6 @@ void psys_cache_edit_paths(Depsgraph *depsgraph, TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, psys_cache_edit_paths_iter, &settings); edit->totcached = totpart; @@ -3590,9 +3585,9 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, psys->part = BKE_particlesettings_add(bmain, psys->name); - md = modifier_new(eModifierType_ParticleSystem); + md = BKE_modifier_new(eModifierType_ParticleSystem); BLI_strncpy(md->name, psys->name, sizeof(md->name)); - modifier_unique_name(&ob->modifiers, md); + BKE_modifier_unique_name(&ob->modifiers, md); psmd = (ParticleSystemModifierData *)md; psmd->psys = psys; @@ -3620,7 +3615,7 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } /* Clear particle system in fluid modifier. */ - if ((md = modifiers_findByType(ob, eModifierType_Fluid))) { + if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid))) { FluidModifierData *mmd = (FluidModifierData *)md; /* Clear particle system pointer in flow settings. */ @@ -3662,7 +3657,7 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } } - if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint))) { + if ((md = BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint))) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; if (pmd->brush && pmd->brush->psys) { if (pmd->brush->psys == psys) { @@ -3675,7 +3670,7 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob psmd = psys_get_modifier(ob, psys); if (psmd) { BLI_remlink(&ob->modifiers, psmd); - modifier_free((ModifierData *)psmd); + BKE_modifier_free((ModifierData *)psmd); } /* Clear particle system. */ @@ -4009,7 +4004,7 @@ static void get_cpa_texture(Mesh *mesh, break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false); + RE_texture_evaluate(mtex, texvec, 0, NULL, false, false, &value, rgba); if ((event & mtex->mapto) & PAMAP_ROUGH) { ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend( @@ -4124,7 +4119,7 @@ void psys_get_texture( break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false); + RE_texture_evaluate(mtex, texvec, 0, NULL, false, false, &value, rgba); if ((event & mtex->mapto) & PAMAP_TIME) { /* the first time has to set the base value for time regardless of blend mode */ diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index d91e27a92d8..7b9b2484dbe 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -773,9 +773,7 @@ static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, i } } -static void exec_distribute_parent(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void exec_distribute_parent(TaskPool *__restrict UNUSED(pool), void *taskdata) { ParticleTask *task = taskdata; ParticleSystem *psys = task->ctx->sim.psys; @@ -804,9 +802,7 @@ static void exec_distribute_parent(TaskPool *__restrict UNUSED(pool), } } -static void exec_distribute_child(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void exec_distribute_child(TaskPool *__restrict UNUSED(pool), void *taskdata) { ParticleTask *task = taskdata; ParticleSystem *psys = task->ctx->sim.psys; @@ -1324,7 +1320,6 @@ static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) { - TaskScheduler *task_scheduler; TaskPool *task_pool; ParticleThreadContext ctx; ParticleTask *tasks; @@ -1336,8 +1331,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) return; } - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, &ctx, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&ctx, TASK_PRIORITY_LOW); totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart); psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f7400264131..df74b7a75da 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3450,7 +3450,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) bool realloc_roots; if (!psys->clmd) { - psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); + psys->clmd = (ClothModifierData *)BKE_modifier_new(eModifierType_Cloth); psys->clmd->sim_parms->goalspring = 0.0f; psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS; psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; @@ -3693,10 +3693,11 @@ typedef struct DynamicStepSolverTaskData { SpinLock spin; } DynamicStepSolverTaskData; -static void dynamics_step_finalize_sphdata(void *__restrict UNUSED(userdata), - void *__restrict tls_userdata_chunk) +static void dynamics_step_sphdata_reduce(const void *__restrict UNUSED(userdata), + void *__restrict UNUSED(join_v), + void *__restrict chunk_v) { - SPHData *sphdata = tls_userdata_chunk; + SPHData *sphdata = chunk_v; psys_sph_flush_springs(sphdata); } @@ -3987,7 +3988,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range( 0, psys->totpart, &task_data, dynamics_step_sph_ddr_task_cb_ex, &settings); @@ -4019,7 +4020,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range(0, psys->totpart, &task_data, @@ -4034,7 +4035,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range(0, psys->totpart, &task_data, @@ -4182,7 +4183,8 @@ static void particles_fluid_step(ParticleSimulationData *sim, #else { Object *ob = sim->ob; - FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + FluidModifierData *mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, + eModifierType_Fluid); if (mmd && mmd->domain && mmd->domain->fluid) { FluidDomainSettings *mds = mmd->domain; @@ -4190,7 +4192,7 @@ static void particles_fluid_step(ParticleSimulationData *sim, ParticleSettings *part = psys->part; ParticleData *pa = NULL; - int p, totpart, tottypepart = 0; + int p, totpart = 0, tottypepart = 0; int flagActivePart, activeParts = 0; float posX, posY, posZ, velX, velY, velZ; float resX, resY, resZ; @@ -4848,7 +4850,7 @@ void particle_system_update(struct Depsgraph *depsgraph, hcfra = 100.0f * (float)i / (float)psys->part->hair_step; if ((part->flag & PART_HAIR_REGROW) == 0) { BKE_animsys_evaluate_animdata( - scene, &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); + &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); } system_step(&sim, hcfra, use_render_params); psys->cfra = hcfra; diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index e6d672ad9d9..f72ecd568e2 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1115,11 +1115,11 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode) .vnors = vnors, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings); MEM_freeN(vnors); } @@ -1169,9 +1169,9 @@ static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, in .flag = flag, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings); } static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata, @@ -1207,9 +1207,9 @@ static void pbvh_update_visibility_redraw(PBVH *bvh, PBVHNode **nodes, int totno .flag = flag, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_visibility_redraw_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_redraw_task_cb, &settings); } static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata, @@ -1245,9 +1245,9 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) .flag = flag, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings); } static int pbvh_get_buffers_update_flags(PBVH *bvh, bool show_vcol) @@ -1365,9 +1365,9 @@ static void pbvh_update_draw_buffers( .show_vcol = show_vcol, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings); } static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) @@ -1558,9 +1558,9 @@ static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode) .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings); } void BKE_pbvh_update_visibility(PBVH *bvh) @@ -1927,7 +1927,7 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node, /** * \note doing a full search on all vertices here seems expensive, - * however this is important to avoid having to recalculate boundbox & sync the buffers to the + * however this is important to avoid having to recalculate bound-box & sync the buffers to the * GPU (which is far more expensive!) See: T47232. */ bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node) @@ -2994,7 +2994,7 @@ void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes) } } -void BKE_pbvh_parallel_range_settings(PBVHParallelSettings *settings, +void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings, bool use_threading, int totnode) { diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 77b3f1580ac..5ee61667eca 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -583,7 +583,7 @@ static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) static void ptcache_cloth_error(void *cloth_v, const char *message) { ClothModifierData *clmd = cloth_v; - modifier_setError(&clmd->modifier, "%s", message); + BKE_modifier_set_error(&clmd->modifier, "%s", message); } #ifdef WITH_SMOKE @@ -604,7 +604,7 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) static void ptcache_smoke_error(void *smoke_v, const char *message) { FluidModifierData *mmd = (FluidModifierData *)smoke_v; - modifier_setError(&mmd->modifier, "%s", message); + BKE_modifier_set_error(&mmd->modifier, "%s", message); } # define SMOKE_CACHE_VERSION "1.04" diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index 31b8de53291..79b16443122 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -184,7 +184,7 @@ void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud) PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int totpoint) { - PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_HA, NULL); + PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_PT, NULL); STRNCPY(pointcloud_dst->id.name, pointcloud_src->id.name); pointcloud_dst->mat = MEM_dupallocN(pointcloud_src->mat); @@ -211,12 +211,65 @@ PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src, bool return result; } -static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph), - struct Scene *UNUSED(scene), - Object *UNUSED(object), +static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, + struct Scene *scene, + Object *object, PointCloud *pointcloud_input) { - return pointcloud_input; + PointCloud *pointcloud = pointcloud_input; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; + const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); + + /* Evaluate modifiers. */ + for (; md; md = md->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if ((mti->type == eModifierTypeType_OnlyDeform) && + (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { + /* Ensure we are not modifying the input. */ + if (pointcloud == pointcloud_input) { + pointcloud = BKE_pointcloud_copy_for_eval(pointcloud, true); + } + + /* Ensure we are not overwriting referenced data. */ + CustomData_duplicate_referenced_layer(&pointcloud->pdata, CD_LOCATION, pointcloud->totpoint); + BKE_pointcloud_update_customdata_pointers(pointcloud); + + /* Created deformed coordinates array on demand. */ + mti->deformVerts(md, &mectx, NULL, pointcloud->co, pointcloud->totpoint); + } + else if (mti->modifyPointCloud) { + /* Ensure we are not modifying the input. */ + if (pointcloud == pointcloud_input) { + pointcloud = BKE_pointcloud_copy_for_eval(pointcloud, true); + } + + PointCloud *pointcloud_next = mti->modifyPointCloud(md, &mectx, pointcloud); + + if (pointcloud_next && pointcloud_next != pointcloud) { + /* If the modifier returned a new pointcloud, release the old one. */ + if (pointcloud != pointcloud_input) { + BKE_id_free(NULL, pointcloud); + } + pointcloud = pointcloud_next; + } + } + } + + return pointcloud; } void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 410d5b41057..be6a4e4022b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -343,7 +343,7 @@ static void scene_free_data(ID *id) /* is no lib link block, but scene extension */ if (scene->nodetree) { - ntreeFreeNestedTree(scene->nodetree); + ntreeFreeEmbeddedTree(scene->nodetree); MEM_freeN(scene->nodetree); scene->nodetree = NULL; } @@ -2110,7 +2110,7 @@ static Depsgraph **scene_get_depsgraph_p(Main *bmain, if (allocate_depsgraph) { *depsgraph_ptr = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_VIEWPORT); /* TODO(sergey): Would be cool to avoid string format print, - * but is a bit tricky because we can't know in advance whether + * but is a bit tricky because we can't know in advance whether * we will ever enable debug messages for this depsgraph. */ char name[1024]; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index c1644e39afa..9fa43ed0a5f 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -61,6 +61,8 @@ #include "BLF_api.h" +static struct SeqEffectHandle get_sequence_effect_impl(int seq_type); + static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, @@ -3118,7 +3120,7 @@ static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(fla static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1)) { - return EARLY_USE_INPUT_1; + return EARLY_DO_EFFECT; } static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float *ymin, float *ymax) @@ -3248,36 +3250,60 @@ void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool for } } +/* Override cfra when rendering speed effect input. */ +float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context, + Sequence *seq, + float cfra, + int input) +{ + int nr = BKE_sequencer_give_stripelem_index(seq, cfra); + SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; + BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false); + + /* No interpolation. */ + if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) { + return seq->start + s->frameMap[nr]; + } + + /* We need to provide current and next image for interpolation. */ + if (input == 0) { /* Current frame. */ + return floor(seq->start + s->frameMap[nr]); + } + else { /* Next frame. */ + return ceil(seq->start + s->frameMap[nr]); + } +} + +static float speed_effect_interpolation_ratio_get(SpeedControlVars *s, Sequence *seq, float cfra) +{ + int nr = BKE_sequencer_give_stripelem_index(seq, cfra); + return s->frameMap[nr] - floor(s->frameMap[nr]); +} + static ImBuf *do_speed_effect(const SeqRenderData *context, - Sequence *UNUSED(seq), - float UNUSED(cfra), + Sequence *seq, + float cfra, float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3) { - ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3); + SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; + struct SeqEffectHandle cross_effect = get_sequence_effect_impl(SEQ_TYPE_CROSS); + ImBuf *out; - if (out->rect_float) { - do_cross_effect_float(facf0, - facf1, - context->rectx, - context->recty, - ibuf1->rect_float, - ibuf2->rect_float, - out->rect_float); + if (s->flags & SEQ_SPEED_USE_INTERPOLATION) { + out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3); + facf0 = facf1 = speed_effect_interpolation_ratio_get(s, seq, cfra); + /* Current frame is ibuf1, next frame is ibuf2. */ + out = BKE_sequencer_effect_execute_threaded( + &cross_effect, context, NULL, cfra, facf0, facf1, ibuf1, ibuf2, ibuf3); + return out; } - else { - do_cross_effect_byte(facf0, - facf1, - context->rectx, - context->recty, - (unsigned char *)ibuf1->rect, - (unsigned char *)ibuf2->rect, - (unsigned char *)out->rect); - } - return out; + + /* No interpolation. */ + return IMB_dupImBuf(ibuf1); } /*********************** overdrop *************************/ diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c index dabfd26f5b0..1425bff48a8 100644 --- a/source/blender/blenkernel/intern/seqprefetch.c +++ b/source/blender/blenkernel/intern/seqprefetch.c @@ -343,8 +343,7 @@ static void *seq_prefetch_frames(void *job) seq_prefetch_update_depsgraph(pfjob); AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id); - BKE_animsys_evaluate_animdata(pfjob->context_cpy.scene, - &pfjob->context_cpy.scene->id, + BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id, adt, pfjob->cfra + pfjob->num_frames_prefetched, ADT_RECALC_ALL, diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 6791424694a..16a86fedc51 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1397,7 +1397,7 @@ static void multibuf(ImBuf *ibuf, const float fmul) } } -static float give_stripelem_index(Sequence *seq, float cfra) +float BKE_sequencer_give_stripelem_index(Sequence *seq, float cfra) { float nr; int sta = seq->start; @@ -1455,7 +1455,7 @@ StripElem *BKE_sequencer_give_stripelem(Sequence *seq, int cfra) * all other strips don't use this... */ - int nr = (int)give_stripelem_index(seq, cfra); + int nr = (int)BKE_sequencer_give_stripelem_index(seq, cfra); if (nr == -1 || se == NULL) { return NULL; @@ -1892,7 +1892,7 @@ static bool seq_proxy_get_fname(Editing *ed, frameno = 1; } else { - frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; + frameno = (int)BKE_sequencer_give_stripelem_index(seq, cfra) + seq->anim_startofs; BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, proxy_size_number, suffix); } @@ -1925,7 +1925,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c } if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { - int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; + int frameno = (int)BKE_sequencer_give_stripelem_index(seq, cfra) + seq->anim_startofs; if (proxy->anim == NULL) { if (seq_proxy_get_fname(ed, seq, cfra, psize, name, context->view_id) == 0) { return NULL; @@ -2890,15 +2890,15 @@ static void *render_effect_execute_do_thread(void *thread_data_v) return NULL; } -static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, - const SeqRenderData *context, - Sequence *seq, - float cfra, - float facf0, - float facf1, - ImBuf *ibuf1, - ImBuf *ibuf2, - ImBuf *ibuf3) +ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh, + const SeqRenderData *context, + Sequence *seq, + float cfra, + float facf0, + float facf1, + ImBuf *ibuf1, + ImBuf *ibuf2, + ImBuf *ibuf3) { RenderEffectInitData init_data; ImBuf *out = sh->init_execution(context, ibuf1, ibuf2, ibuf3); @@ -2972,14 +2972,21 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, break; case EARLY_DO_EFFECT: for (i = 0; i < 3; i++) { - if (input[i]) { - ibuf[i] = seq_render_strip(context, state, input[i], cfra); + /* Speed effect requires time remapping of cfra for input(s). */ + if (input[1] && seq->type == SEQ_TYPE_SPEED) { + float target_frame = BKE_sequencer_speed_effect_target_frame_get(context, seq, cfra, i); + ibuf[i] = seq_render_strip(context, state, input[i], target_frame); + } + else { /* Other effects. */ + if (input[i]) { + ibuf[i] = seq_render_strip(context, state, input[i], cfra); + } } } if (ibuf[0] && ibuf[1]) { if (sh.multithreaded) { - out = seq_render_effect_execute_threaded( + out = BKE_sequencer_effect_execute_threaded( &sh, context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]); } else { @@ -3333,8 +3340,7 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr /* anim-data */ adt = BKE_animdata_from_id(&mask->id); - BKE_animsys_evaluate_animdata( - context->scene, &mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__); @@ -3668,8 +3674,7 @@ static ImBuf *do_render_strip_seqbase(const SeqRenderData *context, if (seqbase && !BLI_listbase_is_empty(seqbase)) { if (seq->flag & SEQ_SCENE_STRIPS && seq->scene) { - BKE_animsys_evaluate_all_animation( - context->bmain, context->depsgraph, seq->scene, nr + offset); + BKE_animsys_evaluate_all_animation(context->bmain, context->depsgraph, nr + offset); } ibuf = seq_render_strip_stack(context, @@ -3689,9 +3694,8 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, float cfra) { ImBuf *ibuf = NULL; - float nr = give_stripelem_index(seq, cfra); - int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : - seq->type; + float nr = BKE_sequencer_give_stripelem_index(seq, cfra); + int type = (seq->type & SEQ_TYPE_EFFECT) ? SEQ_TYPE_EFFECT : seq->type; switch (type) { case SEQ_TYPE_META: { ibuf = do_render_strip_seqbase(context, state, seq, nr); @@ -3733,21 +3737,8 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, break; } - case SEQ_TYPE_SPEED: { - float f_cfra; - SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; - - BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false); - - /* weeek! */ - f_cfra = seq->start + s->frameMap[(int)nr]; - ibuf = seq_render_strip(context, state, seq->seq1, f_cfra); - - break; - } - case SEQ_TYPE_EFFECT: { - ibuf = seq_render_effect_strip_impl(context, state, seq, seq->start + nr); + ibuf = seq_render_effect_strip_impl(context, state, seq, cfra); break; } @@ -3941,7 +3932,7 @@ static ImBuf *seq_render_strip_stack_apply_effect( if (swap_input) { if (sh.multithreaded) { - out = seq_render_effect_execute_threaded( + out = BKE_sequencer_effect_execute_threaded( &sh, context, seq, cfra, facf, facf, ibuf2, ibuf1, NULL); } else { @@ -3950,7 +3941,7 @@ static ImBuf *seq_render_strip_stack_apply_effect( } else { if (sh.multithreaded) { - out = seq_render_effect_execute_threaded( + out = BKE_sequencer_effect_execute_threaded( &sh, context, seq, cfra, facf, facf, ibuf1, ibuf2, NULL); } else { diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c index 8d692782413..0ad61de1ff2 100644 --- a/source/blender/blenkernel/intern/shader_fx.c +++ b/source/blender/blenkernel/intern/shader_fx.c @@ -59,7 +59,7 @@ bool BKE_shaderfx_has_gpencil(Object *ob) { ShaderFxData *fx; for (fx = ob->shader_fx.first; fx; fx = fx->next) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if (fxi->type == eShaderFxType_GpencilType) { return true; } @@ -75,7 +75,7 @@ void BKE_shaderfx_init(void) ShaderFxData *BKE_shaderfx_new(int type) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(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 */ @@ -109,7 +109,7 @@ static void shaderfx_free_data_id_us_cb(void *UNUSED(userData), void BKE_shaderfx_free_ex(ShaderFxData *fx, const int flag) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { if (fxi->foreachIDLink) { @@ -139,21 +139,21 @@ void BKE_shaderfx_free(ShaderFxData *fx) bool BKE_shaderfx_unique_name(ListBase *shaders, ShaderFxData *fx) { if (shaders && fx) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); return BLI_uniquename( shaders, fx, DATA_(fxi->name), '.', offsetof(ShaderFxData, name), sizeof(fx->name)); } return false; } -bool BKE_shaderfx_dependsOnTime(ShaderFxData *fx) +bool BKE_shaderfx_depends_ontime(ShaderFxData *fx) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); return fxi->dependsOnTime && fxi->dependsOnTime(fx); } -const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type) +const ShaderFxTypeInfo *BKE_shaderfx_get_info(ShaderFxType type) { /* type unsigned, no need to check < 0 */ if (type < NUM_SHADER_FX_TYPES && shader_fx_types[type]->name[0] != '\0') { @@ -164,9 +164,9 @@ const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type) } } -void BKE_shaderfx_copyData_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst) +void BKE_shaderfx_copydata_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx_src->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx_src->type); /* fx_dst may have already be fully initialized with some extra allocated data, * we need to free it now to avoid memleak. */ @@ -192,9 +192,9 @@ static void shaderfx_copy_data_id_us_cb(void *UNUSED(userData), } } -void BKE_shaderfx_copyData_ex(ShaderFxData *fx, ShaderFxData *target, const int flag) +void BKE_shaderfx_copydata_ex(ShaderFxData *fx, ShaderFxData *target, const int flag) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); target->mode = fx->mode; target->flag = fx->flag; @@ -214,12 +214,12 @@ void BKE_shaderfx_copyData_ex(ShaderFxData *fx, ShaderFxData *target, const int } } -void BKE_shaderfx_copyData(ShaderFxData *fx, ShaderFxData *target) +void BKE_shaderfx_copydata(ShaderFxData *fx, ShaderFxData *target) { - BKE_shaderfx_copyData_ex(fx, target, 0); + BKE_shaderfx_copydata_ex(fx, target, 0); } -ShaderFxData *BKE_shaderfx_findByType(Object *ob, ShaderFxType type) +ShaderFxData *BKE_shaderfx_findby_type(Object *ob, ShaderFxType type) { ShaderFxData *fx = ob->shader_fx.first; @@ -232,12 +232,12 @@ ShaderFxData *BKE_shaderfx_findByType(Object *ob, ShaderFxType type) return fx; } -void BKE_shaderfx_foreachIDLink(Object *ob, ShaderFxIDWalkFunc walk, void *userData) +void BKE_shaderfx_foreach_ID_link(Object *ob, ShaderFxIDWalkFunc walk, void *userData) { ShaderFxData *fx = ob->shader_fx.first; for (; fx; fx = fx->next) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if (fxi->foreachIDLink) { fxi->foreachIDLink(fx, ob, walk, userData); @@ -250,7 +250,7 @@ void BKE_shaderfx_foreachIDLink(Object *ob, ShaderFxIDWalkFunc walk, void *userD } } -ShaderFxData *BKE_shaderfx_findByName(Object *ob, const char *name) +ShaderFxData *BKE_shaderfx_findby_name(Object *ob, const char *name) { return BLI_findstring(&(ob->shader_fx), name, offsetof(ShaderFxData, name)); } diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 06086cdf56a..c59042bc045 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -443,7 +443,7 @@ bool BKE_shrinkwrap_project_normal(char options, BVHTreeRayHit *hit) { /* don't use this because this dist value could be incompatible - * this value used by the callback for comparing prev/new dist values. + * this value used by the callback for comparing previous/new dist values. * also, at the moment there is no need to have a corrected 'dist' value */ // #define USE_DIST_CORRECT diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc new file mode 100644 index 00000000000..ace91424764 --- /dev/null +++ b/source/blender/blenkernel/intern/simulation.cc @@ -0,0 +1,110 @@ +/* + * 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 bke + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_defaults.h" +#include "DNA_simulation_types.h" + +#include "BLI_compiler_compat.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BKE_anim_data.h" +#include "BKE_animsys.h" +#include "BKE_idtype.h" +#include "BKE_lib_id.h" +#include "BKE_lib_query.h" +#include "BKE_lib_remap.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_simulation.h" + +#include "NOD_simulation.h" + +#include "BLT_translation.h" + +static void simulation_init_data(ID *id) +{ + Simulation *simulation = (Simulation *)id; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(simulation, id)); + + MEMCPY_STRUCT_AFTER(simulation, DNA_struct_default_get(Simulation), id); + + bNodeTree *ntree = ntreeAddTree(nullptr, "Simulation Nodetree", ntreeType_Simulation->idname); + simulation->nodetree = ntree; +} + +static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) +{ + Simulation *simulation_dst = (Simulation *)id_dst; + Simulation *simulation_src = (Simulation *)id_src; + + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE; + + if (simulation_src->nodetree) { + BKE_id_copy_ex(bmain, + (ID *)simulation_src->nodetree, + (ID **)&simulation_dst->nodetree, + flag_private_id_data); + } +} + +static void simulation_free_data(ID *id) +{ + Simulation *simulation = (Simulation *)id; + + BKE_animdata_free(&simulation->id, false); + + if (simulation->nodetree) { + ntreeFreeEmbeddedTree(simulation->nodetree); + MEM_freeN(simulation->nodetree); + simulation->nodetree = nullptr; + } +} + +void *BKE_simulation_add(Main *bmain, const char *name) +{ + Simulation *simulation = (Simulation *)BKE_libblock_alloc(bmain, ID_SIM, name, 0); + + simulation_init_data(&simulation->id); + + return simulation; +} + +IDTypeInfo IDType_ID_SIM = { + /* id_code */ ID_SIM, + /* id_filter */ FILTER_ID_SIM, + /* main_listbase_index */ INDEX_ID_SIM, + /* struct_size */ sizeof(Simulation), + /* name */ "Simulation", + /* name_plural */ "simulations", + /* translation_context */ BLT_I18NCONTEXT_ID_SIMULATION, + /* flags */ 0, + + /* init_data */ simulation_init_data, + /* copy_data */ simulation_copy_data, + /* free_data */ simulation_free_data, + /* make_local */ nullptr, +}; diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index c358dde449f..68d0822a223 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -285,7 +285,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob) float hull; int i; - cmd = (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision); + cmd = (CollisionModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Collision); /* first some paranoia checks */ if (!cmd) { @@ -371,7 +371,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M) float hull; int i; - cmd = (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision); + cmd = (CollisionModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Collision); /* first some paranoia checks */ if (!cmd) { @@ -3010,7 +3010,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob) * (C2= continuous in second derivate -> no jump in bending ) condition. * * Not too hard to do, but needs some more code to care for; - * some one may want look at it JOW 2010/06/12. */ + * some one may want look at it (JOW 2010/06/12). */ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++, bp += 3, curindex += 3) { if (setgoal) { bp->goal *= bezt->weight; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 64fe396d6a3..5500918428f 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -751,12 +751,12 @@ static void sound_start_play_scene(Scene *scene) } } -static float get_cur_time(Scene *scene) +static double get_cur_time(Scene *scene) { /* We divide by the current framelen to take into account time remapping. * Otherwise we will get the wrong starting time which will break A/V sync. * See T74111 for further details. */ - return FRA2TIME((CFRA + SUBFRA) / scene->r.framelen); + return FRA2TIME((CFRA + SUBFRA) / (double)scene->r.framelen); } void BKE_sound_play_scene(Scene *scene) @@ -764,7 +764,7 @@ void BKE_sound_play_scene(Scene *scene) sound_verify_evaluated_id(&scene->id); AUD_Status status; - const float cur_time = get_cur_time(scene); + const double cur_time = get_cur_time(scene); AUD_Device_lock(sound_device); @@ -811,8 +811,8 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) bScreen *screen; int animation_playing; - const float one_frame = (float)(1.0 / FPS); - const float cur_time = FRA2TIME(CFRA); + const double one_frame = 1.0 / FPS; + const double cur_time = FRA2TIME(CFRA); AUD_Device_lock(sound_device); @@ -869,7 +869,7 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) AUD_Device_unlock(sound_device); } -float BKE_sound_sync_scene(Scene *scene) +double BKE_sound_sync_scene(Scene *scene) { sound_verify_evaluated_id(&scene->id); @@ -1230,7 +1230,7 @@ void BKE_sound_stop_scene(Scene *UNUSED(scene)) void BKE_sound_seek_scene(Main *UNUSED(bmain), Scene *UNUSED(scene)) { } -float BKE_sound_sync_scene(Scene *UNUSED(scene)) +double BKE_sound_sync_scene(Scene *UNUSED(scene)) { return NAN_FLT; } @@ -1341,7 +1341,7 @@ void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback) #endif } -void BKE_sound_jack_scene_update(Scene *scene, int mode, float time) +void BKE_sound_jack_scene_update(Scene *scene, int mode, double time) { sound_verify_evaluated_id(&scene->id); diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index 0ae32701cd5..d5d5530c1ce 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -40,9 +40,9 @@ #include "opensubdiv_topology_refiner_capi.h" -/* ============================================================================= - * Various forward declarations. - */ +/* -------------------------------------------------------------------- */ +/** \name Various forward declarations + * \{ */ static void subdiv_ccg_average_all_boundaries_and_corners(SubdivCCG *subdiv_ccg, CCGKey *key); @@ -50,9 +50,11 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg, CCGKey *key, SubdivCCGFace *face); -/* ============================================================================= - * Generally useful internal helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generally useful internal helpers + * \{ */ /* Number of floats in per-vertex elements. */ static int num_element_float_get(const SubdivCCG *subdiv_ccg) @@ -74,9 +76,11 @@ static int element_size_bytes_get(const SubdivCCG *subdiv_ccg) return sizeof(float) * num_element_float_get(subdiv_ccg); } -/* ============================================================================= - * Internal helpers for CCG creation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal helpers for CCG creation + * \{ */ static void subdiv_ccg_init_layers(SubdivCCG *subdiv_ccg, const SubdivToCCGSettings *settings) { @@ -158,9 +162,11 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv) } } -/* ============================================================================= - * Grids evaluation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Grids evaluation + * \{ */ typedef struct CCGEvalGridsData { SubdivCCG *subdiv_ccg; @@ -556,9 +562,11 @@ static void subdiv_ccg_init_faces_neighborhood(SubdivCCG *subdiv_ccg) subdiv_ccg_init_faces_vertex_neighborhood(subdiv_ccg); } -/* ============================================================================= - * Creation / evaluation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Creation / evaluation + * \{ */ SubdivCCG *BKE_subdiv_to_ccg(Subdiv *subdiv, const SubdivToCCGSettings *settings, @@ -670,9 +678,11 @@ void BKE_subdiv_ccg_key_top_level(CCGKey *key, const SubdivCCG *subdiv_ccg) BKE_subdiv_ccg_key(key, subdiv_ccg, subdiv_ccg->level); } -/* ============================================================================= - * Normals. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Normals + * \{ */ typedef struct RecalcInnerNormalsData { SubdivCCG *subdiv_ccg; @@ -770,8 +780,8 @@ static void subdiv_ccg_recalc_inner_normal_task(void *__restrict userdata_v, subdiv_ccg_average_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index); } -static void subdiv_ccg_recalc_inner_normal_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_recalc_inner_normal_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { RecalcInnerNormalsTLSData *tls = tls_v; MEM_SAFE_FREE(tls->face_normals); @@ -791,7 +801,7 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG *subdiv_ccg) BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_recalc_inner_normal_finalize; + parallel_range_settings.func_free = subdiv_ccg_recalc_inner_normal_free; BLI_task_parallel_range(0, subdiv_ccg->num_grids, &data, @@ -834,8 +844,8 @@ static void subdiv_ccg_recalc_modified_inner_normal_task(void *__restrict userda subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face); } -static void subdiv_ccg_recalc_modified_inner_normal_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_recalc_modified_inner_normal_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { RecalcInnerNormalsTLSData *tls = tls_v; MEM_SAFE_FREE(tls->face_normals); @@ -857,7 +867,7 @@ static void subdiv_ccg_recalc_modified_inner_grid_normals(SubdivCCG *subdiv_ccg, BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_recalc_modified_inner_normal_finalize; + parallel_range_settings.func_free = subdiv_ccg_recalc_modified_inner_normal_free; BLI_task_parallel_range(0, num_effected_faces, &data, @@ -885,9 +895,11 @@ void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg, subdiv_ccg_average_all_boundaries_and_corners(subdiv_ccg, &key); } -/* ============================================================================= - * Boundary averaging/stitching. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Boundary averaging/stitching + * \{ */ typedef struct AverageInnerGridsData { SubdivCCG *subdiv_ccg; @@ -1077,8 +1089,8 @@ static void subdiv_ccg_average_grids_boundaries_task(void *__restrict userdata_v subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, tls); } -static void subdiv_ccg_average_grids_boundaries_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_average_grids_boundaries_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { AverageGridsBoundariesTLSData *tls = tls_v; MEM_SAFE_FREE(tls->accumulators); @@ -1136,7 +1148,7 @@ static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key AverageGridsBoundariesTLSData tls_data = {NULL}; parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_average_grids_boundaries_finalize; + parallel_range_settings.func_free = subdiv_ccg_average_grids_boundaries_free; BLI_task_parallel_range(0, subdiv_ccg->num_adjacent_edges, &boundaries_data, @@ -1244,9 +1256,11 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg, *r_num_loops = *r_num_faces * 4; } -/* ============================================================================= - * Neighbors. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Neighbors + * \{ */ void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord) { @@ -1791,3 +1805,5 @@ int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int gri const int face_index = face - subdiv_ccg->faces; return face_index; } + +/** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_deform.c b/source/blender/blenkernel/intern/subdiv_deform.c index db0a51c390b..f03cf4c4d21 100644 --- a/source/blender/blenkernel/intern/subdiv_deform.c +++ b/source/blender/blenkernel/intern/subdiv_deform.c @@ -39,9 +39,9 @@ #include "MEM_guardedalloc.h" -/* ================================================================================================ - * Subdivision context. - */ +/* -------------------------------------------------------------------- */ +/** \name Subdivision context + * \{ */ typedef struct SubdivDeformContext { const Mesh *coarse_mesh; @@ -77,9 +77,11 @@ static void subdiv_mesh_context_free(SubdivDeformContext *ctx) MEM_SAFE_FREE(ctx->accumulated_counters); } -/* ================================================================================================ - * Accumulation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Accumulation helpers + * \{ */ static void subdiv_accumulate_vertex_displacement(SubdivDeformContext *ctx, const int ptex_face_index, @@ -105,9 +107,11 @@ static void subdiv_accumulate_vertex_displacement(SubdivDeformContext *ctx, ++ctx->accumulated_counters[vertex_index]; } -/* ================================================================================================ - * Subdivision callbacks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Subdivision callbacks + * \{ */ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context, const int UNUSED(num_vertices), @@ -165,9 +169,11 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex add_v3_v3(vertex_co, D); } -/* ================================================================================================ - * Initialization. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Initialization + * \{ */ static void setup_foreach_callbacks(const SubdivDeformContext *subdiv_context, SubdivForeachContext *foreach_context) @@ -182,9 +188,11 @@ static void setup_foreach_callbacks(const SubdivDeformContext *subdiv_context, foreach_context->vertex_corner = subdiv_mesh_vertex_corner; } -/* ================================================================================================ - * Public entry point. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public entry point + * \{ */ void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv, const struct Mesh *coarse_mesh, @@ -234,3 +242,5 @@ void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv, /* Free used memory. */ subdiv_mesh_context_free(&subdiv_context); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c index b31fb2c9312..ff7f6fad5f0 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.c +++ b/source/blender/blenkernel/intern/subdiv_foreach.c @@ -40,9 +40,9 @@ #include "MEM_guardedalloc.h" -/* ============================================================================= - * General helpers. - */ +/* -------------------------------------------------------------------- */ +/** \name General helpers + * \{ */ /* Number of ptex faces for a given polygon. */ BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly *poly) @@ -75,9 +75,11 @@ BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution) return (poly->totloop == 4) ? (resolution) : ((resolution >> 1) + 1); } -/* ============================================================================= - * Context which is passed to all threaded tasks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Context which is passed to all threaded tasks + * \{ */ typedef struct SubdivForeachTaskContext { const Mesh *coarse_mesh; @@ -122,9 +124,11 @@ typedef struct SubdivForeachTaskContext { BLI_bitmap *coarse_edges_used_map; } SubdivForeachTaskContext; -/* ============================================================================= - * Threading helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Threading helpers + * \{ */ static void *subdiv_foreach_tls_alloc(SubdivForeachTaskContext *ctx) { @@ -148,9 +152,11 @@ static void subdiv_foreach_tls_free(SubdivForeachTaskContext *ctx, void *tls) MEM_freeN(tls); } -/* ============================================================================= - * Initialization. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Initialization + * \{ */ /* NOTE: Expects edge map to be zeroed. */ static void subdiv_foreach_ctx_count(SubdivForeachTaskContext *ctx) @@ -294,9 +300,11 @@ static void subdiv_foreach_ctx_free(SubdivForeachTaskContext *ctx) MEM_freeN(ctx->subdiv_polygon_offset); } -/* ============================================================================= - * Vertex traversal process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex traversal process + * \{ */ /* Traversal of corner vertices. They are coming from coarse vertices. */ @@ -706,9 +714,11 @@ static void subdiv_foreach_vertices(SubdivForeachTaskContext *ctx, void *tls, co } } -/* ============================================================================= - * Edge traversal process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edge traversal process + * \{ */ /* TODO(sergey): Coarse edge are always NONE, consider getting rid of it. */ static int subdiv_foreach_edges_row(SubdivForeachTaskContext *ctx, @@ -1022,9 +1032,11 @@ static void subdiv_foreach_boundary_edges(SubdivForeachTaskContext *ctx, ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2); } -/* ============================================================================= - * Loops traversal. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loops traversal + * \{ */ static void rotate_indices(const int rot, int *a, int *b, int *c, int *d) { @@ -1666,9 +1678,11 @@ static void subdiv_foreach_loops(SubdivForeachTaskContext *ctx, void *tls, int p } } -/* ============================================================================= - * Polygons traverse process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Polygons traverse process + * \{ */ static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int poly_index) { @@ -1697,9 +1711,11 @@ static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int p } } -/* ============================================================================= - * Loose elements traverse process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loose elements traverse process + * \{ */ static void subdiv_foreach_loose_vertices_task(void *__restrict userdata, const int coarse_vertex_index, @@ -1754,9 +1770,11 @@ static void subdiv_foreach_vertices_of_loose_edges_task(void *__restrict userdat } } -/* ============================================================================= - * Subdivision process entry points. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Subdivision process entry points + * \{ */ static void subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext *ctx, void *tls) { @@ -1838,9 +1856,9 @@ static void subdiv_foreach_boundary_edges_task(void *__restrict userdata, subdiv_foreach_boundary_edges(ctx, tls->userdata_chunk, edge_index); } -static void subdiv_foreach_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void subdiv_foreach_free(const void *__restrict userdata, void *__restrict userdata_chunk) { - SubdivForeachTaskContext *ctx = userdata; + const SubdivForeachTaskContext *ctx = userdata; ctx->foreach_context->user_data_tls_free(userdata_chunk); } @@ -1873,7 +1891,7 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, parallel_range_settings.userdata_chunk_size = context->user_data_tls_size; parallel_range_settings.min_iter_per_thread = 1; if (context->user_data_tls_free != NULL) { - parallel_range_settings.func_finalize = subdiv_foreach_finalize; + parallel_range_settings.func_free = subdiv_foreach_free; } /* TODO(sergey): Possible optimization is to have a single pool and push all @@ -1908,3 +1926,5 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, subdiv_foreach_ctx_free(&ctx); return true; } + +/** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index bd091108b11..987cc0311c7 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -41,9 +41,9 @@ #include "MEM_guardedalloc.h" -/* ============================================================================= - * Subdivision context. - */ +/* -------------------------------------------------------------------- */ +/** \name Subdivision Context + * \{ */ typedef struct SubdivMeshContext { const SubdivToMeshSettings *settings; @@ -119,9 +119,11 @@ static void subdiv_mesh_context_free(SubdivMeshContext *ctx) MEM_SAFE_FREE(ctx->accumulated_counters); } -/* ============================================================================= - * Loop custom data copy helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop custom data copy helpers + * \{ */ typedef struct LoopsOfPtex { /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */ @@ -159,9 +161,11 @@ static void loops_of_ptex_get(const SubdivMeshContext *ctx, } } -/* ============================================================================= - * Vertex custom data interpolation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex custom data interpolation helpers + * \{ */ /* TODO(sergey): Somehow de-duplicate with loops storage, without too much * exception cases all over the code. */ @@ -295,9 +299,11 @@ static void vertex_interpolation_end(VerticesForInterpolation *vertex_interpolat } } -/* ============================================================================= - * Loop custom data interpolation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop custom data interpolation helpers + * \{ */ typedef struct LoopsForInterpolation { /* This field points to a loop data which is to be used for interpolation. @@ -413,9 +419,11 @@ static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation) } } -/* ============================================================================= - * TLS. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name TLS + * \{ */ typedef struct SubdivMeshTLS { bool vertex_interpolation_initialized; @@ -440,9 +448,11 @@ static void subdiv_mesh_tls_free(void *tls_v) } } -/* ============================================================================= - * Evaluation helper functions. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation helper functions + * \{ */ static void eval_final_point_and_vertex_normal(Subdiv *subdiv, const int ptex_face_index, @@ -459,9 +469,11 @@ static void eval_final_point_and_vertex_normal(Subdiv *subdiv, } } -/* ============================================================================= - * Accumulation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Accumulation helpers + * \{ */ static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext *ctx, const int ptex_face_index, @@ -490,9 +502,11 @@ static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext * ++ctx->accumulated_counters[subdiv_vertex_index]; } -/* ============================================================================= - * Callbacks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Callbacks + * \{ */ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context, const int num_vertices, @@ -513,9 +527,11 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex return true; } -/* ============================================================================= - * Vertex subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex subdivision process + * \{ */ static void subdiv_vertex_data_copy(const SubdivMeshContext *ctx, const MVert *coarse_vertex, @@ -778,9 +794,11 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vert, u, v); } -/* ============================================================================= - * Edge subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edge subdivision process + * \{ */ static void subdiv_copy_edge_data(SubdivMeshContext *ctx, MEdge *subdiv_edge, @@ -827,9 +845,11 @@ static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context, subdiv_edge->v2 = subdiv_v2; } -/* ============================================================================= - * Loops creation/interpolation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loops creation/interpolation + * \{ */ static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx, MLoop *subdiv_loop, @@ -921,9 +941,11 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context, subdiv_loop->e = subdiv_edge_index; } -/* ============================================================================= - * Polygons subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Polygons subdivision process + * \{ */ static void subdiv_copy_poly_data(const SubdivMeshContext *ctx, MPoly *subdiv_poly, @@ -955,9 +977,11 @@ static void subdiv_mesh_poly(const SubdivForeachContext *foreach_context, subdiv_poly->totloop = num_loops; } -/* ============================================================================= - * Loose elements subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loose elements subdivision process + * \{ */ static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context, void *UNUSED(tls), @@ -1127,9 +1151,11 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext * normal_float_to_short_v3(subdiv_vertex->no, no); } -/* ============================================================================= - * Initialization. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Initialization + * \{ */ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context, SubdivForeachContext *foreach_context) @@ -1157,9 +1183,11 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context, foreach_context->user_data_tls_free = subdiv_mesh_tls_free; } -/* ============================================================================= - * Public entry point. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public entry point + * \{ */ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv, const SubdivToMeshSettings *settings, @@ -1206,3 +1234,5 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv, subdiv_mesh_context_free(&subdiv_context); return result; } + +/** \} */ diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index fe10861f96e..49c5c073f49 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -57,6 +57,7 @@ #include "BKE_image.h" #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_scene.h" @@ -112,7 +113,7 @@ static void texture_free_data(ID *id) /* is no lib link block, but texture extension */ if (texture->nodetree) { - ntreeFreeNestedTree(texture->nodetree); + ntreeFreeEmbeddedTree(texture->nodetree); MEM_freeN(texture->nodetree); texture->nodetree = NULL; } @@ -123,6 +124,16 @@ static void texture_free_data(ID *id) BKE_previewimg_free(&texture->preview); } +static void texture_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Tex *texture = (Tex *)id; + if (texture->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&texture->nodetree); + } + BKE_LIB_FOREACHID_PROCESS(data, texture->ima, IDWALK_CB_USER); +} + IDTypeInfo IDType_ID_TE = { .id_code = ID_TE, .id_filter = FILTER_ID_TE, @@ -137,6 +148,7 @@ IDTypeInfo IDType_ID_TE = { .copy_data = texture_copy_data, .free_data = texture_free_data, .make_local = NULL, + .foreach_id = texture_foreach_id, }; /* ****************** Mapping ******************* */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 0204667b3bd..97d95cb7e46 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -2288,13 +2288,15 @@ void BKE_tracking_distortion_free(MovieDistortion *distortion) MEM_freeN(distortion); } -void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r_co[2]) +void BKE_tracking_distort_v2( + MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2]) { const MovieTrackingCamera *camera = &tracking->camera; const float aspy = 1.0f / tracking->camera.pixel_aspect; libmv_CameraIntrinsicsOptions camera_intrinsics_options; - tracking_cameraIntrinscisOptionsFromTracking(tracking, 0, 0, &camera_intrinsics_options); + tracking_cameraIntrinscisOptionsFromTracking( + tracking, image_width, image_height, &camera_intrinsics_options); libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options); /* Normalize coordinates. */ @@ -2309,13 +2311,15 @@ void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r r_co[1] = y; } -void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float r_co[2]) +void BKE_tracking_undistort_v2( + MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2]) { const MovieTrackingCamera *camera = &tracking->camera; const float aspy = 1.0f / tracking->camera.pixel_aspect; libmv_CameraIntrinsicsOptions camera_intrinsics_options; - tracking_cameraIntrinscisOptionsFromTracking(tracking, 0, 0, &camera_intrinsics_options); + tracking_cameraIntrinscisOptionsFromTracking( + tracking, image_width, image_height, &camera_intrinsics_options); libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options); double x = co[0], y = co[1]; @@ -2361,13 +2365,19 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, } void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, + int image_width, + int image_height, rcti *rect, bool undistort, float delta[2]) { float pos[2], warped_pos[2]; const int coord_delta = 5; - void (*apply_distortion)(MovieTracking * tracking, const float pos[2], float out[2]); + void (*apply_distortion)(MovieTracking * tracking, + int image_width, + int image_height, + const float pos[2], + float out[2]); if (undistort) { apply_distortion = BKE_tracking_undistort_v2; @@ -2387,7 +2397,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = a; pos[1] = rect->ymin; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -2396,7 +2406,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = a; pos[1] = rect->ymax; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -2415,7 +2425,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = rect->xmin; pos[1] = a; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -2424,7 +2434,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = rect->xmax; pos[1] = a; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 5f7452e4775..629c01ec298 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -451,6 +451,12 @@ static void distortion_model_parameters_from_tracking( camera_intrinsics_options->division_k1 = camera->division_k1; camera_intrinsics_options->division_k2 = camera->division_k2; return; + + case TRACKING_DISTORTION_MODEL_NUKE: + camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_NUKE; + camera_intrinsics_options->nuke_k1 = camera->nuke_k1; + camera_intrinsics_options->nuke_k2 = camera->nuke_k2; + return; } /* Unknown distortion model, which might be due to opening newer file in older Blender. @@ -479,6 +485,12 @@ static void distortion_model_parameters_from_options( camera->division_k1 = camera_intrinsics_options->division_k1; camera->division_k2 = camera_intrinsics_options->division_k2; return; + + case LIBMV_DISTORTION_MODEL_NUKE: + camera->distortion_model = TRACKING_DISTORTION_MODEL_NUKE; + camera->nuke_k1 = camera_intrinsics_options->nuke_k1; + camera->nuke_k2 = camera_intrinsics_options->nuke_k2; + return; } /* Libmv returned distortion model which is not known to Blender. This is a logical error in code diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index b0b7a60b556..9e636c0ee8b 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -795,12 +795,52 @@ bool BKE_volume_is_points_only(const Volume *volume) /* Dependency Graph */ -static Volume *volume_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph), - struct Scene *UNUSED(scene), - Object *UNUSED(object), +static Volume *volume_evaluate_modifiers(struct Depsgraph *depsgraph, + struct Scene *scene, + Object *object, Volume *volume_input) { - return volume_input; + Volume *volume = volume_input; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; + const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); + + /* Evaluate modifiers. */ + for (; md; md = md->next) { + const ModifierTypeInfo *mti = (const ModifierTypeInfo *)BKE_modifier_get_info( + (ModifierType)md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if (mti->modifyVolume) { + /* Ensure we are not modifying the input. */ + if (volume == volume_input) { + volume = BKE_volume_copy_for_eval(volume, true); + } + + Volume *volume_next = mti->modifyVolume(md, &mectx, volume); + + if (volume_next && volume_next != volume) { + /* If the modifier returned a new volume, release the old one. */ + if (volume != volume_input) { + BKE_id_free(NULL, volume); + } + volume = volume_next; + } + } + } + + return volume; } void BKE_volume_eval_geometry(struct Depsgraph *depsgraph, Volume *volume) diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index f2219ad1cf8..3be62750673 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -59,7 +59,7 @@ static void world_free_data(ID *id) /* is no lib link block, but world extension */ if (wrld->nodetree) { - ntreeFreeNestedTree(wrld->nodetree); + ntreeFreeEmbeddedTree(wrld->nodetree); MEM_freeN(wrld->nodetree); wrld->nodetree = NULL; } diff --git a/source/blender/blenlib/BLI_allocator.h b/source/blender/blenlib/BLI_allocator.hh index e2d39c4e897..c52db4aab53 100644 --- a/source/blender/blenlib/BLI_allocator.h +++ b/source/blender/blenlib/BLI_allocator.hh @@ -13,8 +13,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_ALLOCATOR_H__ -#define __BLI_ALLOCATOR_H__ +#ifndef __BLI_ALLOCATOR_HH__ +#define __BLI_ALLOCATOR_HH__ /** \file * \ingroup bli @@ -102,4 +102,4 @@ class RawAllocator { } // namespace BLI -#endif /* __BLI_ALLOCATOR_H__ */ +#endif /* __BLI_ALLOCATOR_HH__ */ diff --git a/source/blender/blenlib/BLI_array_cxx.h b/source/blender/blenlib/BLI_array.hh index 8fc2aec6698..9dd8341aa76 100644 --- a/source/blender/blenlib/BLI_array_cxx.h +++ b/source/blender/blenlib/BLI_array.hh @@ -13,8 +13,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_ARRAY_CXX_H__ -#define __BLI_ARRAY_CXX_H__ +#ifndef __BLI_ARRAY_HH__ +#define __BLI_ARRAY_HH__ /** \file * \ingroup bli @@ -23,20 +23,21 @@ * a template argument. Instead it can be specified at the construction time. */ -#include "BLI_allocator.h" -#include "BLI_array_ref.h" -#include "BLI_index_range.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_allocator.hh" +#include "BLI_array_ref.hh" +#include "BLI_index_range.hh" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" namespace BLI { -template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Array { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Array { private: T *m_data; uint m_size; Allocator m_allocator; - AlignedBuffer<sizeof(T) * N, alignof(T)> m_inline_storage; + AlignedBuffer<sizeof(T) * InlineBufferCapacity, alignof(T)> m_inline_storage; public: Array() @@ -79,7 +80,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ar m_allocator = other.m_allocator; m_data = this->get_buffer_for_size(other.size()); - copy_n(other.begin(), m_size, m_data); + uninitialized_copy_n(other.begin(), m_size, m_data); } Array(Array &&other) noexcept @@ -201,10 +202,15 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ar return IndexRange(m_size); } + Allocator &allocator() + { + return m_allocator; + } + private: T *get_buffer_for_size(uint size) { - if (size <= N) { + if (size <= InlineBufferCapacity) { return this->inline_storage(); } else { @@ -231,4 +237,4 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ar } // namespace BLI -#endif /* __BLI_ARRAY_CXX_H__ */ +#endif /* __BLI_ARRAY_HH__ */ diff --git a/source/blender/blenlib/BLI_array_ref.h b/source/blender/blenlib/BLI_array_ref.hh index 2c2e441a47d..c0484493bda 100644 --- a/source/blender/blenlib/BLI_array_ref.h +++ b/source/blender/blenlib/BLI_array_ref.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_ARRAY_REF_H__ -#define __BLI_ARRAY_REF_H__ +#ifndef __BLI_ARRAY_REF_HH__ +#define __BLI_ARRAY_REF_HH__ /** \file * \ingroup bli @@ -41,8 +41,8 @@ #include <string> #include <vector> -#include "BLI_index_range.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_index_range.hh" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" namespace BLI { @@ -508,6 +508,16 @@ template<typename T> class MutableArrayRef { BLI_assert(m_size > 0); return m_start[m_size - 1]; } + + /** + * Get a new array ref to the same underlying memory buffer. No conversions are done. + */ + template<typename NewT> MutableArrayRef<NewT> cast() const + { + BLI_assert((m_size * sizeof(T)) % sizeof(NewT) == 0); + uint new_size = m_size * sizeof(T) / sizeof(NewT); + return MutableArrayRef<NewT>(reinterpret_cast<NewT *>(m_start), new_size); + } }; /** @@ -542,4 +552,4 @@ void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3) } /* namespace BLI */ -#endif /* __BLI_ARRAY_REF_H__ */ +#endif /* __BLI_ARRAY_REF_HH__ */ diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h index d67fbabd11c..2b811e50efb 100644 --- a/source/blender/blenlib/BLI_bitmap.h +++ b/source/blender/blenlib/BLI_bitmap.h @@ -24,12 +24,12 @@ * \ingroup bli */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - typedef unsigned int BLI_bitmap; /* warning: the bitmap does not keep track of its own size or check diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 41603bb4f06..6dd1abacf78 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -52,10 +52,6 @@ #include <stdlib.h> -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_listbase.h" #include "BLI_string.h" @@ -68,8 +64,4 @@ extern "C" { #include "BLI_rect.h" -#ifdef __cplusplus -} -#endif - #endif diff --git a/source/blender/blenlib/BLI_color.hh b/source/blender/blenlib/BLI_color.hh new file mode 100644 index 00000000000..ff28ae2c076 --- /dev/null +++ b/source/blender/blenlib/BLI_color.hh @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#ifndef __BLI_COLOR_HH__ +#define __BLI_COLOR_HH__ + +#include <iostream> + +#include "BLI_math_color.h" + +namespace BLI { + +struct Color4f { + float r, g, b, a; + + Color4f() = default; + + Color4f(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) + { + } + + operator float *() + { + return &r; + } + + operator const float *() const + { + return &r; + } + + friend std::ostream &operator<<(std::ostream &stream, Color4f c) + { + stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")"; + return stream; + } +}; + +struct Color4b { + uint8_t r, g, b, a; + + Color4b() = default; + + Color4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) + { + } + + Color4b(Color4f other) + { + rgba_float_to_uchar(*this, other); + } + + operator Color4f() const + { + Color4f result; + rgba_uchar_to_float(result, *this); + return result; + } + + operator uint8_t *() + { + return &r; + } + + operator const uint8_t *() const + { + return &r; + } + + friend std::ostream &operator<<(std::ostream &stream, Color4b c) + { + stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")"; + return stream; + } +}; + +} // namespace BLI + +#endif /* __BLI_COLOR_HH__ */ diff --git a/source/blender/blenlib/BLI_dot_export.hh b/source/blender/blenlib/BLI_dot_export.hh new file mode 100644 index 00000000000..08c37fec01e --- /dev/null +++ b/source/blender/blenlib/BLI_dot_export.hh @@ -0,0 +1,290 @@ +/* + * 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. + */ + +#ifndef __BLI_DOT_EXPORT_HH__ +#define __BLI_DOT_EXPORT_HH__ + +/** + * Language grammar: https://www.graphviz.org/doc/info/lang.html + * Attributes: https://www.graphviz.org/doc/info/attrs.html + * Node Shapes: https://www.graphviz.org/doc/info/shapes.html + * Preview: https://dreampuf.github.io/GraphvizOnline + */ + +#include "BLI_map.hh" +#include "BLI_optional.hh" +#include "BLI_set.hh" +#include "BLI_string_map.hh" +#include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" + +#include "BLI_dot_export_attribute_enums.hh" + +#include <sstream> + +namespace BLI { +namespace DotExport { + +class Graph; +class DirectedGraph; +class UndirectedGraph; +class Node; +class NodePort; +class DirectedEdge; +class UndirectedEdge; +class Cluster; +class AttributeList; + +class AttributeList { + private: + Map<std::string, std::string> m_attributes; + + public: + void export__as_bracket_list(std::stringstream &ss) const; + + void set(StringRef key, StringRef value) + { + m_attributes.add_override(key, value); + } +}; + +class Graph { + private: + AttributeList m_attributes; + Vector<std::unique_ptr<Node>> m_nodes; + Vector<std::unique_ptr<Cluster>> m_clusters; + + Set<Node *> m_top_level_nodes; + Set<Cluster *> m_top_level_clusters; + + friend Cluster; + friend Node; + + public: + Node &new_node(StringRef label); + Cluster &new_cluster(StringRef label = ""); + + void export__declare_nodes_and_clusters(std::stringstream &ss) const; + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_rankdir(Attr_rankdir rankdir) + { + this->set_attribute("rankdir", rankdir_to_string(rankdir)); + } + + void set_random_cluster_bgcolors(); +}; + +class Cluster { + private: + AttributeList m_attributes; + Graph &m_graph; + Cluster *m_parent = nullptr; + Set<Cluster *> m_children; + Set<Node *> m_nodes; + + friend Graph; + friend Node; + + Cluster(Graph &graph) : m_graph(graph) + { + } + + public: + void export__declare_nodes_and_clusters(std::stringstream &ss) const; + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_parent_cluster(Cluster *cluster); + void set_parent_cluster(Cluster &cluster) + { + this->set_parent_cluster(&cluster); + } + + void set_random_cluster_bgcolors(); +}; + +class Node { + private: + AttributeList m_attributes; + Graph &m_graph; + Cluster *m_cluster = nullptr; + + friend Graph; + + Node(Graph &graph) : m_graph(graph) + { + } + + public: + const AttributeList &attributes() const + { + return m_attributes; + } + + AttributeList &attributes() + { + return m_attributes; + } + + void set_parent_cluster(Cluster *cluster); + void set_parent_cluster(Cluster &cluster) + { + this->set_parent_cluster(&cluster); + } + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_shape(Attr_shape shape) + { + this->set_attribute("shape", shape_to_string(shape)); + } + + /* See https://www.graphviz.org/doc/info/attrs.html#k:color. */ + void set_background_color(StringRef name) + { + this->set_attribute("fillcolor", name); + this->set_attribute("style", "filled"); + } + + void export__as_id(std::stringstream &ss) const; + + void export__as_declaration(std::stringstream &ss) const; +}; + +class UndirectedGraph final : public Graph { + private: + Vector<std::unique_ptr<UndirectedEdge>> m_edges; + + public: + std::string to_dot_string() const; + + UndirectedEdge &new_edge(NodePort a, NodePort b); +}; + +class DirectedGraph final : public Graph { + private: + Vector<std::unique_ptr<DirectedEdge>> m_edges; + + public: + std::string to_dot_string() const; + + DirectedEdge &new_edge(NodePort from, NodePort to); +}; + +class NodePort { + private: + Node *m_node; + Optional<std::string> m_port_name; + + public: + NodePort(Node &node, Optional<std::string> port_name = {}) + : m_node(&node), m_port_name(std::move(port_name)) + { + } + + void to_dot_string(std::stringstream &ss) const; +}; + +class Edge : BLI::NonCopyable, BLI::NonMovable { + protected: + AttributeList m_attributes; + NodePort m_a; + NodePort m_b; + + public: + Edge(NodePort a, NodePort b) : m_a(std::move(a)), m_b(std::move(b)) + { + } + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_arrowhead(Attr_arrowType type) + { + this->set_attribute("arrowhead", arrowType_to_string(type)); + } + + void set_arrowtail(Attr_arrowType type) + { + this->set_attribute("arrowtail", arrowType_to_string(type)); + } + + void set_dir(Attr_dirType type) + { + this->set_attribute("dir", dirType_to_string(type)); + } +}; + +class DirectedEdge : public Edge { + public: + DirectedEdge(NodePort from, NodePort to) : Edge(std::move(from), std::move(to)) + { + } + + void export__as_edge_statement(std::stringstream &ss) const; +}; + +class UndirectedEdge : public Edge { + public: + UndirectedEdge(NodePort a, NodePort b) : Edge(std::move(a), std::move(b)) + { + } + + void export__as_edge_statement(std::stringstream &ss) const; +}; + +std::string color_attr_from_hsv(float h, float s, float v); + +class NodeWithSocketsRef { + private: + Node *m_node; + + public: + NodeWithSocketsRef(Node &node, + StringRef name, + ArrayRef<std::string> input_names, + ArrayRef<std::string> output_names); + + NodePort input(uint index) const + { + std::string port = "\"in" + std::to_string(index) + "\""; + return NodePort(*m_node, port); + } + + NodePort output(uint index) const + { + std::string port = "\"out" + std::to_string(index) + "\""; + return NodePort(*m_node, port); + } +}; + +} // namespace DotExport +} // namespace BLI + +#endif /* __BLI_DOT_EXPORT_HH__ */ diff --git a/source/blender/blenlib/BLI_dot_export_attribute_enums.hh b/source/blender/blenlib/BLI_dot_export_attribute_enums.hh new file mode 100644 index 00000000000..8e61f46dc12 --- /dev/null +++ b/source/blender/blenlib/BLI_dot_export_attribute_enums.hh @@ -0,0 +1,125 @@ +/* + * 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. + */ + +#ifndef __BLI_DOT_EXPORT_ATTRIBUTE_ENUMS_HH__ +#define __BLI_DOT_EXPORT_ATTRIBUTE_ENUMS_HH__ + +#include "BLI_string_ref.hh" + +namespace BLI { +namespace DotExport { + +enum class Attr_rankdir { + LeftToRight, + TopToBottom, +}; + +inline StringRef rankdir_to_string(Attr_rankdir value) +{ + switch (value) { + case Attr_rankdir::LeftToRight: + return "LR"; + case Attr_rankdir::TopToBottom: + return "TB"; + } + return ""; +} + +enum class Attr_shape { + Rectangle, + Ellipse, + Circle, + Point, + Diamond, + Square, +}; + +inline StringRef shape_to_string(Attr_shape value) +{ + switch (value) { + case Attr_shape::Rectangle: + return "rectangle"; + case Attr_shape::Ellipse: + return "ellipse"; + case Attr_shape::Circle: + return "circle"; + case Attr_shape::Point: + return "point"; + case Attr_shape::Diamond: + return "diamond"; + case Attr_shape::Square: + return "square"; + } + return ""; +} + +enum class Attr_arrowType { + Normal, + Inv, + Dot, + None, + Empty, + Box, + Vee, +}; + +inline StringRef arrowType_to_string(Attr_arrowType value) +{ + switch (value) { + case Attr_arrowType::Normal: + return "normal"; + case Attr_arrowType::Inv: + return "inv"; + case Attr_arrowType::Dot: + return "dot"; + case Attr_arrowType::None: + return "none"; + case Attr_arrowType::Empty: + return "empty"; + case Attr_arrowType::Box: + return "box"; + case Attr_arrowType::Vee: + return "vee"; + } + return ""; +} + +enum class Attr_dirType { + Forward, + Back, + Both, + None, +}; + +inline StringRef dirType_to_string(Attr_dirType value) +{ + switch (value) { + case Attr_dirType::Forward: + return "forward"; + case Attr_dirType::Back: + return "back"; + case Attr_dirType::Both: + return "both"; + case Attr_dirType::None: + return "none"; + } + return ""; +} + +} // namespace DotExport +} // namespace BLI + +#endif /* __BLI_DOT_EXPORT_ATTRIBUTE_ENUMS_HH__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 4eb6f184a76..fe4600b9121 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -29,10 +29,6 @@ #include <stdio.h> #include <sys/stat.h> -#ifdef __cplusplus -extern "C" { -#endif - /* for size_t (needed on windows) */ #include <stddef.h> @@ -41,6 +37,10 @@ extern "C" { #include "BLI_compiler_attrs.h" #include "BLI_utildefines.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifndef PATH_MAX # define PATH_MAX 4096 #endif diff --git a/source/blender/blenlib/BLI_float2.hh b/source/blender/blenlib/BLI_float2.hh new file mode 100644 index 00000000000..da12dd7d206 --- /dev/null +++ b/source/blender/blenlib/BLI_float2.hh @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#ifndef __BLI_FLOAT2_HH__ +#define __BLI_FLOAT2_HH__ + +#include "BLI_float3.hh" + +namespace BLI { + +struct float2 { + float x, y; + + float2() = default; + + float2(const float *ptr) : x{ptr[0]}, y{ptr[1]} + { + } + + float2(float x, float y) : x(x), y(y) + { + } + + float2(const float3 &other) : x(other.x), y(other.y) + { + } + + operator float *() + { + return &x; + } + + operator const float *() const + { + return &x; + } + + friend float2 operator+(const float2 &a, const float2 &b) + { + return {a.x + b.x, a.y + b.y}; + } + + friend float2 operator-(const float2 &a, const float2 &b) + { + return {a.x - b.x, a.y - b.y}; + } + + friend float2 operator*(const float2 &a, float b) + { + return {a.x * b, a.y * b}; + } + + friend float2 operator/(const float2 &a, float b) + { + BLI_assert(b != 0.0f); + return {a.x / b, a.y / b}; + } + + friend float2 operator*(float a, const float2 &b) + { + return b * a; + } + + friend std::ostream &operator<<(std::ostream &stream, const float2 &v) + { + stream << "(" << v.x << ", " << v.y << ")"; + return stream; + } +}; + +} // namespace BLI + +#endif /* __BLI_FLOAT2_HH__ */ diff --git a/source/blender/blenlib/BLI_float3.hh b/source/blender/blenlib/BLI_float3.hh new file mode 100644 index 00000000000..9678fa4b2d3 --- /dev/null +++ b/source/blender/blenlib/BLI_float3.hh @@ -0,0 +1,218 @@ +/* + * 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. + */ + +#ifndef __BLI_FLOAT3_HH__ +#define __BLI_FLOAT3_HH__ + +#include <iostream> + +#include "BLI_math_vector.h" + +namespace BLI { + +struct float3 { + float x, y, z; + + float3() = default; + + float3(const float *ptr) : x{ptr[0]}, y{ptr[1]}, z{ptr[2]} + { + } + + float3(const float (*ptr)[3]) : float3((const float *)ptr) + { + } + + explicit float3(float value) : x(value), y(value), z(value) + { + } + + explicit float3(int value) : x(value), y(value), z(value) + { + } + + float3(float x, float y, float z) : x{x}, y{y}, z{z} + { + } + + operator const float *() const + { + return &x; + } + + operator float *() + { + return &x; + } + + float normalize_and_get_length() + { + return normalize_v3(*this); + } + + float3 normalized() const + { + float3 result; + normalize_v3_v3(result, *this); + return result; + } + + float length() const + { + return len_v3(*this); + } + + float length_squared() const + { + return len_squared_v3(*this); + } + + void reflect(const float3 &normal) + { + *this = this->reflected(normal); + } + + float3 reflected(const float3 &normal) const + { + float3 result; + reflect_v3_v3v3(result, *this, normal); + return result; + } + + static float3 safe_divide(const float3 &a, const float3 &b) + { + float3 result; + result.x = (b.x == 0.0f) ? 0.0f : a.x / b.x; + result.y = (b.y == 0.0f) ? 0.0f : a.y / b.y; + result.z = (b.z == 0.0f) ? 0.0f : a.z / b.z; + return result; + } + + void invert() + { + x = -x; + y = -y; + z = -z; + } + + friend float3 operator+(const float3 &a, const float3 &b) + { + return {a.x + b.x, a.y + b.y, a.z + b.z}; + } + + void operator+=(const float3 &b) + { + this->x += b.x; + this->y += b.y; + this->z += b.z; + } + + friend float3 operator-(const float3 &a, const float3 &b) + { + return {a.x - b.x, a.y - b.y, a.z - b.z}; + } + + friend float3 operator-(const float3 &a) + { + return {-a.x, -a.y, -a.z}; + } + + void operator-=(const float3 &b) + { + this->x -= b.x; + this->y -= b.y; + this->z -= b.z; + } + + void operator*=(float scalar) + { + this->x *= scalar; + this->y *= scalar; + this->z *= scalar; + } + + void operator*=(const float3 &other) + { + this->x *= other.x; + this->y *= other.y; + this->z *= other.z; + } + + friend float3 operator*(const float3 &a, const float3 &b) + { + return {a.x * b.x, a.y * b.y, a.z * b.z}; + } + + friend float3 operator*(const float3 &a, float b) + { + return {a.x * b, a.y * b, a.z * b}; + } + + friend float3 operator*(float a, const float3 &b) + { + return b * a; + } + + friend float3 operator/(const float3 &a, float b) + { + BLI_assert(b != 0.0f); + return {a.x / b, a.y / b, a.z / b}; + } + + friend std::ostream &operator<<(std::ostream &stream, const float3 &v) + { + stream << "(" << v.x << ", " << v.y << ", " << v.z << ")"; + return stream; + } + + static float dot(const float3 &a, const float3 &b) + { + return a.x * b.x + a.y * b.y + a.z * b.z; + } + + static float3 cross_high_precision(const float3 &a, const float3 &b) + { + float3 result; + cross_v3_v3v3_hi_prec(result, a, b); + return result; + } + + static float3 project(const float3 &a, const float3 &b) + { + float3 result; + project_v3_v3v3(result, a, b); + return result; + } + + static float distance(const float3 &a, const float3 &b) + { + return (a - b).length(); + } + + static float distance_squared(const float3 &a, const float3 &b) + { + return float3::dot(a, b); + } + + static float3 interpolate(const float3 &a, const float3 &b, float t) + { + return a * (1 - t) + b * t; + } +}; + +} // namespace BLI + +#endif /* __BLI_FLOAT3_HH__ */ diff --git a/source/blender/blenlib/BLI_float4x4.hh b/source/blender/blenlib/BLI_float4x4.hh new file mode 100644 index 00000000000..36186d319c9 --- /dev/null +++ b/source/blender/blenlib/BLI_float4x4.hh @@ -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. + */ + +#ifndef __BLI_FLOAT4X4_HH__ +#define __BLI_FLOAT4X4_HH__ + +#include "BLI_float3.hh" +#include "BLI_math_matrix.h" + +namespace BLI { + +struct float4x4 { + float values[4][4]; + + float4x4() = default; + + float4x4(const float *matrix) + { + memcpy(values, matrix, sizeof(float) * 16); + } + + float4x4(const float matrix[4][4]) : float4x4((float *)matrix) + { + } + + operator float *() + { + return (float *)this; + } + + operator const float *() const + { + return (const float *)this; + } + + float4x4 inverted() const + { + float result[4][4]; + invert_m4_m4(result, values); + return result; + } + + /** + * Matrix inversion can be implemented more efficiently for affine matrices. + */ + float4x4 inverted_affine() const + { + BLI_assert(values[0][3] == 0.0f && values[1][3] == 0.0f && values[2][3] == 0.0f && + values[3][3] == 1.0f); + return this->inverted(); + } + + friend float4x4 operator*(const float4x4 &a, const float4x4 &b) + { + float4x4 result; + mul_m4_m4m4(result.values, a.values, b.values); + return result; + } + + /** + * This also applies the translation on the vector. Use `m.ref_3x3() * v` if that is not + * intended. + */ + friend float3 operator*(const float4x4 &m, const float3 &v) + { + float3 result; + mul_v3_m4v3(result, m.values, v); + return result; + } + + friend float3 operator*(const float4x4 &m, const float (*v)[3]) + { + return m * float3(v); + } + + struct float3x3_ref { + const float4x4 &data; + + friend float3 operator*(const float3x3_ref &m, const float3 &v) + { + float3 result; + mul_v3_mat3_m4v3(result, m.data.values, v); + return result; + } + }; + + float3x3_ref ref_3x3() const + { + return {*this}; + } + + static float4x4 interpolate(const float4x4 &a, const float4x4 &b, float t) + { + float result[4][4]; + interp_m4_m4m4(result, a.values, b.values, t); + return result; + } +}; + +} // namespace BLI + +#endif /* __BLI_FLOAT4X4_HH__ */ diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h index dffb2a165ee..b69bdb7057c 100644 --- a/source/blender/blenlib/BLI_gsqueue.h +++ b/source/blender/blenlib/BLI_gsqueue.h @@ -24,6 +24,8 @@ * \ingroup bli */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h index d09291b64be..96111ffaf5a 100644 --- a/source/blender/blenlib/BLI_hash.h +++ b/source/blender/blenlib/BLI_hash.h @@ -21,12 +21,12 @@ * \ingroup bli */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky) { #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) @@ -81,7 +81,7 @@ BLI_INLINE void BLI_hash_pointer_to_color(const void *ptr, int *r, int *g, int * { size_t val = (size_t)ptr; const size_t hash_a = BLI_hash_int(val & 0x0000ffff); - const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 32)); + const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 16)); const size_t hash = hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); *r = (hash & 0xff0000) >> 16; *g = (hash & 0x00ff00) >> 8; diff --git a/source/blender/blenlib/BLI_hash_cxx.h b/source/blender/blenlib/BLI_hash.hh index 22941a792ba..3b3448f66b1 100644 --- a/source/blender/blenlib/BLI_hash_cxx.h +++ b/source/blender/blenlib/BLI_hash.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_HASH_CXX_H__ -#define __BLI_HASH_CXX_H__ +#ifndef __BLI_HASH_HH__ +#define __BLI_HASH_HH__ /** \file * \ingroup bli @@ -30,6 +30,7 @@ #include <utility> #include "BLI_math_base.h" +#include "BLI_string_ref.hh" #include "BLI_utildefines.h" namespace BLI { @@ -67,14 +68,33 @@ template<> struct DefaultHash<float> { } }; +inline uint32_t hash_string(StringRef str) +{ + uint32_t hash = 5381; + for (char c : str) { + hash = hash * 33 + c; + } + return hash; +} + template<> struct DefaultHash<std::string> { uint32_t operator()(const std::string &value) const { - uint32_t hash = 5381; - for (char c : value) { - hash = hash * 33 + c; - } - return hash; + return hash_string(value); + } +}; + +template<> struct DefaultHash<StringRef> { + uint32_t operator()(const StringRef &value) const + { + return hash_string(value); + } +}; + +template<> struct DefaultHash<StringRefNull> { + uint32_t operator()(const StringRefNull &value) const + { + return hash_string(value); } }; @@ -109,4 +129,4 @@ template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> { } // namespace BLI -#endif /* __BLI_HASH_CXX_H__ */ +#endif /* __BLI_HASH_HH__ */ diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h index fa8e49ef376..ca5edcbead5 100644 --- a/source/blender/blenlib/BLI_heap.h +++ b/source/blender/blenlib/BLI_heap.h @@ -22,12 +22,12 @@ * \brief A min-heap / priority queue ADT */ +#include "BLI_math.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math.h" - struct Heap; struct HeapNode; typedef struct Heap Heap; diff --git a/source/blender/blenlib/BLI_index_range.h b/source/blender/blenlib/BLI_index_range.hh index 4553c996454..e24fd567810 100644 --- a/source/blender/blenlib/BLI_index_range.h +++ b/source/blender/blenlib/BLI_index_range.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_INDEX_RANGE_H__ -#define __BLI_INDEX_RANGE_H__ +#ifndef __BLI_INDEX_RANGE_HH__ +#define __BLI_INDEX_RANGE_HH__ /** \file * \ingroup bli @@ -208,4 +208,4 @@ class IndexRange { } // namespace BLI -#endif /* __BLI_INDEX_RANGE_H__ */ +#endif /* __BLI_INDEX_RANGE_HH__ */ diff --git a/source/blender/blenlib/BLI_lasso_2d.h b/source/blender/blenlib/BLI_lasso_2d.h index 56db360dab0..fb661c41784 100644 --- a/source/blender/blenlib/BLI_lasso_2d.h +++ b/source/blender/blenlib/BLI_lasso_2d.h @@ -30,14 +30,14 @@ extern "C" { struct rcti; -void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const unsigned int moves); -bool BLI_lasso_is_point_inside(const int mcords[][2], - const unsigned int moves, +void BLI_lasso_boundbox(struct rcti *rect, const int mcoords[][2], const unsigned int mcoords_len); +bool BLI_lasso_is_point_inside(const int mcoords[][2], + const unsigned int mcoords_len, const int sx, const int sy, const int error_value); -bool BLI_lasso_is_edge_inside(const int mcords[][2], - const unsigned int moves, +bool BLI_lasso_is_edge_inside(const int mcoords[][2], + const unsigned int mcoords_len, int x0, int y0, int x1, diff --git a/source/blender/blenlib/BLI_linear_allocator.hh b/source/blender/blenlib/BLI_linear_allocator.hh new file mode 100644 index 00000000000..285af49f500 --- /dev/null +++ b/source/blender/blenlib/BLI_linear_allocator.hh @@ -0,0 +1,220 @@ +/* + * 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 bli + * + * A linear allocator is the simplest form of an allocator. It never reuses any memory, and + * therefore does not need a deallocation method. It simply hands out consecutive buffers of + * memory. When the current buffer is full, it reallocates a new larger buffer and continues. + */ + +#ifndef __BLI_LINEAR_ALLOCATOR_HH__ +#define __BLI_LINEAR_ALLOCATOR_HH__ + +#include "BLI_string_ref.hh" +#include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" + +namespace BLI { + +template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopyable, NonMovable { + private: + Allocator m_allocator; + Vector<void *> m_owned_buffers; + Vector<ArrayRef<char>> m_unused_borrowed_buffers; + + uintptr_t m_current_begin; + uintptr_t m_current_end; + uint m_next_min_alloc_size; + +#ifdef DEBUG + uint m_debug_allocated_amount = 0; +#endif + + public: + LinearAllocator() + { + m_current_begin = 0; + m_current_end = 0; + m_next_min_alloc_size = 64; + } + + ~LinearAllocator() + { + for (void *ptr : m_owned_buffers) { + m_allocator.deallocate(ptr); + } + } + + /** + * Get a pointer to a memory buffer with the given size an alignment. The memory buffer will be + * freed when this LinearAllocator is destructed. + * + * The alignment has to be a power of 2. + */ + void *allocate(uint size, uint alignment) + { + BLI_assert(alignment >= 1); + BLI_assert(is_power_of_2_i(alignment)); + +#ifdef DEBUG + m_debug_allocated_amount += size; +#endif + + uintptr_t alignment_mask = alignment - 1; + uintptr_t potential_allocation_begin = (m_current_begin + alignment_mask) & ~alignment_mask; + uintptr_t potential_allocation_end = potential_allocation_begin + size; + + if (potential_allocation_end <= m_current_end) { + m_current_begin = potential_allocation_end; + return (void *)potential_allocation_begin; + } + else { + this->allocate_new_buffer(size + alignment); + return this->allocate(size, alignment); + } + }; + + /** + * Allocate a memory buffer that can hold an instance of T. + * + * This method only allocates memory and does not construct the instance. + */ + template<typename T> T *allocate() + { + return (T *)this->allocate(sizeof(T), alignof(T)); + } + + /** + * Allocate a memory buffer that can hold T array with the given size. + * + * This method only allocates memory and does not construct the instance. + */ + template<typename T> MutableArrayRef<T> allocate_array(uint size) + { + return MutableArrayRef<T>((T *)this->allocate(sizeof(T) * size, alignof(T)), size); + } + + /** + * Construct an instance of T in memory provided by this allocator. + * + * Arguments passed to this method will be forwarded to the constructor of T. + * + * You must not call `delete` on the returned pointer. + * Instead, the destruct has to be called explicitly. + */ + template<typename T, typename... Args> T *construct(Args &&... args) + { + void *buffer = this->allocate(sizeof(T), alignof(T)); + T *value = new (buffer) T(std::forward<Args>(args)...); + return value; + } + + /** + * Copy the given array into a memory buffer provided by this allocator. + */ + template<typename T> MutableArrayRef<T> construct_array_copy(ArrayRef<T> src) + { + MutableArrayRef<T> dst = this->allocate_array<T>(src.size()); + uninitialized_copy_n(src.begin(), src.size(), dst.begin()); + return dst; + } + + /** + * Copy the given string into a memory buffer provided by this allocator. The returned string is + * always null terminated. + */ + StringRefNull copy_string(StringRef str) + { + uint alloc_size = str.size() + 1; + char *buffer = (char *)this->allocate(alloc_size, 1); + str.copy(buffer, alloc_size); + return StringRefNull((const char *)buffer); + } + + MutableArrayRef<void *> allocate_elements_and_pointer_array(uint element_amount, + uint element_size, + uint element_alignment) + { + void *pointer_buffer = this->allocate(element_amount * sizeof(void *), alignof(void *)); + void *elements_buffer = this->allocate(element_amount * element_size, element_alignment); + + MutableArrayRef<void *> pointers((void **)pointer_buffer, element_amount); + void *next_element_buffer = elements_buffer; + for (uint i : IndexRange(element_amount)) { + pointers[i] = next_element_buffer; + next_element_buffer = POINTER_OFFSET(next_element_buffer, element_size); + } + + return pointers; + } + + template<typename T, typename... Args> + ArrayRef<T *> construct_elements_and_pointer_array(uint n, Args &&... args) + { + MutableArrayRef<void *> void_pointers = this->allocate_elements_and_pointer_array( + n, sizeof(T), alignof(T)); + MutableArrayRef<T *> pointers = void_pointers.cast<T *>(); + + for (uint i : IndexRange(n)) { + new (pointers[i]) T(std::forward<Args>(args)...); + } + + return pointers; + } + + /** + * Tell the allocator to use up the given memory buffer, before allocating new memory from the + * system. + */ + void provide_buffer(void *buffer, uint size) + { + m_unused_borrowed_buffers.append(ArrayRef<char>((char *)buffer, size)); + } + + template<uint Size, uint Alignment> + void provide_buffer(AlignedBuffer<Size, Alignment> &aligned_buffer) + { + this->provide_buffer(aligned_buffer.ptr(), Size); + } + + private: + void allocate_new_buffer(uint min_allocation_size) + { + for (uint i : m_unused_borrowed_buffers.index_range()) { + ArrayRef<char> buffer = m_unused_borrowed_buffers[i]; + if (buffer.size() >= min_allocation_size) { + m_unused_borrowed_buffers.remove_and_reorder(i); + m_current_begin = (uintptr_t)buffer.begin(); + m_current_end = (uintptr_t)buffer.end(); + return; + } + } + + uint size_in_bytes = power_of_2_min_u(std::max(min_allocation_size, m_next_min_alloc_size)); + m_next_min_alloc_size = size_in_bytes * 2; + + void *buffer = m_allocator.allocate(size_in_bytes, __func__); + m_owned_buffers.append(buffer); + m_current_begin = (uintptr_t)buffer; + m_current_end = m_current_begin + size_in_bytes; + } +}; + +} // namespace BLI + +#endif /* __BLI_LINEAR_ALLOCATOR_HH__ */ diff --git a/source/blender/blenlib/BLI_listbase_wrapper.h b/source/blender/blenlib/BLI_listbase_wrapper.hh index d6832166e35..02313d9d22d 100644 --- a/source/blender/blenlib/BLI_listbase_wrapper.h +++ b/source/blender/blenlib/BLI_listbase_wrapper.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_LISTBASE_WRAPPER_H__ -#define __BLI_LISTBASE_WRAPPER_H__ +#ifndef __BLI_LISTBASE_WRAPPER_HH__ +#define __BLI_LISTBASE_WRAPPER_HH__ /** \file * \ingroup bli @@ -29,17 +29,17 @@ namespace BLI { -template<typename T> class IntrusiveListBaseWrapper { +template<typename T> class ListBaseWrapper { private: ListBase *m_listbase; public: - IntrusiveListBaseWrapper(ListBase *listbase) : m_listbase(listbase) + ListBaseWrapper(ListBase *listbase) : m_listbase(listbase) { BLI_assert(listbase); } - IntrusiveListBaseWrapper(ListBase &listbase) : IntrusiveListBaseWrapper(&listbase) + ListBaseWrapper(ListBase &listbase) : ListBaseWrapper(&listbase) { } @@ -110,4 +110,4 @@ template<typename T> class IntrusiveListBaseWrapper { } /* namespace BLI */ -#endif /* __BLI_LISTBASE_WRAPPER_H__ */ +#endif /* __BLI_LISTBASE_WRAPPER_HH__ */ diff --git a/source/blender/blenlib/BLI_map.h b/source/blender/blenlib/BLI_map.hh index 4b7ac0791d9..ea5e5da4099 100644 --- a/source/blender/blenlib/BLI_map.h +++ b/source/blender/blenlib/BLI_map.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_MAP_H__ -#define __BLI_MAP_H__ +#ifndef __BLI_MAP_HH__ +#define __BLI_MAP_HH__ /** \file * \ingroup bli @@ -26,9 +26,9 @@ * lookups. Keys and values are stored in groups of four to avoid wasting memory due to padding. */ -#include "BLI_array_ref.h" -#include "BLI_hash_cxx.h" -#include "BLI_open_addressing.h" +#include "BLI_array_ref.hh" +#include "BLI_hash.hh" +#include "BLI_open_addressing.hh" namespace BLI { @@ -53,7 +53,11 @@ namespace BLI { // clang-format on -template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> class Map { +template<typename KeyT, + typename ValueT, + uint32_t InlineBufferCapacity = 4, + typename Allocator = GuardedAllocator> +class Map { private: static constexpr uint OFFSET_MASK = 3; static constexpr uint OFFSET_SHIFT = 2; @@ -65,8 +69,8 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> static constexpr uint8_t IS_DUMMY = 2; uint8_t m_status[4]; - char m_keys[4 * sizeof(KeyT)]; - char m_values[4 * sizeof(ValueT)]; + AlignedBuffer<4 * sizeof(KeyT), alignof(KeyT)> m_keys_buffer; + AlignedBuffer<4 * sizeof(ValueT), alignof(ValueT)> m_values_buffer; public: static constexpr uint slots_per_item = 4; @@ -134,20 +138,18 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> KeyT *key(uint offset) const { - return (KeyT *)(m_keys + offset * sizeof(KeyT)); + return (KeyT *)m_keys_buffer.ptr() + offset; } ValueT *value(uint offset) const { - return (ValueT *)(m_values + offset * sizeof(ValueT)); + return (ValueT *)m_values_buffer.ptr() + offset; } template<typename ForwardKeyT, typename ForwardValueT> void store(uint offset, ForwardKeyT &&key, ForwardValueT &&value) { - BLI_assert(m_status[offset] != IS_SET); - m_status[offset] = IS_SET; - new (this->key(offset)) KeyT(std::forward<ForwardKeyT>(key)); + this->store_without_value(offset, std::forward<ForwardKeyT>(key)); new (this->value(offset)) ValueT(std::forward<ForwardValueT>(value)); } @@ -167,7 +169,7 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> } }; - using ArrayType = OpenAddressingArray<Item, 1, Allocator>; + using ArrayType = OpenAddressingArray<Item, InlineBufferCapacity, Allocator>; ArrayType m_array; public: @@ -351,6 +353,12 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> ITER_SLOTS_END(offset); } + ValueT *lookup_ptr(const KeyT &key) + { + const Map *const_this = this; + return const_cast<ValueT *>(const_this->lookup_ptr(key)); + } + /** * Lookup the value that corresponds to the key. * Asserts when the key does not exist. @@ -362,12 +370,6 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> return *ptr; } - ValueT *lookup_ptr(const KeyT &key) - { - const Map *const_this = this; - return const_cast<ValueT *>(const_this->lookup_ptr(key)); - } - ValueT &lookup(const KeyT &key) { const Map *const_this = this; @@ -406,6 +408,19 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> } /** + * Return the value that corresponds to the given key. + * If it does not exist yet, insert a new default constructed value and return that. + */ + ValueT &lookup_or_add_default(const KeyT &key) + { + return this->lookup_or_add(key, []() { return ValueT(); }); + } + ValueT &lookup_or_add_default(const KeyT &&key) + { + return this->lookup_or_add(std::move(key), []() { return ValueT(); }); + } + + /** * Get the number of elements in the map. */ uint32_t size() const @@ -413,6 +428,17 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> return m_array.slots_set(); } + /** + * Returns true if there are no elements in the map. + */ + bool is_empty() const + { + return this->size() == 0; + } + + /** + * Calls the given function for each key-value-pair. + */ template<typename FuncT> void foreach_item(const FuncT &func) const { for (const Item &item : m_array) { @@ -733,4 +759,4 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> } // namespace BLI -#endif /* __BLI_MAP_H__ */ +#endif /* __BLI_MAP_HH__ */ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index ae9617d2f16..3d91a9e98cf 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -92,6 +92,10 @@ static const int NAN_INT = 0x7FC00000; # pragma GCC diagnostic ignored "-Wredundant-decls" #endif +#ifdef __cplusplus +extern "C" { +#endif + /******************************* Float ******************************/ MINLINE float pow2f(float x); @@ -281,4 +285,8 @@ double double_round(double x, int ndigits); # define BLI_ASSERT_UNIT_M3(m) (void)(m) #endif +#ifdef __cplusplus +} +#endif + #endif /* __BLI_MATH_BASE_H__ */ diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index 71e2d2d9e2c..842fce22f91 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -22,12 +22,12 @@ * \ingroup bli */ +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math_inline.h" - /* Search the value from LSB to MSB for a set bit. Returns index of this bit. */ MINLINE int bitscan_forward_i(int a); MINLINE unsigned int bitscan_forward_uint(unsigned int a); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 97d0eb1ddda..f247e09a83b 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -27,12 +27,12 @@ * \ingroup bli */ +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math_inline.h" - /* YCbCr */ #define BLI_YCC_ITU_BT601 0 #define BLI_YCC_ITU_BT709 1 diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h index 47bafff3a49..60ada1e4509 100644 --- a/source/blender/blenlib/BLI_math_color_blend.h +++ b/source/blender/blenlib/BLI_math_color_blend.h @@ -27,12 +27,12 @@ * \ingroup bli */ +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math_inline.h" - /******************** Blending Modes ********************** * - byte function assume straight alpha * - float functions assume premultiplied alpha diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 2049f368578..563bcad5d14 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -27,10 +27,6 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_compiler_attrs.h" #include "BLI_math_inline.h" @@ -39,6 +35,10 @@ extern "C" { # pragma GCC diagnostic ignored "-Wredundant-decls" #endif +#ifdef __cplusplus +extern "C" { +#endif + /********************************** Polygons *********************************/ float normal_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]); diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 1221ecfb7b1..2d11797bc34 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -26,13 +26,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_sys_types.h" - /********************************* Init **************************************/ void zero_m2(float R[2][2]); diff --git a/source/blender/blenlib/BLI_math_solvers.h b/source/blender/blenlib/BLI_math_solvers.h index 4bd1a46bb78..193bbdd4e8c 100644 --- a/source/blender/blenlib/BLI_math_solvers.h +++ b/source/blender/blenlib/BLI_math_solvers.h @@ -24,13 +24,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_math_inline.h" - #ifdef BLI_MATH_GCC_WARN_PRAGMA # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wredundant-decls" diff --git a/source/blender/blenlib/BLI_math_statistics.h b/source/blender/blenlib/BLI_math_statistics.h index b2cc6568abb..a9f9ae39506 100644 --- a/source/blender/blenlib/BLI_math_statistics.h +++ b/source/blender/blenlib/BLI_math_statistics.h @@ -24,13 +24,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_math_inline.h" - #ifdef BLI_MATH_GCC_WARN_PRAGMA # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wredundant-decls" diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 6cfa2d2ced6..af28e826e84 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -27,14 +27,14 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_compiler_attrs.h" #include "BLI_math_inline.h" #include "BLI_utildefines.h" +#ifdef __cplusplus +extern "C" { +#endif + /************************************* Init ***********************************/ #ifdef BLI_MATH_GCC_WARN_PRAGMA @@ -62,6 +62,11 @@ MINLINE void swap_v4_v4(float a[4], float b[4]); MINLINE void copy_v2_v2_uchar(unsigned char r[2], const unsigned char a[2]); MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3]); MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4]); + +MINLINE void copy_v2_uchar(unsigned char r[2], const unsigned char a); +MINLINE void copy_v3_uchar(unsigned char r[3], const unsigned char a); +MINLINE void copy_v4_uchar(unsigned char r[4], const unsigned char a); + /* char */ MINLINE void copy_v2_v2_char(char r[2], const char a[2]); MINLINE void copy_v3_v3_char(char r[3], const char a[3]); diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index 5440bdfef60..e0aff82e874 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -24,12 +24,12 @@ #ifndef __BLI_MEMARENA_H__ #define __BLI_MEMARENA_H__ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - /* A reasonable standard buffer size, big * enough to not cause much internal fragmentation, * small enough not to waste resources diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h index 8bd8642a4e8..8f66ee3b9cb 100644 --- a/source/blender/blenlib/BLI_memblock.h +++ b/source/blender/blenlib/BLI_memblock.h @@ -24,12 +24,12 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - #define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */ struct BLI_memblock; diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h index fb4a79a491b..4aa9cdb6b6c 100644 --- a/source/blender/blenlib/BLI_memiter.h +++ b/source/blender/blenlib/BLI_memiter.h @@ -21,14 +21,14 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_compiler_attrs.h" #include "BLI_compiler_compat.h" #include "BLI_sys_types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* 512kb, good default for small elems. */ #define BLI_MEMITER_DEFAULT_SIZE (1 << 19) diff --git a/source/blender/blenlib/BLI_memory_utils_cxx.h b/source/blender/blenlib/BLI_memory_utils.hh index 6534138315d..d9acf08a43f 100644 --- a/source/blender/blenlib/BLI_memory_utils_cxx.h +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_MEMORY_UTILS_CXX_H__ -#define __BLI_MEMORY_UTILS_CXX_H__ +#ifndef __BLI_MEMORY_UTILS_HH__ +#define __BLI_MEMORY_UTILS_HH__ /** \file * \ingroup bli @@ -120,4 +120,4 @@ template<uint Size, uint Alignment> class alignas(Alignment) AlignedBuffer { } // namespace BLI -#endif /* __BLI_MEMORY_UTILS_CXX_H__ */ +#endif /* __BLI_MEMORY_UTILS_HH__ */ diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 6491180c2fd..3749f9e1b76 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -24,13 +24,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - struct BLI_mempool; struct BLI_mempool_chunk; diff --git a/source/blender/blenlib/BLI_open_addressing.h b/source/blender/blenlib/BLI_open_addressing.hh index 6a0acd418eb..3bd932350d0 100644 --- a/source/blender/blenlib/BLI_open_addressing.h +++ b/source/blender/blenlib/BLI_open_addressing.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_OPEN_ADDRESSING_H__ -#define __BLI_OPEN_ADDRESSING_H__ +#ifndef __BLI_OPEN_ADDRESSING_HH__ +#define __BLI_OPEN_ADDRESSING_HH__ /** \file * \ingroup bli @@ -33,28 +33,88 @@ #include <cmath> -#include "BLI_allocator.h" +#include "BLI_allocator.hh" +#include "BLI_array.hh" #include "BLI_math_base.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" namespace BLI { -template<typename Item, uint32_t ItemsInSmallStorage = 1, typename Allocator = GuardedAllocator> +/** \name Constexpr utility functions. + * \{ */ + +inline constexpr int is_power_of_2_i_constexpr(int n) +{ + return (n & (n - 1)) == 0; +} + +inline constexpr uint32_t log2_floor_u_constexpr(uint32_t x) +{ + return x <= 1 ? 0 : 1 + log2_floor_u_constexpr(x >> 1); +} + +inline constexpr uint32_t log2_ceil_u_constexpr(uint32_t x) +{ + return (is_power_of_2_i_constexpr((int)x)) ? log2_floor_u_constexpr(x) : + log2_floor_u_constexpr(x) + 1; +} + +template<typename IntT> inline constexpr IntT ceil_division(IntT x, IntT y) +{ + BLI_STATIC_ASSERT(!std::is_signed<IntT>::value, ""); + return x / y + ((x % y) != 0); +} + +template<typename IntT> inline constexpr IntT floor_division(IntT x, IntT y) +{ + BLI_STATIC_ASSERT(!std::is_signed<IntT>::value, ""); + return x / y; +} + +inline constexpr uint8_t compute_item_exponent(uint32_t min_usable_slots, + uint32_t slots_per_item, + uint32_t max_load_factor_numerator, + uint32_t max_load_factor_denominator) +{ + // uint64_t min_total_slots = ceil_division((uint64_t)min_usable_slots * + // (uint64_t)max_load_factor_denominator, + // (uint64_t)max_load_factor_numerator); + // uint32_t min_total_items = (uint32_t)ceil_division(min_total_slots, (uint64_t)slots_per_item); + // uint8_t item_exponent = (uint8_t)log2_ceil_u_constexpr(min_total_items); + // return item_exponent; + + return (uint8_t)log2_ceil_u_constexpr((uint32_t)ceil_division( + ceil_division((uint64_t)min_usable_slots * (uint64_t)max_load_factor_denominator, + (uint64_t)max_load_factor_numerator), + (uint64_t)slots_per_item)); +} + +/** \} */ + +template<typename Item, + uint32_t MinUsableSlotsInSmallStorage = 1, + typename Allocator = GuardedAllocator> class OpenAddressingArray { private: - static constexpr uint32_t slots_per_item = Item::slots_per_item; - static constexpr float max_load_factor = 0.5f; + static constexpr uint32_t s_max_load_factor_numerator = 1; + static constexpr uint32_t s_max_load_factor_denominator = 2; + static constexpr uint32_t s_slots_per_item = Item::slots_per_item; + + static constexpr uint8_t s_small_storage_item_exponent = compute_item_exponent( + MinUsableSlotsInSmallStorage, + s_slots_per_item, + s_max_load_factor_numerator, + s_max_load_factor_denominator); + static constexpr uint32_t s_items_in_small_storage = 1u << s_small_storage_item_exponent; /* Invariants: * 2^m_item_exponent = m_item_amount - * m_item_amount * slots_per_item = m_slots_total + * m_item_amount * s_slots_per_item = m_slots_total * m_slot_mask = m_slots_total - 1 * m_slots_set_or_dummy < m_slots_total */ - /* Array containing the actual hash table. Might be a pointer to the inlined storage. */ - Item *m_items; /* Number of items in the hash table. Must be a power of two. */ uint32_t m_item_amount; /* Exponent of the current item amount. */ @@ -69,65 +129,28 @@ class OpenAddressingArray { uint32_t m_slots_usable; /* Can be used to map a hash value into the range of valid slot indices. */ uint32_t m_slot_mask; - Allocator m_allocator; - AlignedBuffer<sizeof(Item) * ItemsInSmallStorage, alignof(Item)> m_local_storage; + + Array<Item, s_items_in_small_storage, Allocator> m_items; public: - explicit OpenAddressingArray(uint8_t item_exponent = 0) + explicit OpenAddressingArray(uint8_t item_exponent = s_small_storage_item_exponent) { - m_slots_total = ((uint32_t)1 << item_exponent) * slots_per_item; + m_item_exponent = item_exponent; + m_item_amount = 1u << item_exponent; + m_slots_total = m_item_amount * s_slots_per_item; + m_slot_mask = m_slots_total - 1; m_slots_set_or_dummy = 0; m_slots_dummy = 0; - m_slots_usable = (uint32_t)((float)m_slots_total * max_load_factor); - m_slot_mask = m_slots_total - 1; - m_item_amount = m_slots_total / slots_per_item; - m_item_exponent = item_exponent; + m_slots_usable = (uint32_t)floor_division((uint64_t)m_slots_total * + (uint64_t)s_max_load_factor_numerator, + (uint64_t)s_max_load_factor_denominator); - if (m_item_amount <= ItemsInSmallStorage) { - m_items = this->small_storage(); - } - else { - m_items = (Item *)m_allocator.allocate_aligned( - (uint32_t)sizeof(Item) * m_item_amount, std::alignment_of<Item>::value, __func__); - } - - for (uint32_t i = 0; i < m_item_amount; i++) { - new (m_items + i) Item(); - } + m_items = Array<Item, s_items_in_small_storage, Allocator>(m_item_amount); } - ~OpenAddressingArray() - { - if (m_items != nullptr) { - for (uint32_t i = 0; i < m_item_amount; i++) { - m_items[i].~Item(); - } - if (!this->is_in_small_storage()) { - m_allocator.deallocate((void *)m_items); - } - } - } - - OpenAddressingArray(const OpenAddressingArray &other) - { - m_slots_total = other.m_slots_total; - m_slots_set_or_dummy = other.m_slots_set_or_dummy; - m_slots_dummy = other.m_slots_dummy; - m_slots_usable = other.m_slots_usable; - m_slot_mask = other.m_slot_mask; - m_item_amount = other.m_item_amount; - m_item_exponent = other.m_item_exponent; - - if (m_item_amount <= ItemsInSmallStorage) { - m_items = this->small_storage(); - } - else { - m_items = (Item *)m_allocator.allocate_aligned( - sizeof(Item) * m_item_amount, std::alignment_of<Item>::value, __func__); - } + ~OpenAddressingArray() = default; - uninitialized_copy_n(other.m_items, m_item_amount, m_items); - } + OpenAddressingArray(const OpenAddressingArray &other) = default; OpenAddressingArray(OpenAddressingArray &&other) noexcept { @@ -138,15 +161,8 @@ class OpenAddressingArray { m_slot_mask = other.m_slot_mask; m_item_amount = other.m_item_amount; m_item_exponent = other.m_item_exponent; - if (other.is_in_small_storage()) { - m_items = this->small_storage(); - uninitialized_relocate_n(other.m_items, m_item_amount, m_items); - } - else { - m_items = other.m_items; - } + m_items = std::move(other.m_items); - other.m_items = nullptr; other.~OpenAddressingArray(); new (&other) OpenAddressingArray(); } @@ -171,13 +187,19 @@ class OpenAddressingArray { return *this; } + Allocator &allocator() + { + return m_items.allocator(); + } + /* Prepare a new array that can hold a minimum of min_usable_slots elements. All entries are * empty. */ OpenAddressingArray init_reserved(uint32_t min_usable_slots) const { - float min_total_slots = (float)min_usable_slots / max_load_factor; - uint32_t min_total_items = (uint32_t)std::ceil(min_total_slots / (float)slots_per_item); - uint8_t item_exponent = (uint8_t)log2_ceil_u(min_total_items); + uint8_t item_exponent = compute_item_exponent(min_usable_slots, + s_slots_per_item, + s_max_load_factor_numerator, + s_max_load_factor_denominator); OpenAddressingArray grown(item_exponent); grown.m_slots_set_or_dummy = this->slots_set(); return grown; @@ -270,36 +292,25 @@ class OpenAddressingArray { Item *begin() { - return m_items; + return m_items.begin(); } Item *end() { - return m_items + m_item_amount; + return m_items.end(); } const Item *begin() const { - return m_items; + return m_items.begin(); } const Item *end() const { - return m_items + m_item_amount; - } - - private: - Item *small_storage() const - { - return reinterpret_cast<Item *>((char *)m_local_storage.ptr()); - } - - bool is_in_small_storage() const - { - return m_items == this->small_storage(); + return m_items.end(); } }; } // namespace BLI -#endif /* __BLI_OPEN_ADDRESSING_H__ */ +#endif /* __BLI_OPEN_ADDRESSING_HH__ */ diff --git a/source/blender/blenlib/BLI_optional.h b/source/blender/blenlib/BLI_optional.hh index 267c858e0f2..eac11293781 100644 --- a/source/blender/blenlib/BLI_optional.h +++ b/source/blender/blenlib/BLI_optional.hh @@ -20,10 +20,10 @@ * Simple version of std::optional, which is only available since C++17. */ -#ifndef __BLI_OPTIONAL_H__ -#define __BLI_OPTIONAL_H__ +#ifndef __BLI_OPTIONAL_HH__ +#define __BLI_OPTIONAL_HH__ -#include "BLI_memory_utils_cxx.h" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" #include <algorithm> @@ -196,4 +196,4 @@ template<typename T> class Optional { } /* namespace BLI */ -#endif /* __BLI_OPTIONAL_H__ */ +#endif /* __BLI_OPTIONAL_HH__ */ diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 9a6a14547d2..30823773d6c 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -23,13 +23,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1); void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); const char *BLI_getenv(const char *env) ATTR_NONNULL(1); diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 39d3a679eb3..376ea9d88de 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -36,7 +36,7 @@ typedef struct ScanFillContext { ListBase fillfacebase; /* increment this value before adding each curve to skip having to calculate - * 'poly_nr' for edges and verts (which can take approx half scanfill time) */ + * 'poly_nr' for edges and verts (which can take approx half scan-fill time) */ unsigned short poly_nr; /* private */ @@ -46,9 +46,9 @@ typedef struct ScanFillContext { #define BLI_SCANFILL_ARENA_SIZE MEM_SIZE_OPTIMAL(1 << 14) /** - * \note this is USHRT_MAX so incrementing will set to zero + * \note this is USHRT_MAX so incrementing will set to zero * which happens if callers choose to increment #ScanFillContext.poly_nr before adding each curve. - * Nowhere else in scanfill do we make use of intentional overflow like this. + * Nowhere else in scan-fill do we make use of intentional overflow like this. */ #define SF_POLY_UNSET ((unsigned short)-1) @@ -64,7 +64,7 @@ typedef struct ScanFillVert { float co[3]; /** 2D projection of vertex location */ float xy[2]; - /** index, caller can use how it likes to match the scanfill result with own data */ + /** index, caller can use how it likes to match the scan-fill result with own data */ unsigned int keyindex; unsigned short poly_nr; /** number of edges using this vertex */ diff --git a/source/blender/blenlib/BLI_set.h b/source/blender/blenlib/BLI_set.hh index dc101add1a7..dc9df5d116a 100644 --- a/source/blender/blenlib/BLI_set.h +++ b/source/blender/blenlib/BLI_set.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_SET_H__ -#define __BLI_SET_H__ +#ifndef __BLI_SET_HH__ +#define __BLI_SET_HH__ /** \file * \ingroup bli @@ -23,9 +23,9 @@ * This file provides a set implementation that uses open addressing with probing. */ -#include "BLI_hash_cxx.h" -#include "BLI_open_addressing.h" -#include "BLI_vector.h" +#include "BLI_hash.hh" +#include "BLI_open_addressing.hh" +#include "BLI_vector.hh" namespace BLI { @@ -50,7 +50,8 @@ namespace BLI { // clang-format on -template<typename T, typename Allocator = GuardedAllocator> class Set { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Set { private: static constexpr uint OFFSET_MASK = 3; static constexpr uint OFFSET_SHIFT = 2; @@ -62,7 +63,7 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { static constexpr uint8_t IS_DUMMY = 2; uint8_t m_status[4]; - char m_values[4 * sizeof(T)]; + AlignedBuffer<4 * sizeof(T), alignof(T)> m_buffer; public: static constexpr uint slots_per_item = 4; @@ -114,7 +115,7 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { T *value(uint offset) const { - return (T *)(m_values + offset * sizeof(T)); + return (T *)m_buffer.ptr() + offset; } template<typename ForwardT> void store(uint offset, ForwardT &&value) @@ -153,8 +154,8 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { } }; - using ArrayType = OpenAddressingArray<Item, 1, Allocator>; - ArrayType m_array = OpenAddressingArray<Item>(); + using ArrayType = OpenAddressingArray<Item, InlineBufferCapacity, Allocator>; + ArrayType m_array; public: Set() = default; @@ -202,6 +203,7 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { /** * Add a new value to the set if it does not exist yet. + * Returns true of the value has been newly added. */ bool add(const T &value) { @@ -266,19 +268,26 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { ITER_SLOTS_END(offset); } - Vector<T> to_small_vector() const + /** + * Get the amount of values stored in the set. + */ + uint32_t size() const { - Vector<T> vector; - vector.reserve(this->size()); - for (const T &value : *this) { - vector.append(value); - } - return vector; + return m_array.slots_set(); } - uint32_t size() const + /** + * Return true if this set contains no elements. + */ + bool is_empty() const { - return m_array.slots_set(); + return this->size() == 0; + } + + void clear() + { + this->~Set(); + new (this) Set(); } /** @@ -480,4 +489,4 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { } // namespace BLI -#endif /* __BLI_SET_H__ */ +#endif /* __BLI_SET_HH__ */ diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h index 9d122fdf798..9fc25e378a3 100644 --- a/source/blender/blenlib/BLI_stack.h +++ b/source/blender/blenlib/BLI_stack.h @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/blenlib/BLI_stack_cxx.h b/source/blender/blenlib/BLI_stack.hh index a26318a3dcb..7f1f9f9cc10 100644 --- a/source/blender/blenlib/BLI_stack_cxx.h +++ b/source/blender/blenlib/BLI_stack.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_STACK_CXX_H__ -#define __BLI_STACK_CXX_H__ +#ifndef __BLI_STACK_HH__ +#define __BLI_STACK_HH__ /** \file * \ingroup bli @@ -23,13 +23,14 @@ * Basic stack implementation with support for small object optimization. */ -#include "BLI_vector.h" +#include "BLI_vector.hh" namespace BLI { -template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Stack { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Stack { private: - Vector<T, N, Allocator> m_elements; + Vector<T, InlineBufferCapacity, Allocator> m_elements; public: Stack() = default; @@ -147,4 +148,4 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class St } /* namespace BLI */ -#endif /* __BLI_STACK_CXX_H__ */ +#endif /* __BLI_STACK_HH__ */ diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 6d3f38c7a52..00e4e3485d1 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -27,13 +27,13 @@ #include <inttypes.h> #include <stdarg.h> +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - char *BLI_strdupn(const char *str, const size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_string_map.h b/source/blender/blenlib/BLI_string_map.hh index f304b140bcc..caa7e16d1f3 100644 --- a/source/blender/blenlib/BLI_string_map.h +++ b/source/blender/blenlib/BLI_string_map.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_STRING_MAP_H__ -#define __BLI_STRING_MAP_H__ +#ifndef __BLI_STRING_MAP_HH__ +#define __BLI_STRING_MAP_HH__ /** \file * \ingroup bli @@ -27,10 +27,10 @@ * make it more efficient later on. Also, even if we will never implement this optimization, having * a special map with string keys can be quite handy. */ -#include "BLI_map.h" -#include "BLI_optional.h" -#include "BLI_string_ref.h" -#include "BLI_vector.h" +#include "BLI_map.hh" +#include "BLI_optional.hh" +#include "BLI_string_ref.hh" +#include "BLI_vector.hh" namespace BLI { @@ -156,10 +156,15 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { template<typename ForwardT> void store(uint offset, uint32_t hash, uint32_t index, ForwardT &&value) { + this->store_without_value(offset, hash, index); + new (this->value(offset)) T(std::forward<ForwardT>(value)); + } + + void store_without_value(uint offset, uint32_t hash, uint32_t index) + { BLI_assert(!this->is_set(offset)); m_hashes[offset] = hash; m_indices[offset] = index; - new (this->value(offset)) T(std::forward<ForwardT>(value)); } }; @@ -195,15 +200,51 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { */ void add(StringRef key, const T &value) { - if (!this->contains(key)) { - this->add_new(key, value); - } + this->add__impl(key, value); } void add(StringRef key, T &&value) { - if (!this->contains(key)) { - this->add_new(key, std::move(value)); + this->add__impl(key, std::move(value)); + } + + /** + * First, checks if the key exists in the map. + * If it does exist, call the modify function with a pointer to the corresponding value. + * If it does not exist, call the create function with a pointer to where the value should be + * created. + * + * Returns whatever is returned from one of the callback functions. Both callbacks have to return + * the same type. + * + * CreateValueF: Takes a pointer to where the value should be created. + * ModifyValueF: Takes a pointer to the value that should be modified. + */ + template<typename CreateValueF, typename ModifyValueF> + auto add_or_modify(StringRef key, + const CreateValueF &create_value, + const ModifyValueF &modify_value) -> decltype(create_value(nullptr)) + { + using CreateReturnT = decltype(create_value(nullptr)); + using ModifyReturnT = decltype(modify_value(nullptr)); + BLI_STATIC_ASSERT((std::is_same<CreateReturnT, ModifyReturnT>::value), + "Both callbacks should return the same type."); + + this->ensure_can_add(); + uint32_t hash = this->compute_string_hash(key); + ITER_SLOTS_BEGIN (hash, m_array, , item, offset) { + if (item.is_empty(offset)) { + m_array.update__empty_to_set(); + uint32_t index = this->save_key_in_array(key); + item.store_without_value(offset, hash, index); + T *value_ptr = item.value(offset); + return create_value(value_ptr); + } + else if (item.has_hash(offset, hash) && item.has_exact_key(offset, key, m_chars)) { + T *value_ptr = item.value(offset); + return modify_value(value_ptr); + } } + ITER_SLOTS_END(offset); } /** @@ -301,6 +342,27 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { } /** + * Return the value that corresponds to the given key. + * If it does not exist yet, create and insert it first. + */ + template<typename CreateValueF> T &lookup_or_add(StringRef key, const CreateValueF &create_value) + { + return *this->add_or_modify( + key, + [&](T *value) { return new (value) T(create_value()); }, + [](T *value) { return value; }); + } + + /** + * Return the value that corresponds to the given key. + * If it does not exist yet, insert a new default constructed value and return that. + */ + T &lookup_or_add_default(StringRef key) + { + return this->lookup_or_add(key, []() { return T(); }); + } + + /** * Do a linear search over all items to find a key for a value. */ StringRefNull find_key_for_value(const T &value) const @@ -435,6 +497,24 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { ITER_SLOTS_END(offset); } + template<typename ForwardT> bool add__impl(StringRef key, ForwardT &&value) + { + this->ensure_can_add(); + uint32_t hash = this->compute_string_hash(key); + ITER_SLOTS_BEGIN (hash, m_array, , item, offset) { + if (item.is_empty(offset)) { + uint32_t index = this->save_key_in_array(key); + item.store(offset, hash, index, std::forward<ForwardT>(value)); + m_array.update__empty_to_set(); + return true; + } + else if (item.has_hash(offset, hash) && item.has_exact_key(offset, key, m_chars)) { + return false; + } + } + ITER_SLOTS_END(offset); + } + template<typename ForwardT> void add_new__impl(StringRef key, ForwardT &&value) { BLI_assert(!this->contains(key)); @@ -457,4 +537,4 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { } // namespace BLI -#endif /* __BLI_STRING_MAP_H__ */ +#endif /* __BLI_STRING_MAP_HH__ */ diff --git a/source/blender/blenlib/BLI_string_ref.h b/source/blender/blenlib/BLI_string_ref.hh index 2389542bcea..eacc501375a 100644 --- a/source/blender/blenlib/BLI_string_ref.h +++ b/source/blender/blenlib/BLI_string_ref.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_STRING_REF_H__ -#define __BLI_STRING_REF_H__ +#ifndef __BLI_STRING_REF_HH__ +#define __BLI_STRING_REF_HH__ /** \file * \ingroup bli @@ -32,7 +32,7 @@ #include <sstream> #include <string> -#include "BLI_array_ref.h" +#include "BLI_array_ref.hh" #include "BLI_utildefines.h" namespace BLI { @@ -94,12 +94,28 @@ class StringRefBase { return m_data + m_size; } - void copy_to__with_null(char *dst) const + void unsafe_copy(char *dst) const { memcpy(dst, m_data, m_size); dst[m_size] = '\0'; } + void copy(char *dst, uint dst_size) const + { + if (m_size < dst_size) { + this->unsafe_copy(dst); + } + else { + BLI_assert(false); + dst[0] = '\0'; + } + } + + template<uint N> void copy(char (&dst)[N]) + { + this->copy(dst, N); + } + /** * Returns true when the string begins with the given prefix. Otherwise false. */ @@ -252,4 +268,4 @@ inline StringRef StringRefBase::substr(uint start, uint size) const } // namespace BLI -#endif /* __BLI_STRING_REF_H__ */ +#endif /* __BLI_STRING_REF_HH__ */ diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 8d986d45a17..78e7113b6ef 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -21,13 +21,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_sys_types.h" - char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL(); size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) diff --git a/source/blender/blenlib/BLI_string_utils.h b/source/blender/blenlib/BLI_string_utils.h index 7b0dd13e0c7..857b22540e9 100644 --- a/source/blender/blenlib/BLI_string_utils.h +++ b/source/blender/blenlib/BLI_string_utils.h @@ -26,13 +26,13 @@ #include <stdarg.h> +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - struct ListBase; typedef bool (*UniquenameCheckCallback)(void *arg, const char *name); diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h index b9e799aa2a9..ef15ce111b6 100644 --- a/source/blender/blenlib/BLI_sys_types.h +++ b/source/blender/blenlib/BLI_sys_types.h @@ -73,7 +73,7 @@ typedef uint64_t u_int64_t; #include <stddef.h> /* size_t define */ #ifndef __cplusplus -# if defined(__APPLE__) +# if defined(__APPLE__) || defined(__NetBSD__) /* The <uchar.h> standard header is missing on macOS. */ typedef unsigned int char32_t; # else diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h index 8c0c9ad99bf..50f8adc20f6 100644 --- a/source/blender/blenlib/BLI_system.h +++ b/source/blender/blenlib/BLI_system.h @@ -53,6 +53,10 @@ int BLI_system_memory_max_in_megabytes_int(void); /* getpid */ #ifdef WIN32 # define BLI_SYSTEM_PID_H <process.h> + +/* void* since we really do not want to drag Windows.h in to get the proper typedef. */ +void BLI_windows_handle_exception(void *exception); + #else # define BLI_SYSTEM_PID_H <unistd.h> #endif diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index 898e4be5f92..64dfdc2ad25 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -25,13 +25,13 @@ struct ListBase; * \ingroup bli */ +#include "BLI_threads.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_threads.h" -#include "BLI_utildefines.h" - struct BLI_mempool; /* Task Scheduler @@ -43,16 +43,13 @@ struct BLI_mempool; * must be called from the main threads. All other scheduler and pool functions * are thread-safe. */ -typedef struct TaskScheduler TaskScheduler; - -TaskScheduler *BLI_task_scheduler_create(int num_threads); -void BLI_task_scheduler_free(TaskScheduler *scheduler); - -int BLI_task_scheduler_num_threads(TaskScheduler *scheduler); +void BLI_task_scheduler_init(void); +void BLI_task_scheduler_exit(void); +int BLI_task_scheduler_num_threads(void); /* Task Pool * - * Pool of tasks that will be executed by the central TaskScheduler. For each + * Pool of tasks that will be executed by the central task scheduler. For each * pool, we can wait for all tasks to be done, or cancel them before they are * done. * @@ -70,16 +67,30 @@ typedef enum TaskPriority { } TaskPriority; typedef struct TaskPool TaskPool; -typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata, int threadid); -typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata, int threadid); - -TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPriority priority); -TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority); -TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority); +typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata); +typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata); + +/* Regular task pool that immediately starts executing tasks as soon as they + * are pushed, either on the current or another thread. */ +TaskPool *BLI_task_pool_create(void *userdata, TaskPriority priority); + +/* Background: always run tasks in a background thread, never immediately + * execute them. For running background jobs. */ +TaskPool *BLI_task_pool_create_background(void *userdata, TaskPriority priority); + +/* Background Serial: run tasks one after the other in the background, + * without parallelization between the tasks. */ +TaskPool *BLI_task_pool_create_background_serial(void *userdata, TaskPriority priority); + +/* Suspended: don't execute tasks until work_and_wait is called. This is slower + * as threads can't immediately start working. But it can be used if the data + * structures the threads operate on are not fully initialized until all tasks + * are created. */ +TaskPool *BLI_task_pool_create_suspended(void *userdata, TaskPriority priority); + +/* No threads: immediately executes tasks on the same thread. For debugging. */ +TaskPool *BLI_task_pool_create_no_threads(void *userdata); + void BLI_task_pool_free(TaskPool *pool); void BLI_task_pool_push(TaskPool *pool, @@ -87,17 +98,9 @@ void BLI_task_pool_push(TaskPool *pool, void *taskdata, bool free_taskdata, TaskFreeFunction freedata); -void BLI_task_pool_push_from_thread(TaskPool *pool, - TaskRunFunction run, - void *taskdata, - bool free_taskdata, - TaskFreeFunction freedata, - int thread_id); /* work and wait until all tasks are done */ void BLI_task_pool_work_and_wait(TaskPool *pool); -/* work and wait until all tasks are done, then reset to the initial suspended state */ -void BLI_task_pool_work_wait_and_reset(TaskPool *pool); /* cancel all tasks, keep worker threads running */ void BLI_task_pool_cancel(TaskPool *pool); @@ -105,53 +108,29 @@ void BLI_task_pool_cancel(TaskPool *pool); bool BLI_task_pool_canceled(TaskPool *pool); /* optional userdata pointer to pass along to run function */ -void *BLI_task_pool_userdata(TaskPool *pool); +void *BLI_task_pool_user_data(TaskPool *pool); /* optional mutex to use from run function */ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool); -/* Thread ID of thread that created the task pool. */ -int BLI_task_pool_creator_thread_id(TaskPool *pool); - -/* Delayed push, use that to reduce thread overhead by accumulating - * all new tasks into local queue first and pushing it to scheduler - * from within a single mutex lock. - */ -void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id); -void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id); - /* Parallel for routines */ -typedef enum eTaskSchedulingMode { - /* Task scheduler will divide overall work into equal chunks, scheduling - * even chunks to all worker threads. - * Least run time benefit, ideal for cases when each task requires equal - * amount of compute power. - */ - TASK_SCHEDULING_STATIC, - /* Task scheduler will schedule small amount of work to each worker thread. - * Has more run time overhead, but deals much better with cases when each - * part of the work requires totally different amount of compute power. - */ - TASK_SCHEDULING_DYNAMIC, -} eTaskSchedulingMode; - /* Per-thread specific data passed to the callback. */ typedef struct TaskParallelTLS { - /* Identifier of the thread who this data belongs to. */ - int thread_id; /* Copy of user-specifier chunk, which is copied from original chunk to all * worker threads. This is similar to OpenMP's firstprivate. */ void *userdata_chunk; } TaskParallelTLS; -typedef void (*TaskParallelFinalizeFunc)(void *__restrict userdata, - void *__restrict userdata_chunk); - typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict tls); +typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata, + void *__restrict chunk_join, + void *__restrict chunk); + +typedef void (*TaskParallelFreeFunc)(const void *__restrict userdata, void *__restrict chunk); typedef struct TaskParallelSettings { /* Whether caller allows to do threading of the particular range. @@ -161,8 +140,6 @@ typedef struct TaskParallelSettings { * is higher than a chunk size. As in, threading will always be performed. */ bool use_threading; - /* Scheduling mode to use for this parallel range invocation. */ - eTaskSchedulingMode scheduling_mode; /* Each instance of looping chunks will get a copy of this data * (similar to OpenMP's firstprivate). */ @@ -171,7 +148,13 @@ typedef struct TaskParallelSettings { /* Function called from calling thread once whole range have been * processed. */ - TaskParallelFinalizeFunc func_finalize; + /* 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 + * can be run on any thread. */ + TaskParallelReduceFunc func_reduce; + /* Function called to free data created by TaskParallelRangeFunc. */ + TaskParallelFreeFunc func_free; /* Minimum allowed number of range iterators to be handled by a single * thread. This allows to achieve following: * - Reduce amount of threading overhead. @@ -191,19 +174,7 @@ void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, - TaskParallelSettings *settings); - -typedef struct TaskParallelRangePool TaskParallelRangePool; -struct TaskParallelRangePool *BLI_task_parallel_range_pool_init( - const struct TaskParallelSettings *settings); -void BLI_task_parallel_range_pool_push(struct TaskParallelRangePool *range_pool, - const int start, - const int stop, - void *userdata, - TaskParallelRangeFunc func, - const struct TaskParallelSettings *settings); -void BLI_task_parallel_range_pool_work_and_wait(struct TaskParallelRangePool *range_pool); -void BLI_task_parallel_range_pool_free(struct TaskParallelRangePool *range_pool); + const TaskParallelSettings *settings); /* This data is shared between all tasks, its access needs thread lock or similar protection. */ @@ -258,11 +229,14 @@ BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *setti { memset(settings, 0, sizeof(*settings)); settings->use_threading = true; - settings->scheduling_mode = TASK_SCHEDULING_STATIC; /* Use default heuristic to define actual chunk size. */ settings->min_iter_per_thread = 0; } +/* Don't use this, store any thread specific data in tls->userdata_chunk instead. + * Only here for code to be removed. */ +int BLI_task_parallel_thread_id(const TaskParallelTLS *tls); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index c2127c1ec3a..c199417017b 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -23,9 +23,6 @@ /** \file * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif #include <pthread.h> @@ -35,6 +32,10 @@ extern "C" { # include <libkern/OSAtomic.h> #endif +#ifdef __cplusplus +extern "C" { +#endif + /* for tables, button in UI, etc */ #define BLENDER_MAX_THREADS 1024 @@ -47,8 +48,6 @@ struct TaskScheduler; void BLI_threadapi_init(void); void BLI_threadapi_exit(void); -struct TaskScheduler *BLI_task_scheduler_get(void); - void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot); int BLI_available_threads(struct ListBase *threadbase); int BLI_threadpool_available_thread_index(struct ListBase *threadbase); diff --git a/source/blender/blenlib/BLI_timeit.hh b/source/blender/blenlib/BLI_timeit.hh new file mode 100644 index 00000000000..e9f121ec654 --- /dev/null +++ b/source/blender/blenlib/BLI_timeit.hh @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef __BLI_TIMEIT_HH__ +#define __BLI_TIMEIT_HH__ + +#include <chrono> +#include <iostream> +#include <string> + +#include "BLI_sys_types.h" + +namespace BLI { +namespace Timeit { + +using Clock = std::chrono::steady_clock; +using TimePoint = Clock::time_point; +using Nanoseconds = std::chrono::nanoseconds; + +void print_duration(Nanoseconds duration); + +class ScopedTimer { + private: + std::string m_name; + TimePoint m_start; + + public: + ScopedTimer(std::string name) : m_name(std::move(name)) + { + m_start = Clock::now(); + } + + ~ScopedTimer() + { + TimePoint end = Clock::now(); + Nanoseconds duration = end - m_start; + + std::cout << "Timer '" << m_name << "' took "; + print_duration(duration); + std::cout << '\n'; + } +}; + +} // namespace Timeit +} // namespace BLI + +#define SCOPED_TIMER(name) BLI::Timeit::ScopedTimer scoped_timer(name) + +#endif /* __BLI_TIMEIT_HH__ */ diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index fb5dbf66819..1f28f7e80c5 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -24,10 +24,6 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - /* avoid many includes for now */ #include "BLI_compiler_compat.h" #include "BLI_sys_types.h" @@ -39,6 +35,10 @@ extern "C" { /* include after _VA_NARGS macro */ #include "BLI_compiler_typecheck.h" +#ifdef __cplusplus +extern "C" { +#endif + /* -------------------------------------------------------------------- */ /** \name Min/Max Macros * \{ */ diff --git a/source/blender/blenlib/BLI_utility_mixins.h b/source/blender/blenlib/BLI_utility_mixins.hh index ce7a4ce094a..441575f9111 100644 --- a/source/blender/blenlib/BLI_utility_mixins.h +++ b/source/blender/blenlib/BLI_utility_mixins.hh @@ -18,8 +18,8 @@ * \ingroup bli */ -#ifndef __BLI_UTILITY_MIXINS_H__ -#define __BLI_UTILITY_MIXINS_H__ +#ifndef __BLI_UTILITY_MIXINS_HH__ +#define __BLI_UTILITY_MIXINS_HH__ namespace BLI { @@ -49,4 +49,4 @@ class NonMovable { } // namespace BLI -#endif /* __BLI_UTILITY_MIXINS_H__ */ +#endif /* __BLI_UTILITY_MIXINS_HH__ */ diff --git a/source/blender/blenlib/BLI_vector.h b/source/blender/blenlib/BLI_vector.hh index 6a708759d0e..49cf41c2005 100644 --- a/source/blender/blenlib/BLI_vector.h +++ b/source/blender/blenlib/BLI_vector.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_VECTOR_H__ -#define __BLI_VECTOR_H__ +#ifndef __BLI_VECTOR_HH__ +#define __BLI_VECTOR_HH__ /** \file * \ingroup bli @@ -31,25 +31,26 @@ #include <iostream> #include <memory> -#include "BLI_allocator.h" -#include "BLI_array_ref.h" -#include "BLI_index_range.h" -#include "BLI_listbase_wrapper.h" +#include "BLI_allocator.hh" +#include "BLI_array_ref.hh" +#include "BLI_index_range.hh" +#include "BLI_listbase_wrapper.hh" #include "BLI_math_base.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" namespace BLI { -template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Vector { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Vector { private: T *m_begin; T *m_end; T *m_capacity_end; Allocator m_allocator; - AlignedBuffer<sizeof(T) * N, alignof(T)> m_small_buffer; + AlignedBuffer<(uint)sizeof(T) * InlineBufferCapacity, (uint)alignof(T)> m_small_buffer; #ifndef NDEBUG /* Storing size in debug builds, because it makes debugging much easier sometimes. */ @@ -70,7 +71,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve { m_begin = this->small_buffer(); m_end = m_begin; - m_capacity_end = m_begin + N; + m_capacity_end = m_begin + InlineBufferCapacity; UPDATE_VECTOR_SIZE(this); } @@ -130,20 +131,17 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve /** * Create a vector from a ListBase. */ - Vector(ListBase &values, bool intrusive_next_and_prev_pointers) : Vector() + Vector(ListBase &values) : Vector() { - BLI_assert(intrusive_next_and_prev_pointers); - if (intrusive_next_and_prev_pointers) { - for (T value : IntrusiveListBaseWrapper<typename std::remove_pointer<T>::type>(values)) { - this->append(value); - } + for (T value : ListBaseWrapper<typename std::remove_pointer<T>::type>(values)) { + this->append(value); } } /** * Create a copy of another vector. * The other vector will not be changed. - * If the other vector has less than N elements, no allocation will be made. + * If the other vector has less than InlineBufferCapacity elements, no allocation will be made. */ Vector(const Vector &other) : m_allocator(other.m_allocator) { @@ -167,11 +165,11 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve uint size = other.size(); if (other.is_small()) { - if (size <= N) { + if (size <= InlineBufferCapacity) { /* Copy between inline buffers. */ m_begin = this->small_buffer(); m_end = m_begin + size; - m_capacity_end = m_begin + N; + m_capacity_end = m_begin + InlineBufferCapacity; uninitialized_relocate_n(other.m_begin, size, m_begin); } else { @@ -286,7 +284,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve m_begin = this->small_buffer(); m_end = m_begin; - m_capacity_end = m_begin + N; + m_capacity_end = m_begin + InlineBufferCapacity; UPDATE_VECTOR_SIZE(this); } @@ -429,7 +427,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve /** * Returns true when the vector contains no elements, otherwise false. */ - bool empty() const + bool is_empty() const { return m_begin == m_end; } @@ -440,7 +438,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve */ void remove_last() { - BLI_assert(!this->empty()); + BLI_assert(!this->is_empty()); m_end--; destruct(m_end); UPDATE_VECTOR_SIZE(this); @@ -451,7 +449,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve */ T pop_last() { - BLI_assert(!this->empty()); + BLI_assert(!this->is_empty()); m_end--; T value = std::move(*m_end); destruct(m_end); @@ -581,7 +579,8 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve std::cout << "Small Vector at " << (void *)this << ":" << std::endl; std::cout << " Elements: " << this->size() << std::endl; std::cout << " Capacity: " << (m_capacity_end - m_begin) << std::endl; - std::cout << " Small Elements: " << N << " Size on Stack: " << sizeof(*this) << std::endl; + std::cout << " Small Elements: " << InlineBufferCapacity + << " Size on Stack: " << sizeof(*this) << std::endl; } private: @@ -637,9 +636,9 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve uint size = other.size(); uint capacity = size; - if (size <= N) { + if (size <= InlineBufferCapacity) { m_begin = this->small_buffer(); - capacity = N; + capacity = InlineBufferCapacity; } else { m_begin = (T *)m_allocator.allocate_aligned( @@ -661,8 +660,9 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve * Use when the vector is used in the local scope of a function. It has a larger inline storage by * default to make allocations less likely. */ -template<typename T, uint N = 20> using ScopedVector = Vector<T, N, GuardedAllocator>; +template<typename T, uint InlineBufferCapacity = 20> +using ScopedVector = Vector<T, InlineBufferCapacity, GuardedAllocator>; } /* namespace BLI */ -#endif /* __BLI_VECTOR_H__ */ +#endif /* __BLI_VECTOR_HH__ */ diff --git a/source/blender/blenlib/BLI_vector_set.h b/source/blender/blenlib/BLI_vector_set.hh index 99d955c60d8..9f887513816 100644 --- a/source/blender/blenlib/BLI_vector_set.h +++ b/source/blender/blenlib/BLI_vector_set.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_VECTOR_SET_H__ -#define __BLI_VECTOR_SET_H__ +#ifndef __BLI_VECTOR_SET_HH__ +#define __BLI_VECTOR_SET_HH__ /** \file * \ingroup bli @@ -25,9 +25,9 @@ * no deletes. The expected time to check if a value is in the VectorSet is O(1). */ -#include "BLI_hash_cxx.h" -#include "BLI_open_addressing.h" -#include "BLI_vector.h" +#include "BLI_hash.hh" +#include "BLI_open_addressing.hh" +#include "BLI_vector.hh" namespace BLI { @@ -76,7 +76,7 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { return m_value == IS_DUMMY; } - bool has_value(const T &value, const Vector<T> &elements) const + bool has_value(const T &value, const T *elements) const { return this->is_set() && elements[this->index()] == value; } @@ -112,12 +112,14 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { using ArrayType = OpenAddressingArray<Slot, 4, Allocator>; ArrayType m_array; - Vector<T, 4, Allocator> m_elements; + + /* The capacity of the array should always be at least m_array.slots_usable(). */ + T *m_elements = nullptr; public: VectorSet() { - BLI_assert(m_array.slots_usable() <= m_elements.capacity()); + m_elements = this->allocate_elements_array(m_array.slots_usable()); } VectorSet(ArrayRef<T> values) : VectorSet() @@ -135,6 +137,43 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { this->add_multiple(values); } + VectorSet(const VectorSet &other) : m_array(other.m_array) + { + m_elements = this->allocate_elements_array(m_array.slots_usable()); + copy_n(other.m_elements, m_array.slots_set(), m_elements); + } + + VectorSet(VectorSet &&other) : m_array(std::move(other.m_array)), m_elements(other.m_elements) + { + other.m_elements = other.allocate_elements_array(other.m_array.slots_usable()); + } + + ~VectorSet() + { + destruct_n(m_elements, this->size()); + this->deallocate_elements_array(m_elements); + } + + VectorSet &operator=(const VectorSet &other) + { + if (this == &other) { + return *this; + } + this->~VectorSet(); + new (this) VectorSet(other); + return *this; + } + + VectorSet &operator=(VectorSet &&other) + { + if (this == &other) { + return *this; + } + this->~VectorSet(); + new (this) VectorSet(std::move(other)); + return *this; + } + /** * Allocate memory such that at least min_usable_slots can be added without having to grow again. */ @@ -203,17 +242,17 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { BLI_assert(this->contains(value)); ITER_SLOTS_BEGIN (value, m_array, , slot) { if (slot.has_value(value, m_elements)) { - uint old_index = m_elements.size() - 1; + uint old_index = this->size() - 1; uint new_index = slot.index(); - m_elements.remove_and_reorder(new_index); + if (new_index < old_index) { + m_elements[new_index] = std::move(m_elements[old_index]); + this->update_slot_index(m_elements[new_index], old_index, new_index); + } + + destruct(m_elements + old_index); slot.set_dummy(); m_array.update__set_to_dummy(); - - if (old_index != new_index) { - T &moved_value = m_elements[new_index]; - this->update_slot_index(moved_value, old_index, new_index); - } return; } } @@ -226,11 +265,12 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { T pop() { BLI_assert(this->size() > 0); - T value = m_elements.pop_last(); - uint old_index = m_elements.size(); + uint index_to_pop = this->size() - 1; + T value = std::move(m_elements[index_to_pop]); + destruct(m_elements + index_to_pop); ITER_SLOTS_BEGIN (value, m_array, , slot) { - if (slot.has_index(old_index)) { + if (slot.has_index(index_to_pop)) { slot.set_dummy(); m_array.update__set_to_dummy(); return value; @@ -277,18 +317,24 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { return m_array.slots_set(); } + bool is_empty() const + { + return this->size() == 0; + } + const T *begin() const { - return m_elements.begin(); + return m_elements; } const T *end() const { - return m_elements.end(); + return m_elements + this->size(); } const T &operator[](uint index) const { + BLI_assert(index <= this->size()); return m_elements[index]; } @@ -299,7 +345,7 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { operator ArrayRef<T>() const { - return m_elements; + return ArrayRef<T>(m_elements, this->size()); } void print_stats() const @@ -326,9 +372,9 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { template<typename ForwardT> void add_new_in_slot(Slot &slot, ForwardT &&value) { - uint index = m_elements.size(); + uint index = this->size(); slot.set_index(index); - m_elements.append_unchecked(std::forward<ForwardT>(value)); + new (m_elements + index) T(std::forward<ForwardT>(value)); m_array.update__empty_to_set(); } @@ -341,14 +387,20 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { BLI_NOINLINE void grow(uint min_usable_slots) { + uint size = this->size(); + ArrayType new_array = m_array.init_reserved(min_usable_slots); + T *new_elements = this->allocate_elements_array(new_array.slots_usable()); - for (uint i = 0; i < m_elements.size(); i++) { + for (uint i : IndexRange(size)) { this->add_after_grow(i, new_array); } + uninitialized_relocate_n(m_elements, size, new_elements); + this->deallocate_elements_array(m_elements); + m_array = std::move(new_array); - m_elements.reserve(m_array.slots_usable()); + m_elements = new_elements; } void add_after_grow(uint index, ArrayType &new_array) @@ -365,15 +417,15 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { float compute_average_collisions() const { - if (m_elements.size() == 0) { + if (this->size() == 0) { return 0.0f; } uint collisions_sum = 0; - for (const T &value : m_elements) { + for (const T &value : this->as_ref()) { collisions_sum += this->count_collisions(value); } - return (float)collisions_sum / (float)m_elements.size(); + return (float)collisions_sum / (float)this->size(); } uint count_collisions(const T &value) const @@ -415,6 +467,16 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { } ITER_SLOTS_END; } + + T *allocate_elements_array(uint size) + { + return (T *)m_array.allocator().allocate_aligned((uint)sizeof(T) * size, alignof(T), __func__); + } + + void deallocate_elements_array(T *elements) + { + m_array.allocator().deallocate(elements); + } }; #undef ITER_SLOTS_BEGIN @@ -422,4 +484,4 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { } // namespace BLI -#endif /* __BLI_VECTOR_SET_H__ */ +#endif /* __BLI_VECTOR_SET_HH__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index bdfe3dd4747..ab9b3e19ab9 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -64,6 +64,7 @@ set(SRC intern/buffer.c intern/convexhull_2d.c intern/delaunay_2d.c + intern/dot_export.cc intern/dynlib.c intern/easing.c intern/edgehash.c @@ -118,11 +119,14 @@ set(SRC intern/string_utf8.c intern/string_utils.c intern/system.c - intern/task_pool.cc intern/task_iterator.c + intern/task_pool.cc + intern/task_range.cc + intern/task_scheduler.cc intern/threads.c intern/time.c intern/timecode.c + intern/timeit.cc intern/uvproject.c intern/voronoi_2d.c intern/voxel.c @@ -136,11 +140,11 @@ set(SRC BLI_alloca.h - BLI_allocator.h + BLI_allocator.hh BLI_args.h BLI_array.h - BLI_array_cxx.h - BLI_array_ref.h + BLI_array.hh + BLI_array_ref.hh BLI_array_store.h BLI_array_store_utils.h BLI_array_utils.h @@ -151,6 +155,7 @@ set(SRC BLI_blenlib.h BLI_boxpack_2d.h BLI_buffer.h + BLI_color.hh BLI_compiler_attrs.h BLI_compiler_compat.h BLI_compiler_typecheck.h @@ -159,6 +164,8 @@ set(SRC BLI_delaunay_2d.h BLI_dial_2d.h BLI_dlrbTree.h + BLI_dot_export.hh + BLI_dot_export_attribute_enums.hh BLI_dynlib.h BLI_dynstr.h BLI_easing.h @@ -168,17 +175,20 @@ set(SRC BLI_expr_pylike_eval.h BLI_fileops.h BLI_fileops_types.h + BLI_float2.hh + BLI_float3.hh + BLI_float4x4.hh BLI_fnmatch.h BLI_ghash.h BLI_gsqueue.h BLI_hash.h - BLI_hash_cxx.h + BLI_hash.hh BLI_hash_md5.h BLI_hash_mm2a.h BLI_hash_mm3.h BLI_heap.h BLI_heap_simple.h - BLI_index_range.h + BLI_index_range.hh BLI_iterator.h BLI_jitter_2d.h BLI_kdopbvh.h @@ -190,8 +200,8 @@ set(SRC BLI_linklist_lockfree.h BLI_linklist_stack.h BLI_listbase.h - BLI_listbase_wrapper.h - BLI_map.h + BLI_listbase_wrapper.hh + BLI_map.hh BLI_math.h BLI_math_base.h BLI_math_bits.h @@ -209,11 +219,11 @@ set(SRC BLI_memblock.h BLI_memiter.h BLI_memory_utils.h - BLI_memory_utils_cxx.h + BLI_memory_utils.hh BLI_mempool.h BLI_noise.h - BLI_open_addressing.h - BLI_optional.h + BLI_open_addressing.hh + BLI_optional.hh BLI_path_util.h BLI_polyfill_2d.h BLI_polyfill_2d_beautify.h @@ -221,17 +231,17 @@ set(SRC BLI_rand.h BLI_rect.h BLI_scanfill.h - BLI_set.h + BLI_set.hh BLI_smallhash.h BLI_sort.h BLI_sort_utils.h BLI_stack.h - BLI_stack_cxx.h + BLI_stack.hh BLI_strict_flags.h BLI_string.h BLI_string_cursor_utf8.h - BLI_string_map.h - BLI_string_ref.h + BLI_string_map.hh + BLI_string_ref.hh BLI_string_utf8.h BLI_string_utils.h BLI_sys_types.h @@ -239,15 +249,16 @@ set(SRC BLI_task.h BLI_threads.h BLI_timecode.h + BLI_timeit.hh BLI_timer.h BLI_utildefines.h BLI_utildefines_iter.h BLI_utildefines_stack.h BLI_utildefines_variadic.h - BLI_utility_mixins.h + BLI_utility_mixins.hh BLI_uvproject.h - BLI_vector.h - BLI_vector_set.h + BLI_vector.hh + BLI_vector_set.hh BLI_vfontdata.h BLI_voronoi_2d.h BLI_voxel.h @@ -269,6 +280,18 @@ if(WITH_MEM_VALGRIND) add_definitions(-DWITH_MEM_VALGRIND) endif() +if(WITH_TBB) + add_definitions(-DWITH_TBB) + + list(APPEND INC_SYS + ${TBB_INCLUDE_DIRS} + ) + + list(APPEND LIB + ${TBB_LIBRARIES} + ) +endif() + if(WIN32) list(APPEND INC ../../../intern/utfconv @@ -276,6 +299,9 @@ if(WIN32) list(APPEND LIB bf_intern_utfconv ) + list(APPEND SRC + intern/system_win32.c + ) endif() diff --git a/source/blender/blenlib/intern/BLI_index_range.cc b/source/blender/blenlib/intern/BLI_index_range.cc index 90eb4e4a89c..fefb6e6598e 100644 --- a/source/blender/blenlib/intern/BLI_index_range.cc +++ b/source/blender/blenlib/intern/BLI_index_range.cc @@ -17,10 +17,10 @@ #include <atomic> #include <mutex> -#include "BLI_array_cxx.h" -#include "BLI_array_ref.h" -#include "BLI_index_range.h" -#include "BLI_vector.h" +#include "BLI_array.hh" +#include "BLI_array_ref.hh" +#include "BLI_index_range.hh" +#include "BLI_vector.hh" namespace BLI { diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c index 836292e0c88..4e0cd3a78dc 100644 --- a/source/blender/blenlib/intern/delaunay_2d.c +++ b/source/blender/blenlib/intern/delaunay_2d.c @@ -1264,6 +1264,7 @@ static void fill_crossdata_for_intersect(CDT_state *cdt, se_vcva = t->next->next; BLI_assert(se_vcva->vert == vc && se_vcva->next->vert == va); BLI_assert(se_vcvb->vert == vc && se_vcvb->next->vert == vb); + UNUSED_VARS_NDEBUG(vc); isect = isect_seg_seg_v2_lambda_mu_db(va->co, vb->co, curco, v2->co, &lambda, &mu); #ifdef DEBUG_CDT if (dbg_level > 0) { diff --git a/source/blender/blenlib/intern/dot_export.cc b/source/blender/blenlib/intern/dot_export.cc new file mode 100644 index 00000000000..96de4056fc5 --- /dev/null +++ b/source/blender/blenlib/intern/dot_export.cc @@ -0,0 +1,305 @@ +/* + * 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 <iomanip> + +#include "BLI_dot_export.hh" + +namespace BLI { +namespace DotExport { + +/* Graph Building + ************************************************/ + +Node &Graph::new_node(StringRef label) +{ + Node *node = new Node(*this); + m_nodes.append(std::unique_ptr<Node>(node)); + m_top_level_nodes.add_new(node); + node->set_attribute("label", label); + return *node; +} + +Cluster &Graph::new_cluster(StringRef label) +{ + Cluster *cluster = new Cluster(*this); + m_clusters.append(std::unique_ptr<Cluster>(cluster)); + m_top_level_clusters.add_new(cluster); + cluster->set_attribute("label", label); + return *cluster; +} + +UndirectedEdge &UndirectedGraph::new_edge(NodePort a, NodePort b) +{ + UndirectedEdge *edge = new UndirectedEdge(a, b); + m_edges.append(std::unique_ptr<UndirectedEdge>(edge)); + return *edge; +} + +DirectedEdge &DirectedGraph::new_edge(NodePort from, NodePort to) +{ + DirectedEdge *edge = new DirectedEdge(from, to); + m_edges.append(std::unique_ptr<DirectedEdge>(edge)); + return *edge; +} + +void Cluster::set_parent_cluster(Cluster *new_parent) +{ + if (m_parent == new_parent) { + return; + } + else if (m_parent == nullptr) { + m_graph.m_top_level_clusters.remove(this); + new_parent->m_children.add_new(this); + } + else if (new_parent == nullptr) { + m_parent->m_children.remove(this); + m_graph.m_top_level_clusters.add_new(this); + } + else { + m_parent->m_children.remove(this); + new_parent->m_children.add_new(this); + } + m_parent = new_parent; +} + +void Node::set_parent_cluster(Cluster *cluster) +{ + if (m_cluster == cluster) { + return; + } + else if (m_cluster == nullptr) { + m_graph.m_top_level_nodes.remove(this); + cluster->m_nodes.add_new(this); + } + else if (cluster == nullptr) { + m_cluster->m_nodes.remove(this); + m_graph.m_top_level_nodes.add_new(this); + } + else { + m_cluster->m_nodes.remove(this); + cluster->m_nodes.add_new(this); + } + m_cluster = cluster; +} + +/* Utility methods + **********************************************/ + +void Graph::set_random_cluster_bgcolors() +{ + for (Cluster *cluster : m_top_level_clusters) { + cluster->set_random_cluster_bgcolors(); + } +} + +void Cluster::set_random_cluster_bgcolors() +{ + float hue = rand() / (float)RAND_MAX; + float staturation = 0.3f; + float value = 0.8f; + this->set_attribute("bgcolor", color_attr_from_hsv(hue, staturation, value)); + + for (Cluster *cluster : m_children) { + cluster->set_random_cluster_bgcolors(); + } +} + +/* Dot Generation + **********************************************/ + +std::string DirectedGraph::to_dot_string() const +{ + std::stringstream ss; + ss << "digraph {\n"; + this->export__declare_nodes_and_clusters(ss); + ss << "\n"; + + for (const std::unique_ptr<DirectedEdge> &edge : m_edges) { + edge->export__as_edge_statement(ss); + ss << "\n"; + } + + ss << "}\n"; + return ss.str(); +} + +std::string UndirectedGraph::to_dot_string() const +{ + std::stringstream ss; + ss << "graph {\n"; + this->export__declare_nodes_and_clusters(ss); + ss << "\n"; + + for (const std::unique_ptr<UndirectedEdge> &edge : m_edges) { + edge->export__as_edge_statement(ss); + ss << "\n"; + } + + ss << "}\n"; + return ss.str(); +} + +void Graph::export__declare_nodes_and_clusters(std::stringstream &ss) const +{ + ss << "graph "; + m_attributes.export__as_bracket_list(ss); + ss << "\n\n"; + + for (Node *node : m_top_level_nodes) { + node->export__as_declaration(ss); + } + + for (Cluster *cluster : m_top_level_clusters) { + cluster->export__declare_nodes_and_clusters(ss); + } +} + +void Cluster::export__declare_nodes_and_clusters(std::stringstream &ss) const +{ + ss << "subgraph cluster_" << (uintptr_t)this << " {\n"; + + ss << "graph "; + m_attributes.export__as_bracket_list(ss); + ss << "\n\n"; + + for (Node *node : m_nodes) { + node->export__as_declaration(ss); + } + + for (Cluster *cluster : m_children) { + cluster->export__declare_nodes_and_clusters(ss); + } + + ss << "}\n"; +} + +void DirectedEdge::export__as_edge_statement(std::stringstream &ss) const +{ + m_a.to_dot_string(ss); + ss << " -> "; + m_b.to_dot_string(ss); + ss << " "; + m_attributes.export__as_bracket_list(ss); +} + +void UndirectedEdge::export__as_edge_statement(std::stringstream &ss) const +{ + m_a.to_dot_string(ss); + ss << " -- "; + m_b.to_dot_string(ss); + ss << " "; + m_attributes.export__as_bracket_list(ss); +} + +void AttributeList::export__as_bracket_list(std::stringstream &ss) const +{ + ss << "["; + m_attributes.foreach_item([&](StringRef key, StringRef value) { + if (StringRef(value).startswith("<")) { + /* Don't draw the quotes, this is an html-like value. */ + ss << key << "=" << value << ", "; + } + else { + ss << key << "=\"" << value << "\", "; + } + }); + ss << "]"; +} + +void Node::export__as_id(std::stringstream &ss) const +{ + ss << '"' << (uintptr_t)this << '"'; +} + +void Node::export__as_declaration(std::stringstream &ss) const +{ + this->export__as_id(ss); + ss << " "; + m_attributes.export__as_bracket_list(ss); + ss << "\n"; +} + +void NodePort::to_dot_string(std::stringstream &ss) const +{ + m_node->export__as_id(ss); + if (m_port_name.has_value()) { + ss << ":" << m_port_name.value(); + } +} + +std::string color_attr_from_hsv(float h, float s, float v) +{ + std::stringstream ss; + ss << std::setprecision(4) << h << ' ' << s << ' ' << v; + return ss.str(); +} + +NodeWithSocketsRef::NodeWithSocketsRef(Node &node, + StringRef name, + ArrayRef<std::string> input_names, + ArrayRef<std::string> output_names) + : m_node(&node) +{ + std::stringstream ss; + + ss << "<<table border=\"0\" cellspacing=\"3\">"; + + /* Header */ + ss << "<tr><td colspan=\"3\" align=\"center\"><b>"; + ss << ((name.size() == 0) ? "No Name" : name); + ss << "</b></td></tr>"; + + /* Sockets */ + uint socket_max_amount = std::max(input_names.size(), output_names.size()); + for (uint i = 0; i < socket_max_amount; i++) { + ss << "<tr>"; + if (i < input_names.size()) { + StringRef name = input_names[i]; + if (name.size() == 0) { + name = "No Name"; + } + ss << "<td align=\"left\" port=\"in" << i << "\">"; + ss << name; + ss << "</td>"; + } + else { + ss << "<td></td>"; + } + ss << "<td></td>"; + if (i < output_names.size()) { + StringRef name = output_names[i]; + if (name.size() == 0) { + name = "No Name"; + } + ss << "<td align=\"right\" port=\"out" << i << "\">"; + ss << name; + ss << "</td>"; + } + else { + ss << "<td></td>"; + } + ss << "</tr>"; + } + + ss << "</table>>"; + + m_node->set_attribute("label", ss.str()); + m_node->set_shape(Attr_shape::Rectangle); +} + +} // namespace DotExport +} // namespace BLI diff --git a/source/blender/blenlib/intern/lasso_2d.c b/source/blender/blenlib/intern/lasso_2d.c index f1e9b1e655f..a01adf4fa6a 100644 --- a/source/blender/blenlib/intern/lasso_2d.c +++ b/source/blender/blenlib/intern/lasso_2d.c @@ -28,47 +28,47 @@ #include "BLI_lasso_2d.h" /* own include */ -void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const unsigned int moves) +void BLI_lasso_boundbox(rcti *rect, const int mcoords[][2], const unsigned int mcoords_len) { unsigned int a; - rect->xmin = rect->xmax = mcords[0][0]; - rect->ymin = rect->ymax = mcords[0][1]; + rect->xmin = rect->xmax = mcoords[0][0]; + rect->ymin = rect->ymax = mcoords[0][1]; - for (a = 1; a < moves; a++) { - if (mcords[a][0] < rect->xmin) { - rect->xmin = mcords[a][0]; + for (a = 1; a < mcoords_len; a++) { + if (mcoords[a][0] < rect->xmin) { + rect->xmin = mcoords[a][0]; } - else if (mcords[a][0] > rect->xmax) { - rect->xmax = mcords[a][0]; + else if (mcoords[a][0] > rect->xmax) { + rect->xmax = mcoords[a][0]; } - if (mcords[a][1] < rect->ymin) { - rect->ymin = mcords[a][1]; + if (mcoords[a][1] < rect->ymin) { + rect->ymin = mcoords[a][1]; } - else if (mcords[a][1] > rect->ymax) { - rect->ymax = mcords[a][1]; + else if (mcoords[a][1] > rect->ymax) { + rect->ymax = mcoords[a][1]; } } } -bool BLI_lasso_is_point_inside(const int mcords[][2], - const unsigned int moves, +bool BLI_lasso_is_point_inside(const int mcoords[][2], + const unsigned int mcoords_len, const int sx, const int sy, const int error_value) { - if (sx == error_value || moves == 0) { + if (sx == error_value || mcoords_len == 0) { return false; } else { int pt[2] = {sx, sy}; - return isect_point_poly_v2_int(pt, mcords, moves, true); + return isect_point_poly_v2_int(pt, mcoords, mcoords_len, true); } } /* edge version for lasso select. we assume boundbox check was done */ -bool BLI_lasso_is_edge_inside(const int mcords[][2], - const unsigned int moves, +bool BLI_lasso_is_edge_inside(const int mcoords[][2], + const unsigned int mcoords_len, int x0, int y0, int x1, @@ -76,27 +76,27 @@ bool BLI_lasso_is_edge_inside(const int mcords[][2], const int error_value) { - if (x0 == error_value || x1 == error_value || moves == 0) { + if (x0 == error_value || x1 == error_value || mcoords_len == 0) { return false; } const int v1[2] = {x0, y0}, v2[2] = {x1, y1}; /* check points in lasso */ - if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) { + if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v1[0], v1[1], error_value)) { return true; } - if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) { + if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v2[0], v2[1], error_value)) { return true; } /* no points in lasso, so we have to intersect with lasso edge */ - if (isect_seg_seg_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) { + if (isect_seg_seg_v2_int(mcoords[0], mcoords[mcoords_len - 1], v1, v2) > 0) { return true; } - for (unsigned int a = 0; a < moves - 1; a++) { - if (isect_seg_seg_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) { + for (unsigned int a = 0; a < mcoords_len - 1; a++) { + if (isect_seg_seg_v2_int(mcoords[a], mcoords[a + 1], v1, v2) > 0) { return true; } } diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index e0cac508d28..d5105a7cefc 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -38,6 +38,10 @@ #include "BLI_math_base.h" +#ifdef __cplusplus +extern "C" { +#endif + /* copied from BLI_utildefines.h */ #ifdef __GNUC__ # define UNLIKELY(x) __builtin_expect(!!(x), 0) @@ -793,4 +797,8 @@ MINLINE unsigned char unit_ushort_to_uchar(unsigned short val) } \ ((void)0) +#ifdef __cplusplus +} +#endif + #endif /* __MATH_BASE_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c index 235589abdab..cda3d9b66a2 100644 --- a/source/blender/blenlib/intern/math_solvers.c +++ b/source/blender/blenlib/intern/math_solvers.c @@ -55,7 +55,7 @@ bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], } /** - * \brief Compute the SVD (Singular Values Decomposition) of given 3D matrix (m3 = USV*). + * \brief Compute the SVD (Singular Values Decomposition) of given 3D matrix (m3 = USV*). * * \param m3: the matrix to decompose. * \return r_U the computed left singular vector of \a m3 (NULL if not needed). diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index d2c55233653..ca405907bdd 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -123,6 +123,27 @@ MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4]) r[3] = a[3]; } +MINLINE void copy_v2_uchar(unsigned char r[2], const unsigned char a) +{ + r[0] = a; + r[1] = a; +} + +MINLINE void copy_v3_uchar(unsigned char r[3], const unsigned char a) +{ + r[0] = a; + r[1] = a; + r[2] = a; +} + +MINLINE void copy_v4_uchar(unsigned char r[4], const unsigned char a) +{ + r[0] = a; + r[1] = a; + r[2] = a; + r[3] = a; +} + /* char */ MINLINE void copy_v2_v2_char(char r[2], const char a[2]) { diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 229a06948c2..42b5ba28f5a 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -23,6 +23,7 @@ #include <math.h> +#include "BLI_compiler_compat.h" #include "BLI_noise.h" /* local */ @@ -264,17 +265,17 @@ static const float hashvectf[768] = { /* IMPROVED PERLIN NOISE */ /**************************/ -static float lerp(float t, float a, float b) +BLI_INLINE float lerp(float t, float a, float b) { return (a + t * (b - a)); } -static float npfade(float t) +BLI_INLINE float npfade(float t) { return (t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f)); } -static float grad(int hash_val, float x, float y, float z) +BLI_INLINE float grad(int hash_val, float x, float y, float z) { int h = hash_val & 15; /* CONVERT LO 4 BITS OF HASH CODE */ float u = h < 8 ? x : y; /* INTO 12 GRADIENT DIRECTIONS. */ diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index 0a1ff9f8116..3ad1844cfe1 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -141,9 +141,14 @@ void BLI_quadric_mul(Quadric *a, const double scalar) double BLI_quadric_evaluate(const Quadric *q, const double v[3]) { - return ((q->a2 * v[0] * v[0]) + (q->ab * 2 * v[0] * v[1]) + (q->ac * 2 * v[0] * v[2]) + - (q->ad * 2 * v[0]) + (q->b2 * v[1] * v[1]) + (q->bc * 2 * v[1] * v[2]) + - (q->bd * 2 * v[1]) + (q->c2 * v[2] * v[2]) + (q->cd * 2 * v[2]) + (q->d2)); + const double v00 = v[0] * v[0], v01 = v[0] * v[1], v02 = v[0] * v[2]; + const double v11 = v[1] * v[1], v12 = v[1] * v[2]; + const double v22 = v[2] * v[2]; + return ((q->a2 * v00) + (q->ab * 2 * v01) + (q->ac * 2 * v02) + (q->ad * 2 * v[0]) + /* a */ + (q->b2 * v11) + (q->bc * 2 * v12) + (q->bd * 2 * v[1]) + /* b */ + (q->c2 * v22) + (q->cd * 2 * v[2]) + /* c */ + (q->d2) /* d */ + ); } bool BLI_quadric_optimize(const Quadric *q, double v[3], const double epsilon) diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c index e75d944c764..f2e8b352aab 100644 --- a/source/blender/blenlib/intern/stack.c +++ b/source/blender/blenlib/intern/stack.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 7d9ed2598a6..53db49aa59c 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -32,11 +32,8 @@ /* for backtrace and gethostname/GetComputerName */ #if defined(WIN32) # include <intrin.h> -# include <windows.h> -# pragma warning(push) -# pragma warning(disable : 4091) -# include <dbghelp.h> -# pragma warning(pop) + +# include "BLI_winstuff.h" #else # include <execinfo.h> # include <unistd.h> @@ -74,6 +71,8 @@ int BLI_cpu_support_sse2(void) #endif } +/* Windows stackwalk lives in system_win32.c */ +#if !defined(_MSC_VER) /** * Write a backtrace into a file for systems which support it. */ @@ -81,9 +80,9 @@ void BLI_system_backtrace(FILE *fp) { /* ------------- */ /* Linux / Apple */ -#if defined(__linux__) || defined(__APPLE__) +# if defined(__linux__) || defined(__APPLE__) -# define SIZE 100 +# define SIZE 100 void *buffer[SIZE]; int nptrs; char **strings; @@ -98,48 +97,15 @@ void BLI_system_backtrace(FILE *fp) } free(strings); -# undef SIZE - - /* -------- */ - /* Windows */ -#elif defined(_MSC_VER) - -# ifndef NDEBUG -# define MAXSYMBOL 256 -# define SIZE 100 - unsigned short i; - void *stack[SIZE]; - unsigned short nframes; - SYMBOL_INFO *symbolinfo; - HANDLE process; - - process = GetCurrentProcess(); - - SymInitialize(process, NULL, TRUE); - - nframes = CaptureStackBackTrace(0, SIZE, stack, NULL); - symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table"); - symbolinfo->MaxNameLen = MAXSYMBOL - 1; - symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); - - for (i = 0; i < nframes; i++) { - SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo); - - fprintf(fp, "%u: %s - 0x%0llX\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); - } - - MEM_freeN(symbolinfo); -# undef MAXSYMBOL # undef SIZE + # else - fprintf(fp, "Crash backtrace not supported on release builds\n"); -# endif /* NDEBUG */ -#else /* _MSC_VER */ /* ------------------ */ /* non msvc/osx/linux */ (void)fp; -#endif +# endif } +#endif /* end BLI_system_backtrace */ /* NOTE: The code for CPU brand string is adopted from Cycles. */ diff --git a/source/blender/blenlib/intern/system_win32.c b/source/blender/blenlib/intern/system_win32.c new file mode 100644 index 00000000000..d60f54ebe67 --- /dev/null +++ b/source/blender/blenlib/intern/system_win32.c @@ -0,0 +1,410 @@ +/* + * 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 bli + */ +#include <Windows.h> +#include <stdio.h> + +#include <dbghelp.h> +#include <shlwapi.h> +#include <tlhelp32.h> + +#include "BLI_string.h" + +#include "MEM_guardedalloc.h" + +static EXCEPTION_POINTERS *current_exception = NULL; + +static const char *bli_windows_get_exception_description(const DWORD exceptioncode) +{ + switch (exceptioncode) { + case EXCEPTION_ACCESS_VIOLATION: + return "EXCEPTION_ACCESS_VIOLATION"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; + case EXCEPTION_BREAKPOINT: + return "EXCEPTION_BREAKPOINT"; + case EXCEPTION_DATATYPE_MISALIGNMENT: + return "EXCEPTION_DATATYPE_MISALIGNMENT"; + case EXCEPTION_FLT_DENORMAL_OPERAND: + return "EXCEPTION_FLT_DENORMAL_OPERAND"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + return "EXCEPTION_FLT_DIVIDE_BY_ZERO"; + case EXCEPTION_FLT_INEXACT_RESULT: + return "EXCEPTION_FLT_INEXACT_RESULT"; + case EXCEPTION_FLT_INVALID_OPERATION: + return "EXCEPTION_FLT_INVALID_OPERATION"; + case EXCEPTION_FLT_OVERFLOW: + return "EXCEPTION_FLT_OVERFLOW"; + case EXCEPTION_FLT_STACK_CHECK: + return "EXCEPTION_FLT_STACK_CHECK"; + case EXCEPTION_FLT_UNDERFLOW: + return "EXCEPTION_FLT_UNDERFLOW"; + case EXCEPTION_ILLEGAL_INSTRUCTION: + return "EXCEPTION_ILLEGAL_INSTRUCTION"; + case EXCEPTION_IN_PAGE_ERROR: + return "EXCEPTION_IN_PAGE_ERROR"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + return "EXCEPTION_INT_DIVIDE_BY_ZERO"; + case EXCEPTION_INT_OVERFLOW: + return "EXCEPTION_INT_OVERFLOW"; + case EXCEPTION_INVALID_DISPOSITION: + return "EXCEPTION_INVALID_DISPOSITION"; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + return "EXCEPTION_NONCONTINUABLE_EXCEPTION"; + case EXCEPTION_PRIV_INSTRUCTION: + return "EXCEPTION_PRIV_INSTRUCTION"; + case EXCEPTION_SINGLE_STEP: + return "EXCEPTION_SINGLE_STEP"; + case EXCEPTION_STACK_OVERFLOW: + return "EXCEPTION_STACK_OVERFLOW"; + default: + return "UNKNOWN EXCEPTION"; + } +} + +static void bli_windows_get_module_name(LPVOID address, PCHAR buffer, size_t size) +{ + HMODULE mod; + buffer[0] = 0; + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &mod)) { + if (GetModuleFileName(mod, buffer, size)) { + PathStripPath(buffer); + } + } +} + +static void bli_windows_get_module_version(const char *file, char *buffer, size_t buffersize) +{ + buffer[0] = 0; + DWORD verHandle = 0; + UINT size = 0; + LPBYTE lpBuffer = NULL; + DWORD verSize = GetFileVersionInfoSize(file, &verHandle); + if (verSize != 0) { + LPSTR verData = (LPSTR)MEM_callocN(verSize, "crash module version"); + + if (GetFileVersionInfo(file, verHandle, verSize, verData)) { + if (VerQueryValue(verData, "\\", (VOID FAR * FAR *)&lpBuffer, &size)) { + if (size) { + VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer; + /* Magic value from + * https://docs.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo + */ + if (verInfo->dwSignature == 0xfeef04bd) { + BLI_snprintf(buffer, + buffersize, + "%d.%d.%d.%d", + (verInfo->dwFileVersionMS >> 16) & 0xffff, + (verInfo->dwFileVersionMS >> 0) & 0xffff, + (verInfo->dwFileVersionLS >> 16) & 0xffff, + (verInfo->dwFileVersionLS >> 0) & 0xffff); + } + } + } + } + MEM_freeN(verData); + } +} + +static void bli_windows_system_backtrace_exception_record(FILE *fp, PEXCEPTION_RECORD record) +{ + char module[MAX_PATH]; + fprintf(fp, "Exception Record:\n\n"); + fprintf(fp, + "ExceptionCode : %s\n", + bli_windows_get_exception_description(record->ExceptionCode)); + fprintf(fp, "Exception Address : 0x%p\n", record->ExceptionAddress); + bli_windows_get_module_name(record->ExceptionAddress, module, sizeof(module)); + fprintf(fp, "Exception Module : %s\n", module); + fprintf(fp, "Exception Flags : 0x%.8x\n", record->ExceptionFlags); + fprintf(fp, "Exception Parameters : 0x%x\n", record->NumberParameters); + for (DWORD idx = 0; idx < record->NumberParameters; idx++) { + fprintf(fp, "\tParameters[%d] : 0x%p\n", idx, (LPVOID *)record->ExceptionInformation[idx]); + } + if (record->ExceptionRecord) { + fprintf(fp, "Nested "); + bli_windows_system_backtrace_exception_record(fp, record->ExceptionRecord); + } + fprintf(fp, "\n\n"); +} + +static bool BLI_windows_system_backtrace_run_trace(FILE *fp, HANDLE hThread, PCONTEXT context) +{ + const int max_symbol_length = 100; + + bool result = true; + + PSYMBOL_INFO symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + max_symbol_length * sizeof(char), + "crash Symbol table"); + symbolinfo->MaxNameLen = max_symbol_length - 1; + symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); + + STACKFRAME frame = {0}; + frame.AddrPC.Offset = context->Rip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context->Rsp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context->Rsp; + frame.AddrStack.Mode = AddrModeFlat; + + while (true) { + if (StackWalk64(IMAGE_FILE_MACHINE_AMD64, + GetCurrentProcess(), + hThread, + &frame, + context, + NULL, + SymFunctionTableAccess64, + SymGetModuleBase64, + 0)) { + if (frame.AddrPC.Offset) { + char module[MAX_PATH]; + + bli_windows_get_module_name((LPVOID)frame.AddrPC.Offset, module, sizeof(module)); + + if (SymFromAddr(GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), 0, symbolinfo)) { + fprintf(fp, "%-20s:0x%p %s", module, (LPVOID)symbolinfo->Address, symbolinfo->Name); + IMAGEHLP_LINE lineinfo; + lineinfo.SizeOfStruct = sizeof(lineinfo); + DWORD displacement = 0; + if (SymGetLineFromAddr( + GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), &displacement, &lineinfo)) { + fprintf(fp, " %s:%d", lineinfo.FileName, lineinfo.LineNumber); + } + fprintf(fp, "\n"); + } + else { + fprintf(fp, + "%-20s:0x%p %s\n", + module, + (LPVOID)frame.AddrPC.Offset, + "Symbols not available"); + result = false; + break; + } + } + else { + break; + } + } + else { + break; + } + } + MEM_freeN(symbolinfo); + fprintf(fp, "\n\n"); + return result; +} + +static bool bli_windows_system_backtrace_stack_thread(FILE *fp, HANDLE hThread) +{ + CONTEXT context = {0}; + context.ContextFlags = CONTEXT_ALL; + /* GetThreadContext requires the thread to be in a suspended state, which is problematic for the + * currently running thread, RtlCaptureContext is used as an alternative to sidestep this */ + if (hThread != GetCurrentThread()) { + SuspendThread(hThread); + bool success = GetThreadContext(hThread, &context); + ResumeThread(hThread); + if (!success) { + fprintf(fp, "Cannot get thread context : 0x0%.8x\n", GetLastError()); + return false; + } + } + else { + RtlCaptureContext(&context); + } + return BLI_windows_system_backtrace_run_trace(fp, hThread, &context); +} + +static void bli_windows_system_backtrace_modules(FILE *fp) +{ + fprintf(fp, "Loaded Modules :\n"); + HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); + if (hModuleSnap == INVALID_HANDLE_VALUE) + return; + + MODULEENTRY32 me32; + me32.dwSize = sizeof(MODULEENTRY32); + + if (!Module32First(hModuleSnap, &me32)) { + CloseHandle(hModuleSnap); // Must clean up the snapshot object! + fprintf(fp, " Error getting module list.\n"); + return; + } + + do { + if (me32.th32ProcessID == GetCurrentProcessId()) { + char version[MAX_PATH]; + bli_windows_get_module_version(me32.szExePath, version, sizeof(version)); + + IMAGEHLP_MODULE64 m64; + m64.SizeOfStruct = sizeof(m64); + if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)me32.modBaseAddr, &m64)) { + fprintf(fp, + "0x%p %-20s %s %s %s\n", + me32.modBaseAddr, + version, + me32.szModule, + m64.LoadedPdbName, + m64.PdbUnmatched ? "[unmatched]" : ""); + } + else { + fprintf(fp, "0x%p %-20s %s\n", me32.modBaseAddr, version, me32.szModule); + } + } + } while (Module32Next(hModuleSnap, &me32)); +} + +static void bli_windows_system_backtrace_threads(FILE *fp) +{ + fprintf(fp, "Threads:\n"); + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) { + fprintf(fp, "Unable to retrieve threads list.\n"); + return; + } + + te32.dwSize = sizeof(THREADENTRY32); + + if (!Thread32First(hThreadSnap, &te32)) { + CloseHandle(hThreadSnap); + return; + } + do { + if (te32.th32OwnerProcessID == GetCurrentProcessId()) { + if (GetCurrentThreadId() != te32.th32ThreadID) { + fprintf(fp, "Thread : %.8x\n", te32.th32ThreadID); + HANDLE ht = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); + bli_windows_system_backtrace_stack_thread(fp, ht); + CloseHandle(ht); + } + } + } while (Thread32Next(hThreadSnap, &te32)); + CloseHandle(hThreadSnap); +} + +static bool BLI_windows_system_backtrace_stack(FILE *fp) +{ + fprintf(fp, "Stack trace:\n"); + /* If we are handling an exception use the context record from that. */ + if (current_exception && current_exception->ExceptionRecord->ExceptionAddress) { + /* The back trace code will write to the context record, to protect the original record from + * modifications give the backtrace a copy to work on. */ + CONTEXT TempContext = *current_exception->ContextRecord; + return BLI_windows_system_backtrace_run_trace(fp, GetCurrentThread(), &TempContext); + } + else { + /* If there is no current exception or the address is not set, walk the current stack. */ + return bli_windows_system_backtrace_stack_thread(fp, GetCurrentThread()); + } +} + +static bool bli_private_symbols_loaded() +{ + IMAGEHLP_MODULE64 m64; + m64.SizeOfStruct = sizeof(m64); + if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)GetModuleHandle(NULL), &m64)) { + return m64.GlobalSymbols; + } + return false; +} + +static void bli_load_symbols() +{ + /* If this is a developer station and the private pdb is already loaded leave it be. */ + if (bli_private_symbols_loaded()) { + return; + } + + char pdb_file[MAX_PATH] = {0}; + + /* get the currently executing image */ + if (GetModuleFileNameA(NULL, pdb_file, sizeof(pdb_file))) { + /* remove the filename */ + PathRemoveFileSpecA(pdb_file); + /* append blender.pdb */ + PathAppendA(pdb_file, "blender.pdb"); + if (PathFileExistsA(pdb_file)) { + HMODULE mod = GetModuleHandle(NULL); + if (mod) { + WIN32_FILE_ATTRIBUTE_DATA file_data; + if (GetFileAttributesExA(pdb_file, GetFileExInfoStandard, &file_data)) { + /* SymInitialize will try to load symbols on its own, so we first must unload whatever it + * did trying to help */ + SymUnloadModule64(GetCurrentProcess(), (DWORD64)mod); + + DWORD64 module_base = SymLoadModule(GetCurrentProcess(), + NULL, + pdb_file, + NULL, + (DWORD64)mod, + (DWORD)file_data.nFileSizeLow); + if (module_base == 0) { + fprintf(stderr, + "Error loading symbols %s\n\terror:0x%.8x\n\tsize = %d\n\tbase=0x%p\n", + pdb_file, + GetLastError(), + file_data.nFileSizeLow, + (LPVOID)mod); + } + } + } + } + } +} + +void BLI_system_backtrace(FILE *fp) +{ + SymInitialize(GetCurrentProcess(), NULL, TRUE); + bli_load_symbols(); + if (current_exception) { + bli_windows_system_backtrace_exception_record(fp, current_exception->ExceptionRecord); + } + if (BLI_windows_system_backtrace_stack(fp)) { + /* When the blender symbols are missing the stack traces will be unreliable + * so only run if the previous step completed successfully. */ + bli_windows_system_backtrace_threads(fp); + } + bli_windows_system_backtrace_modules(fp); + fputc(0, fp); /* Give our selves a nice zero terminator for later on */ +} + +void BLI_windows_handle_exception(EXCEPTION_POINTERS *exception) +{ + current_exception = exception; + if (current_exception) { + fprintf(stderr, + "Error : %s\n", + bli_windows_get_exception_description(exception->ExceptionRecord->ExceptionCode)); + fflush(stderr); + + LPVOID address = exception->ExceptionRecord->ExceptionAddress; + fprintf(stderr, "Address : 0x%p\n", address); + + CHAR modulename[MAX_PATH]; + bli_windows_get_module_name(address, modulename, sizeof(modulename)); + fprintf(stderr, "Module : %s\n", modulename); + fprintf(stderr, "Thread : %.8x\n", GetCurrentThreadId()); + } + fflush(stderr); +} diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index 4ac012fa578..ee459ac2548 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -17,7 +17,7 @@ /** \file * \ingroup bli * - * A generic task system which can be used for any task based subsystem. + * Parallel tasks over all elements in a container. */ #include <stdlib.h> @@ -34,77 +34,12 @@ #include "atomic_ops.h" -/* Parallel range routines */ - -/** - * - * Main functions: - * - #BLI_task_parallel_range - * - #BLI_task_parallel_listbase (#ListBase - double linked list) - * - * TODO: - * - #BLI_task_parallel_foreach_link (#Link - single linked list) - * - #BLI_task_parallel_foreach_ghash/gset (#GHash/#GSet - hash & set) - * - #BLI_task_parallel_foreach_mempool (#BLI_mempool - iterate over mempools) - */ - /* Allows to avoid using malloc for userdata_chunk in tasks, when small enough. */ #define MALLOCA(_size) ((_size) <= 8192) ? alloca((_size)) : MEM_mallocN((_size), __func__) #define MALLOCA_FREE(_mem, _size) \ if (((_mem) != NULL) && ((_size) > 8192)) \ MEM_freeN((_mem)) -/* Stores all needed data to perform a parallelized iteration, - * with a same operation (callback function). - * It can be chained with other tasks in a single-linked list way. */ -typedef struct TaskParallelRangeState { - struct TaskParallelRangeState *next; - - /* Start and end point of integer value iteration. */ - int start, stop; - - /* User-defined data, shared between all worker threads. */ - void *userdata_shared; - /* User-defined callback function called for each value in [start, stop[ specified range. */ - TaskParallelRangeFunc func; - - /* Each instance of looping chunks will get a copy of this data - * (similar to OpenMP's firstprivate). - */ - void *initial_tls_memory; /* Pointer to actual user-defined 'tls' data. */ - size_t tls_data_size; /* Size of that data. */ - - void *flatten_tls_storage; /* 'tls' copies of initial_tls_memory for each running task. */ - /* Number of 'tls' copies in the array, i.e. number of worker threads. */ - size_t num_elements_in_tls_storage; - - /* Function called from calling thread once whole range have been processed. */ - TaskParallelFinalizeFunc func_finalize; - - /* Current value of the iterator, shared between all threads (atomically updated). */ - int iter_value; - int iter_chunk_num; /* Amount of iterations to process in a single step. */ -} TaskParallelRangeState; - -/* Stores all the parallel tasks for a single pool. */ -typedef struct TaskParallelRangePool { - /* The workers' task pool. */ - TaskPool *pool; - /* The number of worker tasks we need to create. */ - int num_tasks; - /* The total number of iterations in all the added ranges. */ - int num_total_iters; - /* The size (number of items) processed at once by a worker task. */ - int chunk_size; - - /* Linked list of range tasks to process. */ - TaskParallelRangeState *parallel_range_states; - /* Current range task beeing processed, swapped atomically. */ - TaskParallelRangeState *current_state; - /* Scheduling settings common to all tasks. */ - TaskParallelSettings *settings; -} TaskParallelRangePool; - BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settings, const int tot_items, int num_tasks, @@ -149,429 +84,7 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin } BLI_assert(chunk_size > 0); - - if (tot_items > 0) { - switch (settings->scheduling_mode) { - case TASK_SCHEDULING_STATIC: - *r_chunk_size = max_ii(chunk_size, tot_items / num_tasks); - break; - case TASK_SCHEDULING_DYNAMIC: - *r_chunk_size = chunk_size; - break; - } - } - else { - /* If total amount of items is unknown, we can only use dynamic scheduling. */ - *r_chunk_size = chunk_size; - } -} - -BLI_INLINE void task_parallel_range_calc_chunk_size(TaskParallelRangePool *range_pool) -{ - int num_iters = 0; - int min_num_iters = INT_MAX; - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - const int ni = state->stop - state->start; - num_iters += ni; - if (min_num_iters > ni) { - min_num_iters = ni; - } - } - range_pool->num_total_iters = num_iters; - /* Note: Passing min_num_iters here instead of num_iters kind of partially breaks the 'static' - * scheduling, but pooled range iterator is inherently non-static anyway, so adding a small level - * of dynamic scheduling here should be fine. */ - task_parallel_calc_chunk_size( - range_pool->settings, min_num_iters, range_pool->num_tasks, &range_pool->chunk_size); -} - -BLI_INLINE bool parallel_range_next_iter_get(TaskParallelRangePool *__restrict range_pool, - int *__restrict r_iter, - int *__restrict r_count, - TaskParallelRangeState **__restrict r_state) -{ - /* We need an atomic op here as well to fetch the initial state, since some other thread might - * have already updated it. */ - TaskParallelRangeState *current_state = atomic_cas_ptr( - (void **)&range_pool->current_state, NULL, NULL); - - int previter = INT32_MAX; - - while (current_state != NULL && previter >= current_state->stop) { - previter = atomic_fetch_and_add_int32(¤t_state->iter_value, range_pool->chunk_size); - *r_iter = previter; - *r_count = max_ii(0, min_ii(range_pool->chunk_size, current_state->stop - previter)); - - if (previter >= current_state->stop) { - /* At this point the state we got is done, we need to go to the next one. In case some other - * thread already did it, then this does nothing, and we'll just get current valid state - * at start of the next loop. */ - TaskParallelRangeState *current_state_from_atomic_cas = atomic_cas_ptr( - (void **)&range_pool->current_state, current_state, current_state->next); - - if (current_state == current_state_from_atomic_cas) { - /* The atomic CAS operation was successful, we did update range_pool->current_state, so we - * can safely switch to next state. */ - current_state = current_state->next; - } - else { - /* The atomic CAS operation failed, but we still got range_pool->current_state value out of - * it, just use it as our new current state. */ - current_state = current_state_from_atomic_cas; - } - } - } - - *r_state = current_state; - return (current_state != NULL && previter < current_state->stop); -} - -static void parallel_range_func(TaskPool *__restrict pool, void *tls_data_idx, int thread_id) -{ - TaskParallelRangePool *__restrict range_pool = BLI_task_pool_userdata(pool); - TaskParallelTLS tls = { - .thread_id = thread_id, - .userdata_chunk = NULL, - }; - TaskParallelRangeState *state; - int iter, count; - while (parallel_range_next_iter_get(range_pool, &iter, &count, &state)) { - tls.userdata_chunk = (char *)state->flatten_tls_storage + - (((size_t)POINTER_AS_INT(tls_data_idx)) * state->tls_data_size); - for (int i = 0; i < count; i++) { - state->func(state->userdata_shared, iter + i, &tls); - } - } -} - -static void parallel_range_single_thread(TaskParallelRangePool *range_pool) -{ - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - const int start = state->start; - const int stop = state->stop; - void *userdata = state->userdata_shared; - TaskParallelRangeFunc func = state->func; - - void *initial_tls_memory = state->initial_tls_memory; - const size_t tls_data_size = state->tls_data_size; - void *flatten_tls_storage = NULL; - const bool use_tls_data = (tls_data_size != 0) && (initial_tls_memory != NULL); - if (use_tls_data) { - flatten_tls_storage = MALLOCA(tls_data_size); - memcpy(flatten_tls_storage, initial_tls_memory, tls_data_size); - } - TaskParallelTLS tls = { - .thread_id = 0, - .userdata_chunk = flatten_tls_storage, - }; - for (int i = start; i < stop; i++) { - func(userdata, i, &tls); - } - if (state->func_finalize != NULL) { - state->func_finalize(userdata, flatten_tls_storage); - } - MALLOCA_FREE(flatten_tls_storage, tls_data_size); - } -} - -/** - * This function allows to parallelized for loops in a similar way to OpenMP's - * 'parallel for' statement. - * - * See public API doc of ParallelRangeSettings for description of all settings. - */ -void BLI_task_parallel_range(const int start, - const int stop, - void *userdata, - TaskParallelRangeFunc func, - TaskParallelSettings *settings) -{ - if (start == stop) { - return; - } - - BLI_assert(start < stop); - - TaskParallelRangeState state = { - .next = NULL, - .start = start, - .stop = stop, - .userdata_shared = userdata, - .func = func, - .iter_value = start, - .initial_tls_memory = settings->userdata_chunk, - .tls_data_size = settings->userdata_chunk_size, - .func_finalize = settings->func_finalize, - }; - TaskParallelRangePool range_pool = { - .pool = NULL, .parallel_range_states = &state, .current_state = NULL, .settings = settings}; - int i, num_threads, num_tasks; - - void *tls_data = settings->userdata_chunk; - const size_t tls_data_size = settings->userdata_chunk_size; - if (tls_data_size != 0) { - BLI_assert(tls_data != NULL); - } - const bool use_tls_data = (tls_data_size != 0) && (tls_data != NULL); - void *flatten_tls_storage = NULL; - - /* If it's not enough data to be crunched, don't bother with tasks at all, - * do everything from the current thread. - */ - if (!settings->use_threading) { - parallel_range_single_thread(&range_pool); - return; - } - - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - num_threads = BLI_task_scheduler_num_threads(task_scheduler); - - /* 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 iter to be crunched using the queue. - */ - range_pool.num_tasks = num_tasks = num_threads + 2; - - task_parallel_range_calc_chunk_size(&range_pool); - range_pool.num_tasks = num_tasks = min_ii(num_tasks, - max_ii(1, (stop - start) / range_pool.chunk_size)); - - if (num_tasks == 1) { - parallel_range_single_thread(&range_pool); - return; - } - - TaskPool *task_pool = range_pool.pool = BLI_task_pool_create_suspended( - task_scheduler, &range_pool, TASK_PRIORITY_HIGH); - - range_pool.current_state = &state; - - if (use_tls_data) { - state.flatten_tls_storage = flatten_tls_storage = MALLOCA(tls_data_size * (size_t)num_tasks); - state.tls_data_size = tls_data_size; - } - - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); - for (i = 0; i < num_tasks; i++) { - if (use_tls_data) { - void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i); - memcpy(userdata_chunk_local, tls_data, tls_data_size); - } - /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread( - task_pool, parallel_range_func, POINTER_FROM_INT(i), false, NULL, thread_id); - } - - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - - if (use_tls_data) { - if (settings->func_finalize != NULL) { - for (i = 0; i < num_tasks; i++) { - void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i); - settings->func_finalize(userdata, userdata_chunk_local); - } - } - MALLOCA_FREE(flatten_tls_storage, tls_data_size * (size_t)num_tasks); - } -} - -/** - * Initialize a task pool to parallelize several for loops at the same time. - * - * See public API doc of ParallelRangeSettings for description of all settings. - * Note that loop-specific settings (like 'tls' data or finalize function) must be left NULL here. - * Only settings controlling how iteration is parallelized must be defined, as those will affect - * all loops added to that pool. - */ -TaskParallelRangePool *BLI_task_parallel_range_pool_init(const TaskParallelSettings *settings) -{ - TaskParallelRangePool *range_pool = MEM_callocN(sizeof(*range_pool), __func__); - - BLI_assert(settings->userdata_chunk == NULL); - BLI_assert(settings->func_finalize == NULL); - range_pool->settings = MEM_mallocN(sizeof(*range_pool->settings), __func__); - *range_pool->settings = *settings; - - return range_pool; -} - -/** - * Add a loop task to the pool. It does not execute it at all. - * - * See public API doc of ParallelRangeSettings for description of all settings. - * Note that only 'tls'-related data are used here. - */ -void BLI_task_parallel_range_pool_push(TaskParallelRangePool *range_pool, - const int start, - const int stop, - void *userdata, - TaskParallelRangeFunc func, - const TaskParallelSettings *settings) -{ - BLI_assert(range_pool->pool == NULL); - - if (start == stop) { - return; - } - - BLI_assert(start < stop); - if (settings->userdata_chunk_size != 0) { - BLI_assert(settings->userdata_chunk != NULL); - } - - TaskParallelRangeState *state = MEM_callocN(sizeof(*state), __func__); - state->start = start; - state->stop = stop; - state->userdata_shared = userdata; - state->func = func; - state->iter_value = start; - state->initial_tls_memory = settings->userdata_chunk; - state->tls_data_size = settings->userdata_chunk_size; - state->func_finalize = settings->func_finalize; - - state->next = range_pool->parallel_range_states; - range_pool->parallel_range_states = state; -} - -static void parallel_range_func_finalize(TaskPool *__restrict pool, - void *v_state, - int UNUSED(thread_id)) -{ - TaskParallelRangePool *__restrict range_pool = BLI_task_pool_userdata(pool); - TaskParallelRangeState *state = v_state; - - for (int i = 0; i < range_pool->num_tasks; i++) { - void *tls_data = (char *)state->flatten_tls_storage + (state->tls_data_size * (size_t)i); - state->func_finalize(state->userdata_shared, tls_data); - } -} - -/** - * Run all tasks pushed to the range_pool. - * - * Note that the range pool is re-usable (you may push new tasks into it and call this function - * again). - */ -void BLI_task_parallel_range_pool_work_and_wait(TaskParallelRangePool *range_pool) -{ - BLI_assert(range_pool->pool == NULL); - - /* If it's not enough data to be crunched, don't bother with tasks at all, - * do everything from the current thread. - */ - if (!range_pool->settings->use_threading) { - parallel_range_single_thread(range_pool); - return; - } - - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - const int num_threads = BLI_task_scheduler_num_threads(task_scheduler); - - /* 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 iter to be crunched using the queue. - */ - int num_tasks = num_threads + 2; - range_pool->num_tasks = num_tasks; - - task_parallel_range_calc_chunk_size(range_pool); - range_pool->num_tasks = num_tasks = min_ii( - num_tasks, max_ii(1, range_pool->num_total_iters / range_pool->chunk_size)); - - if (num_tasks == 1) { - parallel_range_single_thread(range_pool); - return; - } - - /* We create all 'tls' data here in a single loop. */ - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - void *userdata_chunk = state->initial_tls_memory; - const size_t userdata_chunk_size = state->tls_data_size; - if (userdata_chunk_size == 0) { - BLI_assert(userdata_chunk == NULL); - continue; - } - - void *userdata_chunk_array = NULL; - state->flatten_tls_storage = userdata_chunk_array = MALLOCA(userdata_chunk_size * - (size_t)num_tasks); - for (int i = 0; i < num_tasks; i++) { - void *userdata_chunk_local = (char *)userdata_chunk_array + - (userdata_chunk_size * (size_t)i); - memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); - } - } - - TaskPool *task_pool = range_pool->pool = BLI_task_pool_create_suspended( - task_scheduler, range_pool, TASK_PRIORITY_HIGH); - - range_pool->current_state = range_pool->parallel_range_states; - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); - for (int i = 0; i < num_tasks; i++) { - BLI_task_pool_push_from_thread( - task_pool, parallel_range_func, POINTER_FROM_INT(i), false, NULL, thread_id); - } - - BLI_task_pool_work_and_wait(task_pool); - - BLI_assert(atomic_cas_ptr((void **)&range_pool->current_state, NULL, NULL) == NULL); - - /* Finalize all tasks. */ - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - const size_t userdata_chunk_size = state->tls_data_size; - void *userdata_chunk_array = state->flatten_tls_storage; - UNUSED_VARS_NDEBUG(userdata_chunk_array); - if (userdata_chunk_size == 0) { - BLI_assert(userdata_chunk_array == NULL); - continue; - } - - if (state->func_finalize != NULL) { - BLI_task_pool_push_from_thread( - task_pool, parallel_range_func_finalize, state, false, NULL, thread_id); - } - } - - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - range_pool->pool = NULL; - - /* Cleanup all tasks. */ - TaskParallelRangeState *state_next; - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state_next) { - state_next = state->next; - - const size_t userdata_chunk_size = state->tls_data_size; - void *userdata_chunk_array = state->flatten_tls_storage; - if (userdata_chunk_size != 0) { - BLI_assert(userdata_chunk_array != NULL); - MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * (size_t)num_tasks); - } - - MEM_freeN(state); - } - range_pool->parallel_range_states = NULL; -} - -/** - * Clear/free given \a range_pool. - */ -void BLI_task_parallel_range_pool_free(TaskParallelRangePool *range_pool) -{ - TaskParallelRangeState *state_next = NULL; - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state_next) { - state_next = state->next; - MEM_freeN(state); - } - MEM_freeN(range_pool->settings); - MEM_freeN(range_pool); + *r_chunk_size = chunk_size; } typedef struct TaskParallelIteratorState { @@ -586,20 +99,10 @@ typedef struct TaskParallelIteratorState { int tot_items; } TaskParallelIteratorState; -BLI_INLINE void task_parallel_iterator_calc_chunk_size(const TaskParallelSettings *settings, - const int num_tasks, - TaskParallelIteratorState *state) -{ - task_parallel_calc_chunk_size( - settings, state->tot_items, num_tasks, &state->iter_shared.chunk_size); -} - static void parallel_iterator_func_do(TaskParallelIteratorState *__restrict state, - void *userdata_chunk, - int threadid) + void *userdata_chunk) { TaskParallelTLS tls = { - .thread_id = threadid, .userdata_chunk = userdata_chunk, }; @@ -652,11 +155,11 @@ static void parallel_iterator_func_do(TaskParallelIteratorState *__restrict stat MALLOCA_FREE(current_chunk_indices, indices_size); } -static void parallel_iterator_func(TaskPool *__restrict pool, void *userdata_chunk, int threadid) +static void parallel_iterator_func(TaskPool *__restrict pool, void *userdata_chunk) { - TaskParallelIteratorState *__restrict state = BLI_task_pool_userdata(pool); + TaskParallelIteratorState *__restrict state = BLI_task_pool_user_data(pool); - parallel_iterator_func_do(state, userdata_chunk, threadid); + parallel_iterator_func_do(state, userdata_chunk); } static void task_parallel_iterator_no_threads(const TaskParallelSettings *settings, @@ -675,23 +178,21 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin /* Also marking it as non-threaded for the iterator callback. */ state->iter_shared.spin_lock = NULL; - parallel_iterator_func_do(state, userdata_chunk, 0); + parallel_iterator_func_do(state, userdata_chunk); - if (use_userdata_chunk) { - if (settings->func_finalize != NULL) { - settings->func_finalize(state->userdata, userdata_chunk_local); - } - MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size); + if (use_userdata_chunk && settings->func_free != NULL) { + /* `func_free` should only free data that was created during execution of `func`. */ + settings->func_free(state->userdata, userdata_chunk_local); } } static void task_parallel_iterator_do(const TaskParallelSettings *settings, TaskParallelIteratorState *state) { - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - const int num_threads = BLI_task_scheduler_num_threads(task_scheduler); + const int num_threads = BLI_task_scheduler_num_threads(); - task_parallel_iterator_calc_chunk_size(settings, num_threads, state); + task_parallel_calc_chunk_size( + settings, state->tot_items, num_threads, &state->iter_shared.chunk_size); if (!settings->use_threading) { task_parallel_iterator_no_threads(settings, state); @@ -720,31 +221,32 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, void *userdata_chunk_array = NULL; const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL); - TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, state, TASK_PRIORITY_HIGH); + TaskPool *task_pool = BLI_task_pool_create(state, TASK_PRIORITY_HIGH); if (use_userdata_chunk) { userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); } - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); for (size_t 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); } /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread( - task_pool, parallel_iterator_func, userdata_chunk_local, false, NULL, thread_id); + BLI_task_pool_push(task_pool, parallel_iterator_func, userdata_chunk_local, false, NULL); } BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); - if (use_userdata_chunk) { - if (settings->func_finalize != NULL) { - for (size_t i = 0; i < num_tasks; i++) { - userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); - settings->func_finalize(state->userdata, userdata_chunk_local); + if (use_userdata_chunk && (settings->func_reduce != NULL || settings->func_free != NULL)) { + for (size_t i = 0; i < num_tasks; i++) { + userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); + if (settings->func_reduce != NULL) { + settings->func_reduce(state->userdata, userdata_chunk, userdata_chunk_local); + } + if (settings->func_free != NULL) { + settings->func_free(state->userdata, userdata_chunk_local); } } MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks); @@ -847,9 +349,9 @@ typedef struct ParallelMempoolState { TaskParallelMempoolFunc func; } ParallelMempoolState; -static void parallel_mempool_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) +static void parallel_mempool_func(TaskPool *__restrict pool, void *taskdata) { - ParallelMempoolState *__restrict state = BLI_task_pool_userdata(pool); + ParallelMempoolState *__restrict state = BLI_task_pool_user_data(pool); BLI_mempool_iter *iter = taskdata; MempoolIterData *item; @@ -875,7 +377,6 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, TaskParallelMempoolFunc func, const bool use_threading) { - TaskScheduler *task_scheduler; TaskPool *task_pool; ParallelMempoolState state; int i, num_threads, num_tasks; @@ -895,9 +396,8 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, return; } - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create_suspended(task_scheduler, &state, TASK_PRIORITY_HIGH); - num_threads = BLI_task_scheduler_num_threads(task_scheduler); + task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); + 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 @@ -911,11 +411,9 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, BLI_mempool_iter *mempool_iterators = BLI_mempool_iter_threadsafe_create(mempool, (size_t)num_tasks); - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); for (i = 0; i < num_tasks; i++) { /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread( - task_pool, parallel_mempool_func, &mempool_iterators[i], false, NULL, thread_id); + BLI_task_pool_push(task_pool, parallel_mempool_func, &mempool_iterators[i], false, NULL); } BLI_task_pool_work_and_wait(task_pool); diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index 8085d495248..c4d60673492 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -17,731 +17,396 @@ /** \file * \ingroup bli * - * A generic task system which can be used for any task based subsystem. + * Task pool to run tasks in parallel. */ +#include <memory> #include <stdlib.h> +#include <utility> #include "MEM_guardedalloc.h" #include "DNA_listBase.h" -#include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_mempool.h" #include "BLI_task.h" #include "BLI_threads.h" -#include "atomic_ops.h" - -/* Define this to enable some detailed statistic print. */ -#undef DEBUG_STATS - -/* Types */ - -/* Number of per-thread pre-allocated tasks. - * - * For more details see description of TaskMemPool. - */ -#define MEMPOOL_SIZE 256 - -/* Number of tasks which are pushed directly to local thread queue. - * - * This allows thread to fetch next task without locking the whole queue. - */ -#define LOCAL_QUEUE_SIZE 1 - -/* Number of tasks which are allowed to be scheduled in a delayed manner. - * - * This allows to use less locks per graph node children schedule. More details - * could be found at TaskThreadLocalStorage::do_delayed_push. - */ -#define DELAYED_QUEUE_SIZE 4096 - -#ifndef NDEBUG -# define ASSERT_THREAD_ID(scheduler, thread_id) \ - do { \ - if (!BLI_thread_is_main()) { \ - TaskThread *thread = (TaskThread *)pthread_getspecific(scheduler->tls_id_key); \ - if (thread == NULL) { \ - BLI_assert(thread_id == 0); \ - } \ - else { \ - BLI_assert(thread_id == thread->id); \ - } \ - } \ - else { \ - BLI_assert(thread_id == 0); \ - } \ - } while (false) -#else -# define ASSERT_THREAD_ID(scheduler, thread_id) +#ifdef WITH_TBB +/* Quiet top level deprecation message, unrelated to API usage here. */ +# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 +# include <tbb/tbb.h> #endif -typedef struct Task { - struct Task *next, *prev; +/* Task + * + * Unit of work to execute. This is a C++ class to work with TBB. */ +class Task { + public: + TaskPool *pool; TaskRunFunction run; void *taskdata; bool free_taskdata; TaskFreeFunction freedata; - TaskPool *pool; -} Task; -/* This is a per-thread storage of pre-allocated tasks. - * - * The idea behind this is simple: reduce amount of malloc() calls when pushing - * new task to the pool. This is done by keeping memory from the tasks which - * were finished already, so instead of freeing that memory we put it to the - * pool for the later re-use. - * - * The tricky part here is to avoid any inter-thread synchronization, hence no - * lock must exist around this pool. The pool will become an owner of the pointer - * from freed task, and only corresponding thread will be able to use this pool - * (no memory stealing and such). - * - * This leads to the following use of the pool: - * - * - task_push() should provide proper thread ID from which the task is being - * pushed from. - * - * - Task allocation function which check corresponding memory pool and if there - * is any memory in there it'll mark memory as re-used, remove it from the pool - * and use that memory for the new task. - * - * At this moment task queue owns the memory. - * - * - When task is done and task_free() is called the memory will be put to the - * pool which corresponds to a thread which handled the task. - */ -typedef struct TaskMemPool { - /* Number of pre-allocated tasks in the pool. */ - int num_tasks; - /* Pre-allocated task memory pointers. */ - Task *tasks[MEMPOOL_SIZE]; -} TaskMemPool; - -#ifdef DEBUG_STATS -typedef struct TaskMemPoolStats { - /* Number of allocations. */ - int num_alloc; - /* Number of avoided allocations (pointer was re-used from the pool). */ - int num_reuse; - /* Number of discarded memory due to pool saturation, */ - int num_discard; -} TaskMemPoolStats; -#endif - -typedef struct TaskThreadLocalStorage { - /* Memory pool for faster task allocation. - * The idea is to re-use memory of finished/discarded tasks by this thread. - */ - TaskMemPool task_mempool; - - /* Local queue keeps thread alive by keeping small amount of tasks ready - * to be picked up without causing global thread locks for synchronization. - */ - int num_local_queue; - Task *local_queue[LOCAL_QUEUE_SIZE]; - - /* Thread can be marked for delayed tasks push. This is helpful when it's - * know that lots of subsequent task pushed will happen from the same thread - * without "interrupting" for task execution. - * - * We try to accumulate as much tasks as possible in a local queue without - * any locks first, and then we push all of them into a scheduler's queue - * from within a single mutex lock. - */ - bool do_delayed_push; - int num_delayed_queue; - Task *delayed_queue[DELAYED_QUEUE_SIZE]; -} TaskThreadLocalStorage; - -struct TaskPool { - TaskScheduler *scheduler; - - volatile size_t num; - ThreadMutex num_mutex; - ThreadCondition num_cond; - - void *userdata; - ThreadMutex user_mutex; + Task(TaskPool *pool, + TaskRunFunction run, + void *taskdata, + bool free_taskdata, + TaskFreeFunction freedata) + : pool(pool), run(run), taskdata(taskdata), free_taskdata(free_taskdata), freedata(freedata) + { + } - volatile bool do_cancel; - volatile bool do_work; + ~Task() + { + if (free_taskdata) { + if (freedata) { + freedata(pool, taskdata); + } + else { + MEM_freeN(taskdata); + } + } + } - volatile bool is_suspended; - bool start_suspended; - ListBase suspended_queue; - size_t num_suspended; + /* Move constructor. + * For performance, ensure we never copy the task and only move it. + * For TBB version 2017 and earlier we apply a workaround to make up for + * the lack of move constructor support. */ + Task(Task &&other) + : pool(other.pool), + run(other.run), + taskdata(other.taskdata), + free_taskdata(other.free_taskdata), + freedata(other.freedata) + { + other.pool = NULL; + other.run = NULL; + other.taskdata = NULL; + other.free_taskdata = false; + other.freedata = NULL; + } + +#if defined(WITH_TBB) && TBB_INTERFACE_VERSION_MAJOR < 10 + Task(const Task &other) + : pool(other.pool), + run(other.run), + taskdata(other.taskdata), + free_taskdata(other.free_taskdata), + freedata(other.freedata) + { + ((Task &)other).pool = NULL; + ((Task &)other).run = NULL; + ((Task &)other).taskdata = NULL; + ((Task &)other).free_taskdata = false; + ((Task &)other).freedata = NULL; + } +#else + Task(const Task &other) = delete; +#endif - TaskPriority priority; + Task &operator=(const Task &other) = delete; + Task &operator=(Task &&other) = delete; - /* If set, this pool may never be work_and_wait'ed, which means TaskScheduler - * has to use its special background fallback thread in case we are in - * single-threaded situation. - */ - bool run_in_background; + /* Execute task. */ + void operator()() const + { + run(pool, taskdata); + } +}; - /* This is a task scheduler's ID of a thread at which pool was constructed. - * It will be used to access task TLS. - */ - int thread_id; +/* TBB Task Group. + * + * Subclass since there seems to be no other way to set priority. */ + +#ifdef WITH_TBB +class TBBTaskGroup : public tbb::task_group { + public: + TBBTaskGroup(TaskPriority priority) + { + switch (priority) { + case TASK_PRIORITY_LOW: + my_context.set_priority(tbb::priority_low); + break; + case TASK_PRIORITY_HIGH: + my_context.set_priority(tbb::priority_normal); + break; + } + } - /* For the pools which are created from non-main thread which is not a - * scheduler worker thread we can't re-use any of scheduler's threads TLS - * and have to use our own one. - */ - bool use_local_tls; - TaskThreadLocalStorage local_tls; -#ifndef NDEBUG - pthread_t creator_thread_id; + ~TBBTaskGroup() + { + } +}; #endif -#ifdef DEBUG_STATS - TaskMemPoolStats *mempool_stats; -#endif -}; +/* Task Pool */ -struct TaskScheduler { - pthread_t *threads; - struct TaskThread *task_threads; - int num_threads; - bool background_thread_only; +typedef enum TaskPoolType { + TASK_POOL_TBB, + TASK_POOL_TBB_SUSPENDED, + TASK_POOL_NO_THREADS, + TASK_POOL_BACKGROUND, + TASK_POOL_BACKGROUND_SERIAL, +} TaskPoolType; - ListBase queue; - ThreadMutex queue_mutex; - ThreadCondition queue_cond; +struct TaskPool { + TaskPoolType type; + bool use_threads; - ThreadMutex startup_mutex; - ThreadCondition startup_cond; - volatile int num_thread_started; + ThreadMutex user_mutex; + void *userdata; - volatile bool do_exit; + /* TBB task pool. */ +#ifdef WITH_TBB + TBBTaskGroup tbb_group; +#endif + volatile bool is_suspended; + BLI_mempool *suspended_mempool; - /* NOTE: In pthread's TLS we store the whole TaskThread structure. */ - pthread_key_t tls_id_key; + /* Background task pool. */ + ListBase background_threads; + ThreadQueue *background_queue; + volatile bool background_is_canceling; }; -typedef struct TaskThread { - TaskScheduler *scheduler; - int id; - TaskThreadLocalStorage tls; -} TaskThread; - -/* Helper */ -BLI_INLINE void task_data_free(Task *task, const int thread_id) -{ - if (task->free_taskdata) { - if (task->freedata) { - task->freedata(task->pool, task->taskdata, thread_id); - } - else { - MEM_freeN(task->taskdata); - } - } -} - -BLI_INLINE void initialize_task_tls(TaskThreadLocalStorage *tls) -{ - memset(tls, 0, sizeof(TaskThreadLocalStorage)); -} +/* TBB Task Pool. + * + * Task pool using the TBB scheduler for tasks. When building without TBB + * support or running Blender with -t 1, this reverts to single threaded. + * + * Tasks may be suspended until in all are created, to make it possible to + * initialize data structures and create tasks in a single pass. */ -BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool, const int thread_id) +static void tbb_task_pool_create(TaskPool *pool, TaskPriority priority) { - TaskScheduler *scheduler = pool->scheduler; - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= scheduler->num_threads); - if (pool->use_local_tls && thread_id == 0) { - BLI_assert(pool->thread_id == 0); - BLI_assert(!BLI_thread_is_main()); - BLI_assert(pthread_equal(pthread_self(), pool->creator_thread_id)); - return &pool->local_tls; + if (pool->type == TASK_POOL_TBB_SUSPENDED) { + pool->is_suspended = true; + pool->suspended_mempool = BLI_mempool_create(sizeof(Task), 512, 512, BLI_MEMPOOL_ALLOW_ITER); } - if (thread_id == 0) { - BLI_assert(BLI_thread_is_main()); - return &scheduler->task_threads[pool->thread_id].tls; - } - return &scheduler->task_threads[thread_id].tls; -} -BLI_INLINE void free_task_tls(TaskThreadLocalStorage *tls) -{ - TaskMemPool *task_mempool = &tls->task_mempool; - for (int i = 0; i < task_mempool->num_tasks; i++) { - MEM_freeN(task_mempool->tasks[i]); +#ifdef WITH_TBB + if (pool->use_threads) { + new (&pool->tbb_group) TBBTaskGroup(priority); } -} - -static Task *task_alloc(TaskPool *pool, const int thread_id) -{ - BLI_assert(thread_id <= pool->scheduler->num_threads); - if (thread_id != -1) { - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= pool->scheduler->num_threads); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - TaskMemPool *task_mempool = &tls->task_mempool; - /* Try to re-use task memory from a thread local storage. */ - if (task_mempool->num_tasks > 0) { - --task_mempool->num_tasks; - /* Success! We've just avoided task allocation. */ -#ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_reuse++; -#endif - return task_mempool->tasks[task_mempool->num_tasks]; - } - /* We are doomed to allocate new task data. */ -#ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_alloc++; +#else + UNUSED_VARS(priority); #endif - } - return (Task *)MEM_mallocN(sizeof(Task), "New task"); } -static void task_free(TaskPool *pool, Task *task, const int thread_id) +static void tbb_task_pool_run(TaskPool *pool, Task &&task) { - task_data_free(task, thread_id); - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= pool->scheduler->num_threads); - if (thread_id == 0) { - BLI_assert(pool->use_local_tls || BLI_thread_is_main()); + if (pool->is_suspended) { + /* Suspended task that will be executed in work_and_wait(). */ + Task *task_mem = (Task *)BLI_mempool_alloc(pool->suspended_mempool); + new (task_mem) Task(std::move(task)); +#ifdef __GNUC__ + /* Work around apparent compiler bug where task is not properly copied + * to task_mem. This appears unrelated to the use of placement new or + * move semantics, happens even writing to a plain C struct. Rather the + * call into TBB seems to have some indirect effect. */ + std::atomic_thread_fence(std::memory_order_release); +#endif } - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - TaskMemPool *task_mempool = &tls->task_mempool; - if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) { - /* Successfully allowed the task to be re-used later. */ - task_mempool->tasks[task_mempool->num_tasks] = task; - ++task_mempool->num_tasks; +#ifdef WITH_TBB + else if (pool->use_threads) { + /* Execute in TBB task group. */ + pool->tbb_group.run(std::move(task)); } - else { - /* Local storage saturated, no other way than just discard - * the memory. - * - * TODO(sergey): We can perhaps store such pointer in a global - * scheduler pool, maybe it'll be faster than discarding and - * allocating again. - */ - MEM_freeN(task); -#ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_discard++; #endif + else { + /* Execute immediately. */ + task(); } } -/* Task Scheduler */ - -static void task_pool_num_decrease(TaskPool *pool, size_t done) +static void tbb_task_pool_work_and_wait(TaskPool *pool) { - BLI_mutex_lock(&pool->num_mutex); + /* Start any suspended task now. */ + if (pool->suspended_mempool) { + pool->is_suspended = false; - BLI_assert(pool->num >= done); - - pool->num -= done; + BLI_mempool_iter iter; + BLI_mempool_iternew(pool->suspended_mempool, &iter); + while (Task *task = (Task *)BLI_mempool_iterstep(&iter)) { + tbb_task_pool_run(pool, std::move(*task)); + } - if (pool->num == 0) { - BLI_condition_notify_all(&pool->num_cond); + BLI_mempool_clear(pool->suspended_mempool); } - BLI_mutex_unlock(&pool->num_mutex); +#ifdef WITH_TBB + if (pool->use_threads) { + /* This is called wait(), but internally it can actually do work. This + * matters because we don't want recursive usage of task pools to run + * out of threads and get stuck. */ + pool->tbb_group.wait(); + } +#endif } -static void task_pool_num_increase(TaskPool *pool, size_t new_num) +static void tbb_task_pool_cancel(TaskPool *pool) { - BLI_mutex_lock(&pool->num_mutex); - - pool->num += new_num; - BLI_condition_notify_all(&pool->num_cond); - - BLI_mutex_unlock(&pool->num_mutex); +#ifdef WITH_TBB + if (pool->use_threads) { + pool->tbb_group.cancel(); + pool->tbb_group.wait(); + } +#else + UNUSED_VARS(pool); +#endif } -static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task) +static bool tbb_task_pool_canceled(TaskPool *pool) { - bool found_task = false; - BLI_mutex_lock(&scheduler->queue_mutex); - - while (!scheduler->queue.first && !scheduler->do_exit) { - BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); +#ifdef WITH_TBB + if (pool->use_threads) { + return pool->tbb_group.is_canceling(); } +#else + UNUSED_VARS(pool); +#endif - do { - Task *current_task; - - /* Assuming we can only have a void queue in 'exit' case here seems logical - * (we should only be here after our worker thread has been woken up from a - * condition_wait(), which only happens after a new task was added to the queue), - * but it is wrong. - * Waiting on condition may wake up the thread even if condition is not signaled - * (spurious wake-ups), and some race condition may also empty the queue **after** - * condition has been signaled, but **before** awoken thread reaches this point... - * See http://stackoverflow.com/questions/8594591 - * - * So we only abort here if do_exit is set. - */ - if (scheduler->do_exit) { - BLI_mutex_unlock(&scheduler->queue_mutex); - return false; - } - - for (current_task = (Task *)scheduler->queue.first; current_task != NULL; - current_task = current_task->next) { - TaskPool *pool = current_task->pool; - - if (scheduler->background_thread_only && !pool->run_in_background) { - continue; - } - - *task = current_task; - found_task = true; - BLI_remlink(&scheduler->queue, *task); - break; - } - if (!found_task) { - BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); - } - } while (!found_task); - - BLI_mutex_unlock(&scheduler->queue_mutex); - - return true; + return false; } -BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, const int thread_id) +static void tbb_task_pool_free(TaskPool *pool) { - BLI_assert(!tls->do_delayed_push); - while (tls->num_local_queue > 0) { - /* We pop task from queue before handling it so handler of the task can - * push next job to the local queue. - */ - tls->num_local_queue--; - Task *local_task = tls->local_queue[tls->num_local_queue]; - /* TODO(sergey): Double-check work_and_wait() doesn't handle other's - * pool tasks. - */ - TaskPool *local_pool = local_task->pool; - local_task->run(local_pool, local_task->taskdata, thread_id); - task_free(local_pool, local_task, thread_id); +#ifdef WITH_TBB + if (pool->use_threads) { + pool->tbb_group.~TBBTaskGroup(); } - BLI_assert(!tls->do_delayed_push); -} +#endif -static void *task_scheduler_thread_run(void *thread_p) -{ - TaskThread *thread = (TaskThread *)thread_p; - TaskThreadLocalStorage *tls = &thread->tls; - TaskScheduler *scheduler = thread->scheduler; - int thread_id = thread->id; - Task *task; - - pthread_setspecific(scheduler->tls_id_key, thread); - - /* signal the main thread when all threads have started */ - BLI_mutex_lock(&scheduler->startup_mutex); - scheduler->num_thread_started++; - if (scheduler->num_thread_started == scheduler->num_threads) { - BLI_condition_notify_one(&scheduler->startup_cond); + if (pool->suspended_mempool) { + BLI_mempool_destroy(pool->suspended_mempool); } - BLI_mutex_unlock(&scheduler->startup_mutex); - - /* keep popping off tasks */ - while (task_scheduler_thread_wait_pop(scheduler, &task)) { - TaskPool *pool = task->pool; - - /* run task */ - BLI_assert(!tls->do_delayed_push); - task->run(pool, task->taskdata, thread_id); - BLI_assert(!tls->do_delayed_push); - - /* delete task */ - task_free(pool, task, thread_id); +} - /* Handle all tasks from local queue. */ - handle_local_queue(tls, thread_id); +/* Background Task Pool. + * + * Fallback for running background tasks when building without TBB. */ - /* notify pool task was done */ - task_pool_num_decrease(pool, 1); +static void *background_task_run(void *userdata) +{ + TaskPool *pool = (TaskPool *)userdata; + while (Task *task = (Task *)BLI_thread_queue_pop(pool->background_queue)) { + (*task)(); + task->~Task(); + MEM_freeN(task); } - return NULL; } -TaskScheduler *BLI_task_scheduler_create(int num_threads) +static void background_task_pool_create(TaskPool *pool) { - TaskScheduler *scheduler = (TaskScheduler *)MEM_callocN(sizeof(TaskScheduler), "TaskScheduler"); - - /* multiple places can use this task scheduler, sharing the same - * threads, so we keep track of the number of users. */ - scheduler->do_exit = false; - - BLI_listbase_clear(&scheduler->queue); - BLI_mutex_init(&scheduler->queue_mutex); - BLI_condition_init(&scheduler->queue_cond); - - BLI_mutex_init(&scheduler->startup_mutex); - BLI_condition_init(&scheduler->startup_cond); - scheduler->num_thread_started = 0; - - if (num_threads == 0) { - /* automatic number of threads will be main thread + num cores */ - num_threads = BLI_system_thread_count(); - } - - /* main thread will also work, so we count it too */ - num_threads -= 1; - - /* Add background-only thread if needed. */ - if (num_threads == 0) { - scheduler->background_thread_only = true; - num_threads = 1; - } - - scheduler->task_threads = (TaskThread *)MEM_mallocN(sizeof(TaskThread) * (num_threads + 1), - "TaskScheduler task threads"); - - /* Initialize TLS for main thread. */ - initialize_task_tls(&scheduler->task_threads[0].tls); - - pthread_key_create(&scheduler->tls_id_key, NULL); - - /* launch threads that will be waiting for work */ - if (num_threads > 0) { - int i; - - scheduler->num_threads = num_threads; - scheduler->threads = (pthread_t *)MEM_callocN(sizeof(pthread_t) * num_threads, - "TaskScheduler threads"); - - for (i = 0; i < num_threads; i++) { - TaskThread *thread = &scheduler->task_threads[i + 1]; - thread->scheduler = scheduler; - thread->id = i + 1; - initialize_task_tls(&thread->tls); - - if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) { - fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads); - } - } - } - - /* Wait for all worker threads to start before returning to caller to prevent the case where - * threads are still starting and pthread_join is called, which causes a deadlock on pthreads4w. - */ - BLI_mutex_lock(&scheduler->startup_mutex); - /* NOTE: Use loop here to avoid false-positive everything-is-ready caused by spontaneous thread - * wake up. */ - while (scheduler->num_thread_started != num_threads) { - BLI_condition_wait(&scheduler->startup_cond, &scheduler->startup_mutex); - } - BLI_mutex_unlock(&scheduler->startup_mutex); - - return scheduler; + pool->background_queue = BLI_thread_queue_init(); + BLI_threadpool_init(&pool->background_threads, background_task_run, 1); } -void BLI_task_scheduler_free(TaskScheduler *scheduler) +static void background_task_pool_run(TaskPool *pool, Task &&task) { - Task *task; - - /* stop all waiting threads */ - BLI_mutex_lock(&scheduler->queue_mutex); - scheduler->do_exit = true; - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); - - pthread_key_delete(scheduler->tls_id_key); - - /* delete threads */ - if (scheduler->threads) { - int i; - - for (i = 0; i < scheduler->num_threads; i++) { - if (pthread_join(scheduler->threads[i], NULL) != 0) { - fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads); - } - } + Task *task_mem = (Task *)MEM_mallocN(sizeof(Task), __func__); + new (task_mem) Task(std::move(task)); + BLI_thread_queue_push(pool->background_queue, task_mem); - MEM_freeN(scheduler->threads); + if (BLI_available_threads(&pool->background_threads)) { + BLI_threadpool_insert(&pool->background_threads, pool); } - - /* Delete task thread data */ - if (scheduler->task_threads) { - for (int i = 0; i < scheduler->num_threads + 1; i++) { - TaskThreadLocalStorage *tls = &scheduler->task_threads[i].tls; - free_task_tls(tls); - } - - MEM_freeN(scheduler->task_threads); - } - - /* delete leftover tasks */ - for (task = (Task *)scheduler->queue.first; task; task = task->next) { - task_data_free(task, 0); - } - BLI_freelistN(&scheduler->queue); - - /* delete mutex/condition */ - BLI_mutex_end(&scheduler->queue_mutex); - BLI_condition_end(&scheduler->queue_cond); - BLI_mutex_end(&scheduler->startup_mutex); - BLI_condition_end(&scheduler->startup_cond); - - MEM_freeN(scheduler); } -int BLI_task_scheduler_num_threads(TaskScheduler *scheduler) +static void background_task_pool_work_and_wait(TaskPool *pool) { - return scheduler->num_threads + 1; + /* Signal background thread to stop waiting for new tasks if none are + * left, and wait for tasks and thread to finish. */ + BLI_thread_queue_nowait(pool->background_queue); + BLI_thread_queue_wait_finish(pool->background_queue); + BLI_threadpool_clear(&pool->background_threads); } -static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority) +static void background_task_pool_cancel(TaskPool *pool) { - task_pool_num_increase(task->pool, 1); + pool->background_is_canceling = true; - /* add task to queue */ - BLI_mutex_lock(&scheduler->queue_mutex); - - if (priority == TASK_PRIORITY_HIGH) { - BLI_addhead(&scheduler->queue, task); - } - else { - BLI_addtail(&scheduler->queue, task); + /* Remove tasks not yet started by background thread. */ + BLI_thread_queue_nowait(pool->background_queue); + while (Task *task = (Task *)BLI_thread_queue_pop(pool->background_queue)) { + task->~Task(); + MEM_freeN(task); } - BLI_condition_notify_one(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); + /* Let background thread finish or cancel task it is working on. */ + BLI_threadpool_remove(&pool->background_threads, pool); + pool->background_is_canceling = false; } -static void task_scheduler_push_all(TaskScheduler *scheduler, - TaskPool *pool, - Task **tasks, - int num_tasks) +static bool background_task_pool_canceled(TaskPool *pool) { - if (num_tasks == 0) { - return; - } - - task_pool_num_increase(pool, num_tasks); - - BLI_mutex_lock(&scheduler->queue_mutex); - - for (int i = 0; i < num_tasks; i++) { - BLI_addhead(&scheduler->queue, tasks[i]); - } - - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); + return pool->background_is_canceling; } -static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool) +static void background_task_pool_free(TaskPool *pool) { - Task *task, *nexttask; - size_t done = 0; - - BLI_mutex_lock(&scheduler->queue_mutex); - - /* free all tasks from this pool from the queue */ - for (task = (Task *)scheduler->queue.first; task; task = nexttask) { - nexttask = task->next; - - if (task->pool == pool) { - task_data_free(task, pool->thread_id); - BLI_freelinkN(&scheduler->queue, task); + background_task_pool_work_and_wait(pool); - done++; - } - } - - BLI_mutex_unlock(&scheduler->queue_mutex); - - /* notify done */ - task_pool_num_decrease(pool, done); + BLI_threadpool_end(&pool->background_threads); + BLI_thread_queue_free(pool->background_queue); } /* Task Pool */ -static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, - void *userdata, - const bool is_background, - const bool is_suspended, - TaskPriority priority) +static TaskPool *task_pool_create_ex(void *userdata, TaskPoolType type, TaskPriority priority) { - TaskPool *pool = (TaskPool *)MEM_mallocN(sizeof(TaskPool), "TaskPool"); + /* Ensure malloc will go fine from threads, + * + * This is needed because we could be in main thread here + * and malloc could be non-thread safe at this point because + * no other jobs are running. + */ + BLI_threaded_malloc_begin(); -#ifndef NDEBUG - /* Assert we do not try to create a background pool from some parent task - - * those only work OK from main thread. */ - if (is_background) { - const pthread_t thread_id = pthread_self(); - int i = scheduler->num_threads; + const bool use_threads = BLI_task_scheduler_num_threads() > 1 && type != TASK_POOL_NO_THREADS; - while (i--) { - BLI_assert(!pthread_equal(scheduler->threads[i], thread_id)); - } + /* Background task pool uses regular TBB scheduling if available. Only when + * building without TBB or running with -t 1 do we need to ensure these tasks + * do not block the main thread. */ + if (type == TASK_POOL_BACKGROUND && use_threads) { + type = TASK_POOL_TBB; } -#endif - pool->scheduler = scheduler; - pool->num = 0; - pool->do_cancel = false; - pool->do_work = false; - pool->is_suspended = is_suspended; - pool->start_suspended = is_suspended; - pool->num_suspended = 0; - pool->suspended_queue.first = pool->suspended_queue.last = NULL; - pool->priority = priority; - pool->run_in_background = is_background; - pool->use_local_tls = false; - - BLI_mutex_init(&pool->num_mutex); - BLI_condition_init(&pool->num_cond); + /* Allocate task pool. */ + TaskPool *pool = (TaskPool *)MEM_callocN(sizeof(TaskPool), "TaskPool"); + + pool->type = type; + pool->use_threads = use_threads; pool->userdata = userdata; BLI_mutex_init(&pool->user_mutex); - if (BLI_thread_is_main()) { - pool->thread_id = 0; - } - else { - TaskThread *thread = (TaskThread *)pthread_getspecific(scheduler->tls_id_key); - if (thread == NULL) { - /* NOTE: Task pool is created from non-main thread which is not - * managed by the task scheduler. We identify ourselves as thread ID - * 0 but we do not use scheduler's TLS storage and use our own - * instead to avoid any possible threading conflicts. - */ - pool->thread_id = 0; - pool->use_local_tls = true; -#ifndef NDEBUG - pool->creator_thread_id = pthread_self(); -#endif - initialize_task_tls(&pool->local_tls); - } - else { - pool->thread_id = thread->id; - } + switch (type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_create(pool, priority); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_create(pool); + break; } -#ifdef DEBUG_STATS - pool->mempool_stats = (TaskMemPoolStats *)MEM_callocN( - sizeof(*pool->mempool_stats) * (scheduler->num_threads + 1), "per-taskpool mempool stats"); -#endif - - /* Ensure malloc will go fine from threads, - * - * This is needed because we could be in main thread here - * and malloc could be non-thread safe at this point because - * no other jobs are running. - */ - BLI_threaded_malloc_begin(); - return pool; } /** * Create a normal task pool. Tasks will be executed as soon as they are added. */ -TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPriority priority) +TaskPool *BLI_task_pool_create(void *userdata, TaskPriority priority) { - return task_pool_create_ex(scheduler, userdata, false, false, priority); + return task_pool_create_ex(userdata, TASK_POOL_TBB, priority); } /** @@ -756,11 +421,9 @@ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPri * they could end never being executed, since the 'fallback' background thread is already * busy with parent task in single-threaded context). */ -TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority) +TaskPool *BLI_task_pool_create_background(void *userdata, TaskPriority priority) { - return task_pool_create_ex(scheduler, userdata, true, false, priority); + return task_pool_create_ex(userdata, TASK_POOL_BACKGROUND, priority); } /** @@ -768,231 +431,117 @@ TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, * for until BLI_task_pool_work_and_wait() is called. This helps reducing threading * overhead when pushing huge amount of small initial tasks from the main thread. */ -TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority) +TaskPool *BLI_task_pool_create_suspended(void *userdata, TaskPriority priority) { - return task_pool_create_ex(scheduler, userdata, false, true, priority); + return task_pool_create_ex(userdata, TASK_POOL_TBB_SUSPENDED, priority); } -void BLI_task_pool_free(TaskPool *pool) +/** + * Single threaded task pool that executes pushed task immediately, for + * debugging purposes. + */ +TaskPool *BLI_task_pool_create_no_threads(void *userdata) { - BLI_task_pool_cancel(pool); - - BLI_mutex_end(&pool->num_mutex); - BLI_condition_end(&pool->num_cond); + return task_pool_create_ex(userdata, TASK_POOL_NO_THREADS, TASK_PRIORITY_HIGH); +} - BLI_mutex_end(&pool->user_mutex); +/** + * Task pool that executes one task after the other, possibly on different threads + * but never in parallel. + */ +TaskPool *BLI_task_pool_create_background_serial(void *userdata, TaskPriority priority) +{ + return task_pool_create_ex(userdata, TASK_POOL_BACKGROUND_SERIAL, priority); +} -#ifdef DEBUG_STATS - printf("Thread ID Allocated Reused Discarded\n"); - for (int i = 0; i < pool->scheduler->num_threads + 1; i++) { - printf("%02d %05d %05d %05d\n", - i, - pool->mempool_stats[i].num_alloc, - pool->mempool_stats[i].num_reuse, - pool->mempool_stats[i].num_discard); +void BLI_task_pool_free(TaskPool *pool) +{ + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_free(pool); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_free(pool); + break; } - MEM_freeN(pool->mempool_stats); -#endif - if (pool->use_local_tls) { - free_task_tls(&pool->local_tls); - } + BLI_mutex_end(&pool->user_mutex); MEM_freeN(pool); BLI_threaded_malloc_end(); } -BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id) -{ - return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work)); -} - -static void task_pool_push(TaskPool *pool, - TaskRunFunction run, - void *taskdata, - bool free_taskdata, - TaskFreeFunction freedata, - int thread_id) -{ - /* Allocate task and fill it's properties. */ - Task *task = task_alloc(pool, thread_id); - task->run = run; - task->taskdata = taskdata; - task->free_taskdata = free_taskdata; - task->freedata = freedata; - task->pool = pool; - /* For suspended pools we put everything yo a global queue first - * and exit as soon as possible. - * - * This tasks will be moved to actual execution when pool is - * activated by work_and_wait(). - */ - if (pool->is_suspended) { - BLI_addhead(&pool->suspended_queue, task); - atomic_fetch_and_add_z(&pool->num_suspended, 1); - return; - } - /* Populate to any local queue first, this is cheapest push ever. */ - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - /* Try to push to a local execution queue. - * These tasks will be picked up next. - */ - if (tls->num_local_queue < LOCAL_QUEUE_SIZE) { - tls->local_queue[tls->num_local_queue] = task; - tls->num_local_queue++; - return; - } - /* If we are in the delayed tasks push mode, we push tasks to a - * temporary local queue first without any locks, and then move them - * to global execution queue with a single lock. - */ - if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) { - tls->delayed_queue[tls->num_delayed_queue] = task; - tls->num_delayed_queue++; - return; - } - } - /* Do push to a global execution pool, slowest possible method, - * causes quite reasonable amount of threading overhead. - */ - task_scheduler_push(pool->scheduler, task, pool->priority); -} - void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata) { - task_pool_push(pool, run, taskdata, free_taskdata, freedata, -1); -} + Task task(pool, run, taskdata, free_taskdata, freedata); -void BLI_task_pool_push_from_thread(TaskPool *pool, - TaskRunFunction run, - void *taskdata, - bool free_taskdata, - TaskFreeFunction freedata, - int thread_id) -{ - task_pool_push(pool, run, taskdata, free_taskdata, freedata, thread_id); + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_run(pool, std::move(task)); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_run(pool, std::move(task)); + break; + } } void BLI_task_pool_work_and_wait(TaskPool *pool) { - TaskThreadLocalStorage *tls = get_task_tls(pool, pool->thread_id); - TaskScheduler *scheduler = pool->scheduler; - - if (atomic_fetch_and_and_uint8((uint8_t *)&pool->is_suspended, 0)) { - if (pool->num_suspended) { - task_pool_num_increase(pool, pool->num_suspended); - BLI_mutex_lock(&scheduler->queue_mutex); - - BLI_movelisttolist(&scheduler->queue, &pool->suspended_queue); - - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); - - pool->num_suspended = 0; - } - } - - pool->do_work = true; - - ASSERT_THREAD_ID(pool->scheduler, pool->thread_id); - - handle_local_queue(tls, pool->thread_id); - - BLI_mutex_lock(&pool->num_mutex); - - while (pool->num != 0) { - Task *task, *work_task = NULL; - bool found_task = false; - - BLI_mutex_unlock(&pool->num_mutex); - - BLI_mutex_lock(&scheduler->queue_mutex); - - /* find task from this pool. if we get a task from another pool, - * we can get into deadlock */ - - for (task = (Task *)scheduler->queue.first; task; task = task->next) { - if (task->pool == pool) { - work_task = task; - found_task = true; - BLI_remlink(&scheduler->queue, task); - break; - } - } - - BLI_mutex_unlock(&scheduler->queue_mutex); - - /* if found task, do it, otherwise wait until other tasks are done */ - if (found_task) { - /* run task */ - BLI_assert(!tls->do_delayed_push); - work_task->run(pool, work_task->taskdata, pool->thread_id); - BLI_assert(!tls->do_delayed_push); - - /* delete task */ - task_free(pool, task, pool->thread_id); - - /* Handle all tasks from local queue. */ - handle_local_queue(tls, pool->thread_id); - - /* notify pool task was done */ - task_pool_num_decrease(pool, 1); - } - - BLI_mutex_lock(&pool->num_mutex); - if (pool->num == 0) { + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_work_and_wait(pool); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_work_and_wait(pool); break; - } - - if (!found_task) { - BLI_condition_wait(&pool->num_cond, &pool->num_mutex); - } } - - BLI_mutex_unlock(&pool->num_mutex); - - BLI_assert(tls->num_local_queue == 0); -} - -void BLI_task_pool_work_wait_and_reset(TaskPool *pool) -{ - BLI_task_pool_work_and_wait(pool); - - pool->do_work = false; - pool->is_suspended = pool->start_suspended; } void BLI_task_pool_cancel(TaskPool *pool) { - pool->do_cancel = true; - - task_scheduler_clear(pool->scheduler, pool); - - /* wait until all entries are cleared */ - BLI_mutex_lock(&pool->num_mutex); - while (pool->num) { - BLI_condition_wait(&pool->num_cond, &pool->num_mutex); + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_cancel(pool); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_cancel(pool); + break; } - BLI_mutex_unlock(&pool->num_mutex); - - pool->do_cancel = false; } bool BLI_task_pool_canceled(TaskPool *pool) { - return pool->do_cancel; + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + return tbb_task_pool_canceled(pool); + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + return background_task_pool_canceled(pool); + } + BLI_assert("BLI_task_pool_canceled: Control flow should not come here!"); + return false; } -void *BLI_task_pool_userdata(TaskPool *pool) +void *BLI_task_pool_user_data(TaskPool *pool) { return pool->userdata; } @@ -1001,29 +550,3 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool) { return &pool->user_mutex; } - -int BLI_task_pool_creator_thread_id(TaskPool *pool) -{ - return pool->thread_id; -} - -void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id) -{ - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - tls->do_delayed_push = true; - } -} - -void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id) -{ - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - BLI_assert(tls->do_delayed_push); - task_scheduler_push_all(pool->scheduler, pool, tls->delayed_queue, tls->num_delayed_queue); - tls->do_delayed_push = false; - tls->num_delayed_queue = 0; - } -} diff --git a/source/blender/blenkernel/intern/pbvh_parallel.cc b/source/blender/blenlib/intern/task_range.cc index 2534fdea3ee..a8447c305e0 100644 --- a/source/blender/blenkernel/intern/pbvh_parallel.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -14,60 +14,72 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/** \file + * \ingroup bli + * + * Task parallel range functions. + */ + +#include <stdlib.h> + #include "MEM_guardedalloc.h" +#include "DNA_listBase.h" + #include "BLI_task.h" #include "BLI_threads.h" -#include "BKE_pbvh.h" - #include "atomic_ops.h" #ifdef WITH_TBB - /* Quiet top level deprecation message, unrelated to API usage here. */ # define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 - # include <tbb/tbb.h> +#endif + +#ifdef WITH_TBB /* Functor for running TBB parallel_for and parallel_reduce. */ -struct PBVHTask { - PBVHParallelRangeFunc func; +struct RangeTask { + TaskParallelRangeFunc func; void *userdata; - const PBVHParallelSettings *settings; + const TaskParallelSettings *settings; void *userdata_chunk; /* Root constructor. */ - PBVHTask(PBVHParallelRangeFunc func, void *userdata, const PBVHParallelSettings *settings) + RangeTask(TaskParallelRangeFunc func, void *userdata, const TaskParallelSettings *settings) : func(func), userdata(userdata), settings(settings) { init_chunk(settings->userdata_chunk); } /* Copy constructor. */ - PBVHTask(const PBVHTask &other) + RangeTask(const RangeTask &other) : func(other.func), userdata(other.userdata), settings(other.settings) { - init_chunk(other.userdata_chunk); + init_chunk(settings->userdata_chunk); } /* Splitting constructor for parallel reduce. */ - PBVHTask(PBVHTask &other, tbb::split) + RangeTask(RangeTask &other, tbb::split) : func(other.func), userdata(other.userdata), settings(other.settings) { init_chunk(settings->userdata_chunk); } - ~PBVHTask() + ~RangeTask() { + if (settings->func_free != NULL) { + settings->func_free(userdata, userdata_chunk); + } MEM_SAFE_FREE(userdata_chunk); } void init_chunk(void *from_chunk) { if (from_chunk) { - userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "PBVHTask"); + userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "RangeTask"); memcpy(userdata_chunk, from_chunk, settings->userdata_chunk_size); } else { @@ -78,59 +90,41 @@ struct PBVHTask { void operator()(const tbb::blocked_range<int> &r) const { TaskParallelTLS tls; - tls.thread_id = get_thread_id(); tls.userdata_chunk = userdata_chunk; for (int i = r.begin(); i != r.end(); ++i) { func(userdata, i, &tls); } } - void join(const PBVHTask &other) + void join(const RangeTask &other) { settings->func_reduce(userdata, userdata_chunk, other.userdata_chunk); } - - int get_thread_id() const - { - /* Get a unique thread ID for texture nodes. In the future we should get rid - * of the thread ID and change texture evaluation to not require per-thread - * storage that can't be efficiently allocated on the stack. */ - static tbb::enumerable_thread_specific<int> pbvh_thread_id(-1); - static int pbvh_thread_id_counter = 0; - - int &thread_id = pbvh_thread_id.local(); - if (thread_id == -1) { - thread_id = atomic_fetch_and_add_int32(&pbvh_thread_id_counter, 1); - if (thread_id >= BLENDER_MAX_THREADS) { - BLI_assert(!"Maximum number of threads exceeded for sculpting"); - thread_id = thread_id % BLENDER_MAX_THREADS; - } - } - return thread_id; - } }; #endif -void BKE_pbvh_parallel_range(const int start, +void BLI_task_parallel_range(const int start, const int stop, void *userdata, - PBVHParallelRangeFunc func, - const struct PBVHParallelSettings *settings) + TaskParallelRangeFunc func, + const TaskParallelSettings *settings) { #ifdef WITH_TBB /* Multithreading. */ - if (settings->use_threading) { - PBVHTask task(func, userdata, settings); + if (settings->use_threading && BLI_task_scheduler_num_threads() > 1) { + RangeTask task(func, userdata, settings); + const size_t grainsize = MAX2(settings->min_iter_per_thread, 1); + const tbb::blocked_range<int> range(start, stop, grainsize); if (settings->func_reduce) { - parallel_reduce(tbb::blocked_range<int>(start, stop), task); + parallel_reduce(range, task); if (settings->userdata_chunk) { memcpy(settings->userdata_chunk, task.userdata_chunk, settings->userdata_chunk_size); } } else { - parallel_for(tbb::blocked_range<int>(start, stop), task); + parallel_for(range, task); } return; @@ -140,9 +134,34 @@ void BKE_pbvh_parallel_range(const int start, /* Single threaded. Nothing to reduce as everything is accumulated into the * main userdata chunk directly. */ TaskParallelTLS tls; - tls.thread_id = 0; tls.userdata_chunk = settings->userdata_chunk; for (int i = start; i < stop; i++) { func(userdata, i, &tls); } + if (settings->func_free != NULL) { + settings->func_free(userdata, settings->userdata_chunk); + } +} + +int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls)) +{ +#ifdef WITH_TBB + /* Get a unique thread ID for texture nodes. In the future we should get rid + * of the thread ID and change texture evaluation to not require per-thread + * storage that can't be efficiently allocated on the stack. */ + static tbb::enumerable_thread_specific<int> tbb_thread_id(-1); + static int tbb_thread_id_counter = 0; + + int &thread_id = tbb_thread_id.local(); + 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"); + thread_id = thread_id % BLENDER_MAX_THREADS; + } + } + return thread_id; +#else + return 0; +#endif } diff --git a/source/blender/blenlib/intern/task_scheduler.cc b/source/blender/blenlib/intern/task_scheduler.cc new file mode 100644 index 00000000000..b0245da0385 --- /dev/null +++ b/source/blender/blenlib/intern/task_scheduler.cc @@ -0,0 +1,78 @@ +/* + * 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 bli + * + * Task scheduler initialization. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_task.h" +#include "BLI_threads.h" + +#ifdef WITH_TBB +/* Quiet top level deprecation message, unrelated to API usage here. */ +# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 +# include <tbb/tbb.h> +# if TBB_INTERFACE_VERSION_MAJOR >= 10 +# define WITH_TBB_GLOBAL_CONTROL +# endif +#endif + +/* Task Scheduler */ + +static int task_scheduler_num_threads = 1; +#ifdef WITH_TBB_GLOBAL_CONTROL +static tbb::global_control *task_scheduler_global_control = nullptr; +#endif + +void BLI_task_scheduler_init() +{ +#ifdef WITH_TBB_GLOBAL_CONTROL + const int num_threads_override = BLI_system_num_threads_override_get(); + + if (num_threads_override > 0) { + /* Override number of threads. This settings is used within the lifetime + * of tbb::global_control, so we allocate it on the heap. */ + task_scheduler_global_control = OBJECT_GUARDED_NEW( + tbb::global_control, tbb::global_control::max_allowed_parallelism, num_threads_override); + task_scheduler_num_threads = num_threads_override; + } + else { + /* Let TBB choose the number of threads. For (legacy) code that calls + * BLI_task_scheduler_num_threads() we provide the system thread count. + * Ideally such code should be rewritten not to use the number of threads + * at all. */ + task_scheduler_num_threads = BLI_system_thread_count(); + } +#else + task_scheduler_num_threads = BLI_system_thread_count(); +#endif +} + +void BLI_task_scheduler_exit() +{ +#ifdef WITH_TBB_GLOBAL_CONTROL + OBJECT_GUARDED_DELETE(task_scheduler_global_control, tbb::global_control); +#endif +} + +int BLI_task_scheduler_num_threads() +{ + return task_scheduler_num_threads; +} diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 31e8581590a..f535798f86d 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -61,9 +61,6 @@ extern pthread_key_t gomp_tls_key; static void *thread_tls_data; #endif -/* We're using one global task scheduler for all kind of tasks. */ -static TaskScheduler *task_scheduler = NULL; - /* ********** basic thread control API ************ * * Many thread cases have an X amount of jobs, and only an Y amount of @@ -157,27 +154,9 @@ void BLI_threadapi_init(void) void BLI_threadapi_exit(void) { - if (task_scheduler) { - BLI_task_scheduler_free(task_scheduler); - task_scheduler = NULL; - } BLI_spin_end(&_malloc_lock); } -TaskScheduler *BLI_task_scheduler_get(void) -{ - if (task_scheduler == NULL) { - int tot_thread = BLI_system_thread_count(); - - /* Do a lazy initialization, so it happens after - * command line arguments parsing - */ - task_scheduler = BLI_task_scheduler_create(tot_thread); - } - - return task_scheduler; -} - /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) * problem otherwise: scene render will kill of the mutex! */ @@ -839,11 +818,6 @@ void BLI_threaded_malloc_begin(void) unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); if (level == 0) { MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); - /* There is a little chance that two threads will need to access to a - * scheduler which was not yet created from main thread. which could - * cause scheduler created multiple times. - */ - BLI_task_scheduler_get(); } } diff --git a/source/blender/blenlib/intern/timeit.cc b/source/blender/blenlib/intern/timeit.cc new file mode 100644 index 00000000000..bab8fd81746 --- /dev/null +++ b/source/blender/blenlib/intern/timeit.cc @@ -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. + */ + +#include "BLI_timeit.hh" + +namespace BLI { +namespace Timeit { + +void print_duration(Nanoseconds duration) +{ + if (duration < std::chrono::microseconds(100)) { + std::cout << duration.count() << " ns"; + } + else if (duration < std::chrono::seconds(5)) { + std::cout << duration.count() / 1.0e6 << " ms"; + } + else { + std::cout << duration.count() / 1.0e9 << " s"; + } +} + +} // namespace Timeit +} // namespace BLI diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 450d3fc2371..1555b9231ed 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -53,6 +53,7 @@ set(SRC intern/versioning_260.c intern/versioning_270.c intern/versioning_280.c + intern/versioning_290.c intern/versioning_cycles.c intern/versioning_defaults.c intern/versioning_dna.c diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cb567147224..7a63c2699f3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -86,6 +86,7 @@ #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" @@ -117,7 +118,7 @@ #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_fluid.h" #include "BKE_global.h" // for G #include "BKE_gpencil_modifier.h" @@ -146,6 +147,7 @@ #include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_shader_fx.h" +#include "BKE_simulation.h" #include "BKE_sound.h" #include "BKE_volume.h" #include "BKE_workspace.h" @@ -2999,6 +3001,19 @@ static void direct_link_brush(FileData *fd, Brush *brush) brush->gpencil_settings->curve_strength); brush->gpencil_settings->curve_jitter = newdataadr(fd, brush->gpencil_settings->curve_jitter); + brush->gpencil_settings->curve_rand_pressure = newdataadr( + fd, brush->gpencil_settings->curve_rand_pressure); + brush->gpencil_settings->curve_rand_strength = newdataadr( + fd, brush->gpencil_settings->curve_rand_strength); + brush->gpencil_settings->curve_rand_uv = newdataadr(fd, + brush->gpencil_settings->curve_rand_uv); + brush->gpencil_settings->curve_rand_hue = newdataadr(fd, + brush->gpencil_settings->curve_rand_hue); + brush->gpencil_settings->curve_rand_saturation = newdataadr( + fd, brush->gpencil_settings->curve_rand_saturation); + brush->gpencil_settings->curve_rand_value = newdataadr( + fd, brush->gpencil_settings->curve_rand_value); + if (brush->gpencil_settings->curve_sensitivity) { direct_link_curvemapping(fd, brush->gpencil_settings->curve_sensitivity); } @@ -3010,6 +3025,30 @@ static void direct_link_brush(FileData *fd, Brush *brush) if (brush->gpencil_settings->curve_jitter) { direct_link_curvemapping(fd, brush->gpencil_settings->curve_jitter); } + + if (brush->gpencil_settings->curve_rand_pressure) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_pressure); + } + + if (brush->gpencil_settings->curve_rand_strength) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_strength); + } + + if (brush->gpencil_settings->curve_rand_uv) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_uv); + } + + if (brush->gpencil_settings->curve_rand_hue) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_hue); + } + + if (brush->gpencil_settings->curve_rand_saturation) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_saturation); + } + + if (brush->gpencil_settings->curve_rand_value) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_value); + } } brush->preview = NULL; @@ -3600,6 +3639,45 @@ static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook /** \name Read ID: Node Tree * \{ */ +static void lib_link_node_socket(FileData *fd, Library *lib, bNodeSocket *sock) +{ + IDP_LibLinkProperty(sock->prop, fd); + + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + default_value->value = newlibadr(fd, lib, default_value->value); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + default_value->value = newlibadr(fd, lib, default_value->value); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + +static void lib_link_node_sockets(FileData *fd, Library *lib, ListBase *sockets) +{ + LISTBASE_FOREACH (bNodeSocket *, sock, sockets) { + lib_link_node_socket(fd, lib, sock); + } +} + /* Single node tree (also used for material/scene trees), ntree is not NULL */ static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree) { @@ -3614,20 +3692,12 @@ static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree) node->id = newlibadr(fd, lib, node->id); - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - IDP_LibLinkProperty(sock->prop, fd); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { - IDP_LibLinkProperty(sock->prop, fd); - } + lib_link_node_sockets(fd, lib, &node->inputs); + lib_link_node_sockets(fd, lib, &node->outputs); } - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { - IDP_LibLinkProperty(sock->prop, fd); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { - IDP_LibLinkProperty(sock->prop, fd); - } + lib_link_node_sockets(fd, lib, &ntree->inputs); + lib_link_node_sockets(fd, lib, &ntree->outputs); /* Set node->typeinfo pointers. This is done in lib linking, after the * first versioning that can change types still without functions that @@ -4779,7 +4849,7 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase /* particle modifier must be removed before particle system */ ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); BLI_remlink(&ob->modifiers, psmd); - modifier_free((ModifierData *)psmd); + BKE_modifier_free((ModifierData *)psmd); BLI_remlink(particles, psys); MEM_freeN(psys); @@ -5148,7 +5218,7 @@ static void lib_link_modifiers_common(void *userData, Object *ob, ID **idpoin, i static void lib_link_modifiers(FileData *fd, Object *ob) { - modifiers_foreachIDLink(ob, lib_link_modifiers_common, fd); + BKE_modifiers_foreach_ID_link(ob, lib_link_modifiers_common, fd); /* If linking from a library, clear 'local' library override flag. */ if (ob->id.lib != NULL) { @@ -5160,7 +5230,7 @@ static void lib_link_modifiers(FileData *fd, Object *ob) static void lib_link_gpencil_modifiers(FileData *fd, Object *ob) { - BKE_gpencil_modifiers_foreachIDLink(ob, lib_link_modifiers_common, fd); + BKE_gpencil_modifiers_foreach_ID_link(ob, lib_link_modifiers_common, fd); /* If linking from a library, clear 'local' library override flag. */ if (ob->id.lib != NULL) { @@ -5173,7 +5243,7 @@ static void lib_link_gpencil_modifiers(FileData *fd, Object *ob) static void lib_link_shaderfxs(FileData *fd, Object *ob) { - BKE_shaderfx_foreachIDLink(ob, lib_link_modifiers_common, fd); + BKE_shaderfx_foreach_ID_link(ob, lib_link_modifiers_common, fd); /* If linking from a library, clear 'local' library override flag. */ if (ob->id.lib != NULL) { @@ -5300,7 +5370,7 @@ static void lib_link_object(FileData *fd, Main *bmain, Object *ob) } { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Fluidsim); if (fluidmd && fluidmd->fss) { @@ -5310,7 +5380,8 @@ static void lib_link_object(FileData *fd, Main *bmain, Object *ob) } { - FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + FluidModifierData *mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, + eModifierType_Fluid); if (mmd && (mmd->type == MOD_FLUID_TYPE_DOMAIN) && mmd->domain) { /* Flag for refreshing the simulation after loading */ @@ -5452,7 +5523,7 @@ static ModifierData *modifier_replace_with_fluid(FileData *fd, ListBase *modifiers, ModifierData *old_modifier_data) { - ModifierData *new_modifier_data = modifier_new(eModifierType_Fluid); + ModifierData *new_modifier_data = BKE_modifier_new(eModifierType_Fluid); FluidModifierData *fluid_modifier_data = (FluidModifierData *)new_modifier_data; if (old_modifier_data->type == eModifierType_Fluidsim) { @@ -5575,7 +5646,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb, Object *ob) is_allocated = true; } /* if modifiers disappear, or for upward compatibility */ - if (NULL == modifierType_getInfo(md->type)) { + if (NULL == BKE_modifier_get_info(md->type)) { md->type = eModifierType_None; } @@ -5929,7 +6000,7 @@ static void direct_link_gpencil_modifiers(FileData *fd, ListBase *lb) md->error = NULL; /* if modifiers disappear, or for upward compatibility */ - if (NULL == BKE_gpencil_modifierType_getInfo(md->type)) { + if (NULL == BKE_gpencil_modifier_get_info(md->type)) { md->type = eModifierType_None; } @@ -6010,7 +6081,7 @@ static void direct_link_shaderfxs(FileData *fd, ListBase *lb) fx->error = NULL; /* if shader disappear, or for upward compatibility */ - if (NULL == BKE_shaderfxType_getInfo(fx->type)) { + if (NULL == BKE_shaderfx_get_info(fx->type)) { fx->type = eShaderFxType_None; } } @@ -6073,7 +6144,7 @@ static void direct_link_object(FileData *fd, Object *ob) if (paf->type == EFF_WAVE) { WaveEff *wav = (WaveEff *)paf; PartEff *next = paf->next; - WaveModifierData *wmd = (WaveModifierData *)modifier_new(eModifierType_Wave); + WaveModifierData *wmd = (WaveModifierData *)BKE_modifier_new(eModifierType_Wave); wmd->damp = wav->damp; wmd->flag = wav->flag; @@ -6097,7 +6168,7 @@ static void direct_link_object(FileData *fd, Object *ob) if (paf->type == EFF_BUILD) { BuildEff *baf = (BuildEff *)paf; PartEff *next = paf->next; - BuildModifierData *bmd = (BuildModifierData *)modifier_new(eModifierType_Build); + BuildModifierData *bmd = (BuildModifierData *)BKE_modifier_new(eModifierType_Build); bmd->start = baf->sfra; bmd->length = baf->len; @@ -6174,7 +6245,7 @@ static void direct_link_object(FileData *fd, Object *ob) link_list(fd, &ob->hooks); while (ob->hooks.first) { ObHook *hook = ob->hooks.first; - HookModifierData *hmd = (HookModifierData *)modifier_new(eModifierType_Hook); + HookModifierData *hmd = (HookModifierData *)BKE_modifier_new(eModifierType_Hook); hook->indexar = newdataadr(fd, hook->indexar); if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { @@ -6196,7 +6267,7 @@ static void direct_link_object(FileData *fd, Object *ob) BLI_addhead(&ob->modifiers, hmd); BLI_remlink(&ob->hooks, hook); - modifier_unique_name(&ob->modifiers, (ModifierData *)hmd); + BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)hmd); MEM_freeN(hook); } @@ -9147,6 +9218,24 @@ static void direct_link_volume(FileData *fd, Volume *volume) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Read ID: Simulation + * \{ */ + +static void lib_link_simulation(FileData *UNUSED(fd), + Main *UNUSED(main), + Simulation *UNUSED(simulation)) +{ +} + +static void direct_link_simulation(FileData *fd, Simulation *simulation) +{ + simulation->adt = newdataadr(fd, simulation->adt); + direct_link_animdata(fd, simulation->adt); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Read Library Data Block * \{ */ @@ -9264,6 +9353,8 @@ static const char *dataname(short id_code) return "Data from PT"; case ID_VO: return "Data from VO"; + case ID_SIM: + return "Data from SIM"; } return "Data from Lib Block"; } @@ -9415,6 +9506,9 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * case ID_VO: direct_link_volume(fd, (Volume *)id); break; + case ID_SIM: + direct_link_simulation(fd, (Simulation *)id); + break; } return success; @@ -9660,7 +9754,7 @@ static bool read_libblock_undo_restore( * this is only for do_version-like code), but for sake of consistency, and also because * it will tell us which ID is re-used from old Main, and which one is actually new. */ /* Also do not add LIB_TAG_NEED_LINK, those IDs will never be re-liblinked, hence that tag will - * never be cleared, leading to critical issue in link/appemd code. */ + * never be cleared, leading to critical issue in link/append code. */ const int id_tag = tag | LIB_TAG_UNDO_OLD_ID_REUSED; read_libblock_undo_restore_identical(fd, main, id, id_old, id_tag); @@ -9933,6 +10027,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) blo_do_versions_260(fd, lib, main); blo_do_versions_270(fd, lib, main); blo_do_versions_280(fd, lib, main); + blo_do_versions_290(fd, lib, main); blo_do_versions_cycles(fd, lib, main); /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ @@ -10105,6 +10200,9 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_AC: lib_link_action(fd, bmain, (bAction *)id); break; + case ID_SIM: + lib_link_simulation(fd, bmain, (Simulation *)id); + break; case ID_IP: /* XXX deprecated... still needs to be maintained for version patches still. */ lib_link_ipo(fd, bmain, (Ipo *)id); @@ -10956,10 +11054,51 @@ static void expand_key(FileData *fd, Main *mainvar, Key *key) expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system } +static void expand_node_socket(FileData *fd, Main *mainvar, bNodeSocket *sock) +{ + expand_idprops(fd, mainvar, sock->prop); + + if (sock->default_value != NULL) { + + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + expand_doit(fd, mainvar, default_value->value); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + expand_doit(fd, mainvar, default_value->value); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } + } +} + +static void expand_node_sockets(FileData *fd, Main *mainvar, ListBase *sockets) +{ + LISTBASE_FOREACH (bNodeSocket *, sock, sockets) { + expand_node_socket(fd, mainvar, sock); + } +} + static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) { bNode *node; - bNodeSocket *sock; if (ntree->gpd) { expand_doit(fd, mainvar, ntree->gpd); @@ -10972,20 +11111,12 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) expand_idprops(fd, mainvar, node->prop); - for (sock = node->inputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } - for (sock = node->outputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } + expand_node_sockets(fd, mainvar, &node->inputs); + expand_node_sockets(fd, mainvar, &node->outputs); } - for (sock = ntree->inputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } - for (sock = ntree->outputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } + expand_node_sockets(fd, mainvar, &ntree->inputs); + expand_node_sockets(fd, mainvar, &ntree->outputs); } static void expand_texture(FileData *fd, Main *mainvar, Tex *tex) @@ -11171,7 +11302,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) data.fd = fd; data.mainvar = mainvar; - modifiers_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data); + BKE_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, (void *)&data); } /* expand_object_expandModifier() */ @@ -11183,7 +11314,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) data.fd = fd; data.mainvar = mainvar; - BKE_gpencil_modifiers_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data); + BKE_gpencil_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, (void *)&data); } /* expand_object_expandShaderFx() */ @@ -11195,7 +11326,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) data.fd = fd; data.mainvar = mainvar; - BKE_shaderfx_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data); + BKE_shaderfx_foreach_ID_link(ob, expand_object_expandModifiers, (void *)&data); } expand_pose(fd, mainvar, ob->pose); @@ -11536,6 +11667,13 @@ static void expand_volume(FileData *fd, Main *mainvar, Volume *volume) } } +static void expand_simulation(FileData *fd, Main *mainvar, Simulation *simulation) +{ + if (simulation->adt) { + expand_animdata(fd, mainvar, simulation->adt); + } +} + /** * Set the callback func used over all ID data found by \a BLO_expand_main func. * @@ -11665,6 +11803,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_VO: expand_volume(fd, mainvar, (Volume *)id); break; + case ID_SIM: + expand_simulation(fd, mainvar, (Simulation *)id); + break; default: break; } @@ -11801,6 +11942,7 @@ static void add_collections_to_scene(Main *mainvar, /* BKE_object_add(...) messes with the selection. */ Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2); ob->type = OB_EMPTY; + ob->empty_drawsize = U.collection_instance_empty_size; BKE_collection_object_add(bmain, active_collection, ob); Base *base = BKE_view_layer_base_find(view_layer, ob); diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 80f8bfc3f07..55abbe703de 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -199,6 +199,7 @@ void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main * void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *bmain); +void blo_do_versions_290(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Main *bmain); void do_versions_after_linking_250(struct Main *bmain); diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index fe0d2293243..62cda5d8feb 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -514,7 +514,7 @@ static void do_version_mdef_250(Main *main) mmd->bindcagecos = mmd->bindcos; mmd->bindcos = NULL; - modifier_mdef_compact_influences(md); + BKE_modifier_mdef_compact_influences(md); } } } @@ -871,7 +871,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) for (ob = bmain->objects.first; ob; ob = ob->id.next) { /* fluid-sim stuff */ - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Fluidsim); if (fluidmd) { fluidmd->fss->fmd = fluidmd; @@ -918,8 +918,8 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) if (do_gravity) { for (md = ob->modifiers.first; md; md = md->next) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, - eModifierType_Cloth); + ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type( + ob, eModifierType_Cloth); if (clmd) { clmd->sim_parms->effector_weights->global_gravity = clmd->sim_parms->gravity[2] / -9.81f; @@ -1154,7 +1154,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) } for (ob = bmain->objects.first; ob; ob = ob->id.next) { - MultiresModifierData *mmd = (MultiresModifierData *)modifiers_findByType( + MultiresModifierData *mmd = (MultiresModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Multires); if (mmd) { @@ -1625,7 +1625,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) ArmatureModifierData *amd; bArmature *arm = (bArmature *)blo_do_versions_newlibadr(fd, lib, parent->data); - amd = (ArmatureModifierData *)modifier_new(eModifierType_Armature); + amd = (ArmatureModifierData *)BKE_modifier_new(eModifierType_Armature); amd->object = ob->parent; BLI_addtail((ListBase *)&ob->modifiers, amd); amd->deformflag = arm->deformflag; @@ -1634,7 +1634,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) else if (parent->type == OB_LATTICE && ob->partype == PARSKEL) { LatticeModifierData *lmd; - lmd = (LatticeModifierData *)modifier_new(eModifierType_Lattice); + lmd = (LatticeModifierData *)BKE_modifier_new(eModifierType_Lattice); lmd->object = ob->parent; BLI_addtail((ListBase *)&ob->modifiers, lmd); ob->partype = PAROBJECT; @@ -1642,7 +1642,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) else if (parent->type == OB_CURVE && ob->partype == PARCURVE) { CurveModifierData *cmd; - cmd = (CurveModifierData *)modifier_new(eModifierType_Curve); + cmd = (CurveModifierData *)BKE_modifier_new(eModifierType_Curve); cmd->object = ob->parent; BLI_addtail((ListBase *)&ob->modifiers, cmd); ob->partype = PAROBJECT; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 98d2acbd938..0ca6fd34535 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -55,7 +55,7 @@ #include "BKE_anim_data.h" #include "BKE_animsys.h" #include "BKE_colortools.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_modifier.h" @@ -841,7 +841,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) for (ob = bmain->objects.first; ob != NULL; ob = ob->id.next) { ModifierData *md; for (md = ob->modifiers.last; md != NULL; md = md->prev) { - if (modifier_unique_name(&ob->modifiers, md)) { + if (BKE_modifier_unique_name(&ob->modifiers, md)) { printf( "Warning: Object '%s' had several modifiers with the " "same name, renamed one of them to '%s'.\n", diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index ff3909f5e1a..4261682a17c 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -75,6 +75,7 @@ #include "BKE_curveprofile.h" #include "BKE_customdata.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_freestyle.h" #include "BKE_global.h" #include "BKE_gpencil.h" @@ -1749,6 +1750,144 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } } + if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) { + /* Patch old grease pencil modifiers material filter. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) { + switch (md->type) { + case eGpencilModifierType_Array: { + ArrayGpencilModifierData *gpmd = (ArrayGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Color: { + ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Hook: { + HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Lattice: { + LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Mirror: { + MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Multiply: { + MultiplyGpencilModifierData *gpmd = (MultiplyGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Noise: { + NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Offset: { + OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Opacity: { + OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Simplify: { + SimplifyGpencilModifierData *gpmd = (SimplifyGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Smooth: { + SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Subdiv: { + SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Texture: { + TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Thick: { + ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + default: + break; + } + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -4647,6 +4786,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) brush->gpencil_weight_tool = brush->gpencil_settings->brush_type; } } + /* Tint brush. */ + Brush *brush = BLI_findstring(&bmain->brushes, "Tint", offsetof(ID, name) + 2); + if (brush == NULL) { + brush = BKE_brush_add(bmain, "Tint", OB_MODE_PAINT_GPENCIL); + BKE_brush_init_gpencil_settings(brush); + } + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TINT); BKE_paint_toolslots_init_from_main(bmain); } diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c new file mode 100644 index 00000000000..40f6689e43b --- /dev/null +++ b/source/blender/blenloader/intern/versioning_290.c @@ -0,0 +1,87 @@ +/* + * 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 blenloader + */ +/* allow readfile to use deprecated functionality */ +#define DNA_DEPRECATED_ALLOW + +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "DNA_brush_types.h" +#include "DNA_genfile.h" +#include "DNA_screen_types.h" + +#include "BKE_collection.h" +#include "BKE_colortools.h" +#include "BKE_main.h" + +#include "BLO_readfile.h" +#include "readfile.h" + +/* Make preferences read-only, use versioning_userdef.c. */ +#define U (*((const UserDef *)&U)) + +void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) +{ + UNUSED_VARS(fd); + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ + + if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "float", "uv_opacity")) { + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + sima->uv_opacity = 1.0f; + } + } + } + } + } + + /* Init Grease Pencil new random curves. */ + if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "random_hue")) { + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if ((brush->gpencil_settings) && (brush->gpencil_settings->curve_rand_pressure == NULL)) { + brush->gpencil_settings->curve_rand_pressure = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_strength = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_uv = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_hue = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_saturation = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_value = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + } + } + } + } +} diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 9309a529ccf..fb1cda2ff31 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -197,6 +197,7 @@ static void blo_update_defaults_screen(bScreen *screen, v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; /* Remove dither pattern in wireframe mode. */ v3d->shading.xray_alpha_wire = 0.0f; + v3d->clip_start = 0.01f; /* Skip startups that use the viewport color by default. */ if (v3d->shading.background_type != V3D_SHADING_BACKGROUND_VIEWPORT) { copy_v3_fl(v3d->shading.background_color, 0.05f); @@ -297,7 +298,7 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) /* Don't enable compositing nodes. */ if (scene->nodetree) { - ntreeFreeNestedTree(scene->nodetree); + ntreeFreeEmbeddedTree(scene->nodetree); MEM_freeN(scene->nodetree); scene->nodetree = NULL; scene->use_nodes = false; diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index ce039182572..2cc811e213f 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1351,7 +1351,8 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) }; if ((me->flag & ME_SUBSURF)) { - SubsurfModifierData *smd = (SubsurfModifierData *)modifier_new(eModifierType_Subsurf); + SubsurfModifierData *smd = (SubsurfModifierData *)BKE_modifier_new( + eModifierType_Subsurf); smd->levels = MAX2(1, me->subdiv); smd->renderLevels = MAX2(1, me->subdivr); @@ -1371,7 +1372,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) BLI_addtail(&ob->modifiers, smd); - modifier_unique_name(&ob->modifiers, (ModifierData *)smd); + BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)smd); } } @@ -1428,18 +1429,19 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } } - if ((ob->softflag & OB_SB_ENABLE) && !modifiers_findByType(ob, eModifierType_Softbody)) { + if ((ob->softflag & OB_SB_ENABLE) && + !BKE_modifiers_findby_type(ob, eModifierType_Softbody)) { if (ob->softflag & OB_SB_POSTDEF) { md = ob->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } - BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(eModifierType_Softbody)); + BLI_insertlinkbefore(&ob->modifiers, md, BKE_modifier_new(eModifierType_Softbody)); } else { - BLI_addhead(&ob->modifiers, modifier_new(eModifierType_Softbody)); + BLI_addhead(&ob->modifiers, BKE_modifier_new(eModifierType_Softbody)); } ob->softflag &= ~OB_SB_ENABLE; @@ -2271,7 +2273,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) BLI_addtail(&ob->particlesystem, psys); - md = modifier_new(eModifierType_ParticleSystem); + md = BKE_modifier_new(eModifierType_ParticleSystem); BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", @@ -2357,7 +2359,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Fluidsim); if (fluidmd && fluidmd->fss && fluidmd->fss->type == OB_FLUIDSIM_PARTICLE) { part->type = PART_FLUID; @@ -2483,7 +2485,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) for (ob = bmain->objects.first; ob; ob = ob->id.next) { if (ob->fluidsimSettings) { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifier_new( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifier_new( eModifierType_Fluidsim); BLI_addhead(&ob->modifiers, (ModifierData *)fluidmd); diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index a426e49dd77..1b0e41ec54a 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -764,6 +764,10 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef) */ { /* Keep this block, even when empty. */ + + if (userdef->collection_instance_empty_size == 0) { + userdef->collection_instance_empty_size = 1.0f; + } } if (userdef->pixelsize == 0.0f) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 2b32621eb37..a54085b3036 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -133,6 +133,7 @@ #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" @@ -156,6 +157,7 @@ #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" // for G #include "BKE_gpencil_modifier.h" #include "BKE_idtype.h" @@ -990,9 +992,19 @@ static void write_node_socket_default_value(WriteData *wd, bNodeSocket *sock) case SOCK_STRING: writestruct(wd, DATA, bNodeSocketValueString, 1, sock->default_value); break; + case SOCK_OBJECT: + writestruct(wd, DATA, bNodeSocketValueObject, 1, sock->default_value); + break; + case SOCK_IMAGE: + writestruct(wd, DATA, bNodeSocketValueImage, 1, sock->default_value); + break; case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: BLI_assert(false); break; } @@ -1634,7 +1646,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) } for (md = modbase->first; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti == NULL) { return; } @@ -1817,7 +1829,7 @@ static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase) } for (md = modbase->first; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti == NULL) { return; } @@ -1884,7 +1896,7 @@ static void write_shaderfxs(WriteData *wd, ListBase *fxbase) } for (fx = fxbase->first; fx; fx = fx->next) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if (fxi == NULL) { return; } @@ -3303,6 +3315,24 @@ static void write_brush(WriteData *wd, Brush *brush, const void *id_address) if (brush->gpencil_settings->curve_jitter) { write_curvemapping(wd, brush->gpencil_settings->curve_jitter); } + if (brush->gpencil_settings->curve_rand_pressure) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_pressure); + } + if (brush->gpencil_settings->curve_rand_strength) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_strength); + } + if (brush->gpencil_settings->curve_rand_uv) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_uv); + } + if (brush->gpencil_settings->curve_rand_hue) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_hue); + } + if (brush->gpencil_settings->curve_rand_saturation) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_saturation); + } + if (brush->gpencil_settings->curve_rand_value) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_value); + } } if (brush->gradient) { writestruct(wd, DATA, ColorBand, 1, brush->gradient); @@ -3854,6 +3884,24 @@ static void write_volume(WriteData *wd, Volume *volume, const void *id_address) } } +static void write_simulation(WriteData *wd, Simulation *simulation) +{ + if (simulation->id.us > 0 || wd->use_memfile) { + writestruct(wd, ID_SIM, Simulation, 1, simulation); + write_iddata(wd, &simulation->id); + + if (simulation->adt) { + write_animdata(wd, simulation->adt); + } + + /* nodetree is integral part of simulation, no libdata */ + if (simulation->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, simulation->nodetree); + write_nodetree_nolib(wd, simulation->nodetree); + } + } +} + /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { @@ -4203,6 +4251,9 @@ static bool write_file_handle(Main *mainvar, case ID_VO: write_volume(wd, (Volume *)id_buffer, id); break; + case ID_SIM: + write_simulation(wd, (Simulation *)id); + break; case ID_LI: /* Do nothing, handled below - and should never be reached. */ BLI_assert(0); diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h index 74c46b1cf3e..817b99e8b91 100644 --- a/source/blender/blentranslation/BLT_translation.h +++ b/source/blender/blentranslation/BLT_translation.h @@ -65,9 +65,9 @@ bool BLT_lang_is_ime_supported(void); # define IFACE_(msgid) msgid # define TIP_(msgid) msgid # define DATA_(msgid) msgid -# define CTX_IFACE_(context, msgid) msgid -# define CTX_TIP_(context, msgid) msgid -# define CTX_DATA_(context, msgid) msgid +# define CTX_IFACE_(context, msgid) ((void)(0 ? (context) : 0), msgid) +# define CTX_TIP_(context, msgid) ((void)(0 ? (context) : 0), msgid) +# define CTX_DATA_(context, msgid) ((void)(0 ? (context) : 0), msgid) #endif /* Helper macro, when we want to define a same msgid for multiple msgctxt... @@ -122,6 +122,7 @@ bool BLT_lang_is_ime_supported(void); #define BLT_I18NCONTEXT_ID_IMAGE "Image" /*#define BLT_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */ #define BLT_I18NCONTEXT_ID_SHAPEKEY "Key" +#define BLT_I18NCONTEXT_ID_SIMULATION "Simulation" #define BLT_I18NCONTEXT_ID_LIGHT "Light" #define BLT_I18NCONTEXT_ID_LIBRARY "Library" #define BLT_I18NCONTEXT_ID_LATTICE "Lattice" @@ -202,6 +203,7 @@ typedef struct { BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCENE, "id_scene"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCREEN, "id_screen"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \ + BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SIMULATION, "id_simulation"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SPEAKER, "id_speaker"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SOUND, "id_sound"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXTURE, "id_texture"), \ diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 7d2100c0f65..9b5072e8e16 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -188,10 +188,6 @@ * - Use two different iterator types for BMO map/buffer types. */ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_customdata_types.h" /* BMesh struct in bmesh_class.h uses */ #include "DNA_listBase.h" /* selection history uses */ @@ -199,6 +195,10 @@ extern "C" { #include <stdio.h> #include <stdlib.h> +#ifdef __cplusplus +extern "C" { +#endif + #include "bmesh_class.h" /* include the rest of the API */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 14e3c57f038..255a52971bb 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1047,6 +1047,7 @@ static BMOpDefine bmo_extrude_face_region_def = { {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */ + {"use_dissolve_ortho_edges", BMO_OP_SLOT_BOOL}, /* Dissolve edges whose faces form a flat surface. */ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index dbd2bf076c6..5af812d1b1d 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -21,14 +21,14 @@ * \ingroup bmesh */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_ghash.h" #include <stdarg.h> +#ifdef __cplusplus +extern "C" { +#endif + /** * operators represent logical, executable mesh modules. all topological * operations involving a bmesh has to go through them. diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 7a7f4a14db3..3c63f4a60d6 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -39,6 +39,7 @@ enum { EXT_INPUT = 1, EXT_KEEP = 2, EXT_DEL = 4, + EXT_TAG = 8, }; #define VERT_MARK 1 @@ -335,6 +336,8 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in, "use_normal_from_adjacent"); + const bool use_dissolve_ortho_edges = BMO_slot_bool_get(op->slots_in, + "use_dissolve_ortho_edges"); /* initialize our sub-operators */ BMO_op_initf(bm, @@ -442,6 +445,24 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } + BMVert **dissolve_verts = NULL; + int dissolve_verts_len = 0; + float average_normal[3]; + if (use_dissolve_ortho_edges) { + /* Calc average normal. */ + zero_v3(average_normal); + BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) { + add_v3_v3(average_normal, f->no); + } + if (normalize_v3(average_normal) == 0.0f) { + average_normal[2] = 1.0f; + } + + /* Allocate array to store possible vertices that will be dissolved. */ + int boundary_verts_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out"); + dissolve_verts = MEM_mallocN((size_t)boundary_verts_len * sizeof(*dissolve_verts), __func__); + } + BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out"); slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); @@ -483,6 +504,16 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } + BMFace *join_face = NULL; + if (use_dissolve_ortho_edges) { + if (BM_edge_is_boundary(e)) { + join_face = e->l->f; + if (fabs(dot_v3v3(average_normal, join_face->no)) > 0.0001f) { + join_face = NULL; + } + } + } + bool edge_normal_flip; if (use_normal_from_adjacent == false) { /* Orient loop to give same normal as a loop of 'e_new' @@ -541,7 +572,22 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); #endif - bm_extrude_copy_face_loop_attributes(bm, f); + if (join_face) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + if (!BMO_elem_flag_test(bm, v1, EXT_TAG)) { + BMO_elem_flag_enable(bm, v1, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v1; + } + if (!BMO_elem_flag_test(bm, v2, EXT_TAG)) { + BMO_elem_flag_enable(bm, v2, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v2; + } + bmesh_kernel_join_face_kill_edge(bm, join_face, f, e); + } + else { + bm_extrude_copy_face_loop_attributes(bm, f); + } } /* link isolated vert */ @@ -559,6 +605,23 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE); } + if (dissolve_verts) { + BMVert **v_iter = &dissolve_verts[0]; + for (int i = dissolve_verts_len; i--; v_iter++) { + v = *v_iter; + e = v->e; + BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); + if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) { + /* Lose edge or BMVert is edge pair. */ + BM_edge_collapse(bm, e, v, true, false); + } + else { + BLI_assert(!BM_vert_is_edge_pair(v)); + } + } + MEM_freeN(dissolve_verts); + } + /* cleanup */ if (delorig) { BMO_op_finish(bm, &delop); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index bc127243836..d1ddceb00b0 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -997,10 +997,10 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, * record the change in offset_l (or offset_r); later we can tell that a change has happened * because the offset will differ from its original value in offset_l_spec (or offset_r_spec). * - * \param edges_between If this is true, there are edges between e1 and e2 in CCW order so they + * \param edges_between: If this is true, there are edges between e1 and e2 in CCW order so they * don't share a common face. We want the meeting point to be on an existing face so it * should be dropped onto one of the intermediate faces, if possible. - * \param e_in_plane If we need to drop from the calculated offset lines to one of the faces, + * \param e_in_plane: If we need to drop from the calculated offset lines to one of the faces, * we don't want to drop onto the 'in plane' face, so if this is not null skip this edge's faces. */ static void offset_meet(EdgeHalf *e1, @@ -2601,13 +2601,13 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em * to be a subsequent pass to make the widths as consistent as possible. * Doesn't make the actual BMVerts. * - * For a width consistency pass, we just recalculate the coordinates of the BoundVerts. If the + * For a width consistency pass, we just recalculate the coordinates of the #BoundVerts. If the * other ends have been (re)built already, then we copy the offsets from there to match, else we * use the ideal (user-specified) widths. * - * \param construct The first time through, construct will be true and we are making the BoundVerts - * and setting up the BoundVert and EdgeHalf pointers appropriately. Also, if construct, decide on - * the mesh pattern that will be used inside the boundary. + * \param construct: The first time through, construct will be true and we are making the + * #BoundVerts and setting up the #BoundVert and #EdgeHalf pointers appropriately. + * Also, if construct, decide on the mesh pattern that will be used inside the boundary. */ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) { diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 479a8a3f6d6..8562e584ec9 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -47,4 +47,5 @@ void BM_mesh_bevel(BMesh *bm, const bool use_custom_profile, const struct CurveProfile *custom_profile, const int vmesh_method); + #endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_intersect_edges.c b/source/blender/bmesh/tools/bmesh_intersect_edges.c index e2d03a65d46..3f0492aebb6 100644 --- a/source/blender/bmesh/tools/bmesh_intersect_edges.c +++ b/source/blender/bmesh/tools/bmesh_intersect_edges.c @@ -893,7 +893,7 @@ bool BM_mesh_intersect_edges( if (BM_vert_pair_share_face_check(va, va_dest)) { /* Vert par acts on the same face. - * Although there are cases like this where the face can be splitted, + * Although there are cases like this where the face can be split, * for efficiency it is better to ignore then. */ continue; } @@ -909,7 +909,7 @@ bool BM_mesh_intersect_edges( if (BM_vert_pair_share_face_check(v_other, v_other_dest)) { /* Vert par acts on the same face. - * Although there are cases like this where the face can be splitted, + * Although there are cases like this where the face can be split, * for efficiency and to avoid complications, it is better to ignore these cases. */ break; diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index 55f68f2b5c1..a24904551c6 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -19,13 +19,13 @@ #ifndef __COM_COMPOSITOR_H__ #define __COM_COMPOSITOR_H__ +#include "DNA_color_types.h" +#include "DNA_node_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_color_types.h" -#include "DNA_node_types.h" - /* Keep ascii art. */ /* clang-format off */ /** @@ -295,8 +295,6 @@ extern "C" { * * \section executePixel executing a pixel * Finally the last step, the node functionality :) - * - * \page newnode Creating new nodes */ /** diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index e8474ba8318..edfeb3a3a04 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -18,11 +18,9 @@ #include <string.h> -extern "C" { #include "DNA_node_types.h" #include "BKE_node.h" -} #include "COM_NodeOperation.h" #include "COM_NodeOperationBuilder.h" diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index fa40f150335..34682aae2fd 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -20,9 +20,8 @@ #include "BLI_utildefines.h" #include "PIL_time.h" -extern "C" { + #include "BKE_node.h" -} #include "BLT_translation.h" diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index 7e5b0264aa3..6ba8f144482 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -25,10 +25,8 @@ class MemoryBuffer; #include "COM_MemoryProxy.h" #include "COM_SocketReader.h" -extern "C" { #include "BLI_math.h" #include "BLI_rect.h" -} /** * \brief state of a memory buffer diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index df5a8e690d3..31535c5851f 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -18,11 +18,9 @@ #include <string.h> -extern "C" { #include "BKE_node.h" #include "RNA_access.h" -} #include "COM_ExecutionSystem.h" #include "COM_NodeOperation.h" diff --git a/source/blender/compositor/intern/COM_NodeConverter.cpp b/source/blender/compositor/intern/COM_NodeConverter.cpp index eff825b075d..2db31bd4133 100644 --- a/source/blender/compositor/intern/COM_NodeConverter.cpp +++ b/source/blender/compositor/intern/COM_NodeConverter.cpp @@ -16,9 +16,7 @@ * Copyright 2013, Blender Foundation. */ -extern "C" { #include "BLI_utildefines.h" -} #include "COM_Debug.h" diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp index 6640f144518..cb27fa21b4d 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.cpp +++ b/source/blender/compositor/intern/COM_NodeGraph.cpp @@ -18,14 +18,12 @@ #include <cstring> -extern "C" { #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "DNA_node_types.h" #include "BKE_node.h" -} #include "COM_CompositorContext.h" #include "COM_Converter.h" diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h index b005149c839..531832c2c65 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.h +++ b/source/blender/compositor/intern/COM_NodeGraph.h @@ -23,9 +23,7 @@ #include <set> #include <vector> -extern "C" { #include "DNA_node_types.h" -} #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index b2c4961ca35..07f482f9e5f 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -23,11 +23,9 @@ #include <sstream> #include <string> -extern "C" { #include "BLI_math_color.h" #include "BLI_math_vector.h" #include "BLI_threads.h" -} #include "COM_MemoryBuffer.h" #include "COM_MemoryProxy.h" diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index 9f6b91915e0..5ce6ca34b34 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -16,9 +16,7 @@ * Copyright 2013, Blender Foundation. */ -extern "C" { #include "BLI_utildefines.h" -} #include "COM_Converter.h" #include "COM_Debug.h" diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h index 5e0675f1833..3a1b4c533bd 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.h +++ b/source/blender/compositor/intern/COM_WorkScheduler.h @@ -20,9 +20,9 @@ #define __COM_WORKSCHEDULER_H__ #include "COM_ExecutionGroup.h" -extern "C" { + #include "BLI_threads.h" -} + #include "COM_Device.h" #include "COM_WorkPackage.h" #include "COM_defines.h" diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index 1793abae134..bccdd026ead 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -16,13 +16,11 @@ * Copyright 2011, Blender Foundation. */ -extern "C" { -#include "BKE_node.h" #include "BLI_threads.h" -} #include "BLT_translation.h" +#include "BKE_node.h" #include "BKE_scene.h" #include "COM_ExecutionSystem.h" diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.h b/source/blender/compositor/nodes/COM_CornerPinNode.h index ea62dea12de..a8e88a0ef4f 100644 --- a/source/blender/compositor/nodes/COM_CornerPinNode.h +++ b/source/blender/compositor/nodes/COM_CornerPinNode.h @@ -20,9 +20,7 @@ #include "COM_Node.h" -extern "C" { #include "DNA_node_types.h" -} /** * \brief CornerPinNode diff --git a/source/blender/compositor/nodes/COM_ImageNode.h b/source/blender/compositor/nodes/COM_ImageNode.h index 6ed9acd58b8..7883f4d7ab3 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.h +++ b/source/blender/compositor/nodes/COM_ImageNode.h @@ -23,9 +23,8 @@ #include "COM_defines.h" #include "DNA_image_types.h" #include "DNA_node_types.h" -extern "C" { + #include "RE_engine.h" -} /** * \brief ImageNode diff --git a/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp b/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp index 6a005b2b712..93a9a071226 100644 --- a/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp @@ -20,9 +20,7 @@ #include "COM_ExecutionSystem.h" #include "COM_KeyingScreenOperation.h" -extern "C" { #include "DNA_movieclip_types.h" -} KeyingScreenNode::KeyingScreenNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_MaskNode.cpp b/source/blender/compositor/nodes/COM_MaskNode.cpp index cceeef6b437..b28b849521c 100644 --- a/source/blender/compositor/nodes/COM_MaskNode.cpp +++ b/source/blender/compositor/nodes/COM_MaskNode.cpp @@ -20,9 +20,7 @@ #include "COM_ExecutionSystem.h" #include "COM_MaskOperation.h" -extern "C" { #include "DNA_mask_types.h" -} MaskNode::MaskNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp index 29fd47f33b3..3366a8c20d6 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp @@ -22,12 +22,12 @@ #include "COM_MovieClipOperation.h" #include "COM_SetValueOperation.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_tracking.h" + #include "DNA_movieclip_types.h" + #include "IMB_imbuf.h" -} MovieClipNode::MovieClipNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp index 39616bba4f9..6b9b51631ec 100644 --- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp +++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp @@ -21,11 +21,9 @@ #include "COM_PlaneTrackOperation.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} PlaneTrackDeformNode::PlaneTrackDeformNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h index 6ee73e22af0..2c17739a220 100644 --- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h +++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h @@ -21,10 +21,8 @@ #include "COM_Node.h" -extern "C" { #include "DNA_movieclip_types.h" #include "DNA_node_types.h" -} /** * \brief PlaneTrackDeformNode diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp index 0b6cb97b049..7a308ac47b9 100644 --- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp +++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp @@ -24,10 +24,9 @@ #include "COM_SetSamplerOperation.h" #include "COM_TranslateOperation.h" -extern "C" { #include "BKE_tracking.h" + #include "DNA_movieclip_types.h" -} Stabilize2dNode::Stabilize2dNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_TimeNode.cpp b/source/blender/compositor/nodes/COM_TimeNode.cpp index b6927fb8373..9722ead0716 100644 --- a/source/blender/compositor/nodes/COM_TimeNode.cpp +++ b/source/blender/compositor/nodes/COM_TimeNode.cpp @@ -19,9 +19,9 @@ #include "COM_TimeNode.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" -extern "C" { + #include "BKE_colortools.h" -} + #include "BLI_utildefines.h" TimeNode::TimeNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_TrackPositionNode.cpp b/source/blender/compositor/nodes/COM_TrackPositionNode.cpp index da9f50a590b..52e7f7d832b 100644 --- a/source/blender/compositor/nodes/COM_TrackPositionNode.cpp +++ b/source/blender/compositor/nodes/COM_TrackPositionNode.cpp @@ -22,11 +22,9 @@ #include "COM_ExecutionSystem.h" #include "COM_TrackPositionOperation.h" -extern "C" { #include "DNA_movieclip_types.h" #include "BKE_node.h" -} TrackPositionNode::TrackPositionNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp index de7c43a8751..85725cc1d37 100644 --- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp +++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp @@ -22,9 +22,7 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "RE_render_ext.h" -} /* An implementation of the Scale3X edge-extrapolation algorithm. * diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp index 44cb4056c99..8168867a522 100644 --- a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp @@ -19,9 +19,7 @@ #include "COM_BilateralBlurOperation.h" #include "BLI_math.h" -extern "C" { #include "RE_pipeline.h" -} BilateralBlurOperation::BilateralBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index 24c68ddbec7..ef0f259c592 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} BlurBaseOperation::BlurBaseOperation(DataType data_type) : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp index 4d858934796..c00ef2468c0 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "COM_OpenCLDevice.h" -extern "C" { #include "RE_pipeline.h" -} BokehBlurOperation::BokehBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index 5d01154bbda..ecd61e95f43 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -extern "C" { #include "IMB_colormanagement.h" -} CalculateMeanOperation::CalculateMeanOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp index dfe1a936c9c..059040d6f05 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -extern "C" { #include "IMB_colormanagement.h" -} CalculateStandardDeviationOperation::CalculateStandardDeviationOperation() : CalculateMeanOperation() diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp index 31567398d98..39ffb690328 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp @@ -19,9 +19,7 @@ #include "COM_ColorCorrectionOperation.h" #include "BLI_math.h" -extern "C" { #include "IMB_colormanagement.h" -} ColorCorrectionOperation::ColorCorrectionOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp index 90d3a60abd0..9d514c872f7 100644 --- a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp @@ -18,14 +18,9 @@ #include "COM_ColorCurveOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -# include "MEM_guardedalloc.h" -#endif + +#include "MEM_guardedalloc.h" ColorCurveOperation::ColorCurveOperation() : CurveBaseOperation() { diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.cpp b/source/blender/compositor/operations/COM_ColorRampOperation.cpp index f2c153c5d30..95e0bd2d82b 100644 --- a/source/blender/compositor/operations/COM_ColorRampOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorRampOperation.cpp @@ -18,13 +18,7 @@ #include "COM_ColorRampOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colorband.h" -#ifdef __cplusplus -} -#endif ColorRampOperation::ColorRampOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index cb41071e6f0..71cef9dc4da 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -22,13 +22,14 @@ #include "BLI_listbase.h" #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_threads.h" + #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" + #include "render_types.h" -} + #include "PIL_time.h" CompositorOperation::CompositorOperation() : NodeOperation() diff --git a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp index 59a605a77c9..6a4c5db856c 100644 --- a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp @@ -18,9 +18,8 @@ #include "COM_ConvertColorProfileOperation.h" -extern "C" { #include "IMB_imbuf.h" -} + ConvertColorProfileOperation::ConvertColorProfileOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR); diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp index 6caccb89046..0bd3f5b8796 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp @@ -18,9 +18,7 @@ #include "COM_ConvertOperation.h" -extern "C" { #include "IMB_colormanagement.h" -} ConvertBaseOperation::ConvertBaseOperation() { diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp index 858931ad46d..b18e77cf0e3 100644 --- a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp @@ -18,13 +18,7 @@ #include "COM_CurveBaseOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -#endif CurveBaseOperation::CurveBaseOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp index 1b590c0c392..31eb74fbc42 100644 --- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp @@ -17,11 +17,11 @@ */ #include "COM_DirectionalBlurOperation.h" -#include "BLI_math.h" #include "COM_OpenCLDevice.h" -extern "C" { + +#include "BLI_math.h" + #include "RE_pipeline.h" -} DirectionalBlurOperation::DirectionalBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index c6239dba604..c028a2c0e4c 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(COM_DT_VALUE) { diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index 37109b4a03e..35abe4cd47b 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(COM_DT_VALUE) { diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index 318c182fdff..43e571c4bb7 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -19,9 +19,8 @@ #include "COM_GaussianBokehBlurOperation.h" #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" -} GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 68cde0d365f..32ad0482791 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -21,9 +21,7 @@ #include "COM_OpenCLDevice.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index eeddd98d4a4..3ffa797c0c1 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -21,9 +21,7 @@ #include "COM_OpenCLDevice.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp index 142c51122a1..d050d9b58a9 100644 --- a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp @@ -19,9 +19,7 @@ #include "COM_GlareThresholdOperation.h" #include "BLI_math.h" -extern "C" { #include "IMB_colormanagement.h" -} GlareThresholdOperation::GlareThresholdOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp index fae280249de..8292413f6f1 100644 --- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp @@ -20,13 +20,7 @@ #include "BLI_math.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -#endif HueSaturationValueCorrectOperation::HueSaturationValueCorrectOperation() : CurveBaseOperation() { diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index d70cab4ad2a..38d2fbf9ed4 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -24,14 +24,12 @@ #include "BLI_math.h" #include "DNA_image_types.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} BaseImageOperation::BaseImageOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h index 57656d03092..3e081ee0000 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.h +++ b/source/blender/compositor/operations/COM_ImageOperation.h @@ -24,11 +24,10 @@ #include "BLI_utildefines.h" #include "COM_NodeOperation.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} /** * \brief Base class for all image operations diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index ab9ef0335e0..082091411fb 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -24,13 +24,11 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_tracking.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} KeyingScreenOperation::KeyingScreenOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h index 860a358e79d..593e902117b 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h @@ -28,9 +28,7 @@ #include "BLI_listbase.h" #include "BLI_string.h" -extern "C" { #include "BLI_voronoi_2d.h" -} /** * Class with implementation of green screen gradient rasterization diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp index 30ad954e0bc..936ac00a0e8 100644 --- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp @@ -19,9 +19,7 @@ #include "COM_LuminanceMatteOperation.h" #include "BLI_math.h" -extern "C" { #include "IMB_colormanagement.h" -} LuminanceMatteOperation::LuminanceMatteOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index 88a3a5c535c..bdc954ac081 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -23,9 +23,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" -extern "C" { #include "BKE_mask.h" -} MaskOperation::MaskOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp index 524812ac992..1363b75433a 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp @@ -17,9 +17,8 @@ */ #include "COM_MathBaseOperation.h" -extern "C" { + #include "BLI_math.h" -} MathBaseOperation::MathBaseOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp index 6b8a0caa13b..371da20044f 100644 --- a/source/blender/compositor/operations/COM_MixOperation.cpp +++ b/source/blender/compositor/operations/COM_MixOperation.cpp @@ -18,9 +18,7 @@ #include "COM_MixOperation.h" -extern "C" { #include "BLI_math.h" -} /* ******** Mix Base Operation ******** */ diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp index 4f5d7f6f00b..34773a1e4f8 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp @@ -17,10 +17,10 @@ */ #include "COM_MovieClipAttributeOperation.h" -extern "C" { + #include "BKE_movieclip.h" #include "BKE_tracking.h" -} + MovieClipAttributeOperation::MovieClipAttributeOperation() : NodeOperation() { this->addOutputSocket(COM_DT_VALUE); diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp index c5757274143..17794ae879e 100644 --- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp @@ -20,11 +20,11 @@ #include "BLI_listbase.h" #include "BLI_math.h" -extern "C" { + +#include "BKE_image.h" #include "BKE_movieclip.h" + #include "IMB_imbuf.h" -} -#include "BKE_image.h" MovieClipBaseOperation::MovieClipBaseOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index ec858ee2c19..67491d51547 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -18,11 +18,10 @@ #include "COM_MovieDistortionOperation.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_tracking.h" + #include "BLI_linklist.h" -} MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperation() { @@ -50,7 +49,8 @@ void MovieDistortionOperation::initExecution() full_frame.xmin = full_frame.ymin = 0; full_frame.xmax = this->m_width; full_frame.ymax = this->m_height; - BKE_tracking_max_distortion_delta_across_bound(tracking, &full_frame, !this->m_apply, delta); + BKE_tracking_max_distortion_delta_across_bound( + tracking, this->m_width, this->m_height, &full_frame, !this->m_apply, delta); /* 5 is just in case we didn't hit real max of distortion in * BKE_tracking_max_undistortion_delta_across_bound diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 3ca9fe16b1e..799c6385a10 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -23,9 +23,7 @@ #include "DNA_movieclip_types.h" #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_tracking.h" -} class MovieDistortionOperation : public NodeOperation { private: diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp index 9876c319944..8878b05ade7 100644 --- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp +++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp @@ -17,10 +17,9 @@ */ #include "COM_MultilayerImageOperation.h" -extern "C" { + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view) : BaseImageOperation() { diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp index 65f4eeeb8bb..c0fe7237687 100644 --- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp @@ -33,11 +33,9 @@ #include "DNA_color_types.h" #include "MEM_guardedalloc.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} /************************************ OpenEXR Singlelayer Multiview ******************************/ diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index efe01d0b5cc..ee3779edcb4 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -32,11 +32,9 @@ #include "DNA_color_types.h" #include "MEM_guardedalloc.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} void add_exr_channels(void *exrhandle, const char *layerName, diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp index 676601d82da..eae576ceb56 100644 --- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp @@ -24,9 +24,7 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_node.h" -} static bool check_corners(float corners[4][2]) { diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp index 07053d01d43..e7574e80c2f 100644 --- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp @@ -20,7 +20,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_jitter_2d.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -29,7 +28,6 @@ extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} /* ******** PlaneDistort WarpImage ******** */ diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp index cbf5a25fa31..ed9a776d0a3 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp @@ -25,11 +25,9 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} /* ******** PlaneTrackCommon ******** */ diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp index e9e1b4a8cd9..30fe2ca824d 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.cpp +++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp @@ -27,12 +27,11 @@ #include "PIL_time.h" #include "WM_api.h" #include "WM_types.h" -extern "C" { + #include "BKE_node.h" #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index 722aab329d7..c8a68c70c4d 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -22,11 +22,9 @@ #include "BLI_listbase.h" #include "DNA_scene_types.h" -extern "C" { #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} /* ******** Render Layers Base Prog ******** */ diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index cb47725b749..6f84eae3252 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -24,9 +24,8 @@ #include "COM_NodeOperation.h" #include "DNA_scene_types.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" -} /** * Base class for all renderlayeroperations @@ -56,7 +55,7 @@ class RenderLayersProg : public NodeOperation { float *m_inputBuffer; /** - * renderpass where this operation needs to get its data from + * Render-pass where this operation needs to get its data from. */ std::string m_passName; diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index 1afc6d9477f..738c51fc719 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -18,12 +18,11 @@ #include "COM_ScreenLensDistortionOperation.h" -extern "C" { #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" + #include "PIL_time.h" -} ScreenLensDistortionOperation::ScreenLensDistortionOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_SplitOperation.cpp b/source/blender/compositor/operations/COM_SplitOperation.cpp index 1862fde2d40..3eddf033cf4 100644 --- a/source/blender/compositor/operations/COM_SplitOperation.cpp +++ b/source/blender/compositor/operations/COM_SplitOperation.cpp @@ -24,10 +24,8 @@ #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" -extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} SplitOperation::SplitOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 0a27a6916b7..07316280bbc 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -20,13 +20,11 @@ #include "COM_WorkScheduler.h" #include "BKE_image.h" +#include "BKE_node.h" + #include "BLI_listbase.h" #include "BLI_threads.h" -extern "C" { -#include "BKE_node.h" -} - TextureBaseOperation::TextureBaseOperation() : NodeOperation() { this->addInputSocket(COM_DT_VECTOR); // offset diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index 0d06ac0bc27..ebfdbb6513a 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -23,11 +23,10 @@ #include "COM_NodeOperation.h" #include "DNA_texture_types.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} /** * Base class for all renderlayeroperations diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp index 6b408a0a791..417fe8713ed 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.cpp +++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -extern "C" { #include "IMB_colormanagement.h" -} TonemapOperation::TonemapOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp index e497d58732b..5c4f3b99f58 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp @@ -24,11 +24,9 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} TrackPositionOperation::TrackPositionOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 02f13effc8f..057dc553f7f 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "COM_OpenCLDevice.h" -extern "C" { #include "RE_pipeline.h" -} VariableSizeBokehBlurOperation::VariableSizeBokehBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index 83ae1a0526d..7a34c84827e 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -16,12 +16,13 @@ * Copyright 2011, Blender Foundation. */ -#include "BLI_math.h" -#include "MEM_guardedalloc.h" #include <string.h> -extern "C" { + +#include "MEM_guardedalloc.h" + #include "BLI_jitter_2d.h" -} +#include "BLI_math.h" + #include "COM_VectorBlurOperation.h" /* Defined */ diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp index 6996c7ecb71..61312355a39 100644 --- a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp @@ -18,13 +18,7 @@ #include "COM_VectorCurveOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -#endif VectorCurveOperation::VectorCurveOperation() : CurveBaseOperation() { diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index 5c32b9962f4..fc26d6219e1 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -28,11 +28,9 @@ #include "WM_api.h" #include "WM_types.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} ViewerOperation::ViewerOperation() : NodeOperation() { diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index c94a8876ab0..d735d3b89bc 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -184,7 +184,7 @@ void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, DEG_EditorUpdateSce /* Evaluation ----------------------------------- */ -bool DEG_is_evaluating(struct Depsgraph *depsgraph); +bool DEG_is_evaluating(const struct Depsgraph *depsgraph); bool DEG_is_active(const struct Depsgraph *depsgraph); void DEG_make_active(struct Depsgraph *depsgraph); diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index e24fa9e8996..19e9c5c26b1 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -42,12 +42,12 @@ struct Scene; struct ViewLayer; struct bNodeTree; +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" - /* Graph Building -------------------------------- */ /* Build depsgraph for the given scene, and dump results in given graph container. */ diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index 26b46376a0a..3d570536223 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -111,14 +111,14 @@ struct ID *DEG_get_original_id(struct ID *id); * * Original IDs are considered all the IDs which are not covered by copy-on-write system and are * not out-of-main localized data-blocks. */ -bool DEG_is_original_id(struct ID *id); -bool DEG_is_original_object(struct Object *object); +bool DEG_is_original_id(const struct ID *id); +bool DEG_is_original_object(const struct Object *object); /* Opposite of the above. * * If the data-block is not original it must be evaluated, and vice versa. */ -bool DEG_is_evaluated_id(struct ID *id); -bool DEG_is_evaluated_object(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: * - Relations are up-to-date. diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index d880618753c..82f3ea7d182 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -31,7 +31,6 @@ #include "DNA_layer_types.h" #include "DNA_object_types.h" -#include "BLI_ghash.h" #include "BLI_stack.h" #include "BLI_utildefines.h" @@ -157,10 +156,9 @@ void deg_graph_build_flush_visibility(Depsgraph *graph) BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *), "DEG flush layers stack"); for (IDNode *id_node : graph->id_nodes) { - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { comp_node->affects_directly_visible |= id_node->is_directly_visible; } - GHASH_FOREACH_END(); } for (OperationNode *op_node : graph->operations) { op_node->custom_flags = 0; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index fe1886c67e8..ba0238b43c7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -29,9 +29,7 @@ #include "BLI_utildefines.h" -extern "C" { #include "BKE_animsys.h" -} namespace DEG { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index f6834feeeae..cefe87d1e1f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -34,7 +34,6 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -60,6 +59,7 @@ extern "C" { #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -74,7 +74,7 @@ extern "C" { #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_idprop.h" @@ -104,7 +104,6 @@ extern "C" { #include "RNA_access.h" #include "RNA_types.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -120,20 +119,6 @@ extern "C" { namespace DEG { -namespace { - -void free_copy_on_write_datablock(void *id_info_v) -{ - DepsgraphNodeBuilder::IDInfo *id_info = (DepsgraphNodeBuilder::IDInfo *)id_info_v; - if (id_info->id_cow != nullptr) { - deg_free_copy_on_write_datablock(id_info->id_cow); - MEM_freeN(id_info->id_cow); - } - MEM_freeN(id_info); -} - -} /* namespace */ - /* ************ */ /* Node Builder */ @@ -147,15 +132,18 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, view_layer_(nullptr), view_layer_index_(-1), collection_(nullptr), - is_parent_collection_visible_(true), - id_info_hash_(nullptr) + is_parent_collection_visible_(true) { } DepsgraphNodeBuilder::~DepsgraphNodeBuilder() { - if (id_info_hash_ != nullptr) { - BLI_ghash_free(id_info_hash_, nullptr, free_copy_on_write_datablock); + for (IDInfo *id_info : id_info_hash_.values()) { + if (id_info->id_cow != nullptr) { + deg_free_copy_on_write_datablock(id_info->id_cow); + MEM_freeN(id_info->id_cow); + } + MEM_freeN(id_info); } } @@ -166,7 +154,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) IDComponentsMask previously_visible_components_mask = 0; uint32_t previous_eval_flags = 0; DEGCustomDataMeshMasks previous_customdata_masks; - IDInfo *id_info = (IDInfo *)BLI_ghash_lookup(id_info_hash_, id); + IDInfo *id_info = id_info_hash_.lookup_default(id, nullptr); if (id_info != nullptr) { id_cow = id_info->id_cow; previously_visible_components_mask = id_info->previously_visible_components_mask; @@ -182,7 +170,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) /* Currently all ID nodes are supposed to have copy-on-write logic. * * NOTE: Zero number of components indicates that ID node was just created. */ - if (BLI_ghash_len(id_node->components) == 0) { + if (id_node->components.is_empty()) { ComponentNode *comp_cow = id_node->add_component(NodeType::COPY_ON_WRITE); OperationNode *op_cow = comp_cow->add_operation( function_bind(deg_evaluate_copy_on_write, _1, id_node), @@ -320,7 +308,6 @@ void DepsgraphNodeBuilder::begin_build() { /* Store existing copy-on-write versions of datablock, so we can re-use * them for new ID nodes. */ - id_info_hash_ = BLI_ghash_ptr_new("Depsgraph id hash"); for (IDNode *id_node : graph_->id_nodes) { /* It is possible that the ID does not need to have CoW version in which case id_cow is the * same as id_orig. Additionally, such ID might have been removed, which makes the check @@ -344,11 +331,11 @@ void DepsgraphNodeBuilder::begin_build() id_info->previously_visible_components_mask = id_node->visible_components_mask; id_info->previous_eval_flags = id_node->eval_flags; id_info->previous_customdata_masks = id_node->customdata_masks; - BLI_ghash_insert(id_info_hash_, id_node->id_orig, id_info); + id_info_hash_.add_new(id_node->id_orig, id_info); id_node->id_cow = nullptr; } - GSET_FOREACH_BEGIN (OperationNode *, op_node, graph_->entry_tags) { + for (OperationNode *op_node : graph_->entry_tags) { ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; @@ -360,12 +347,11 @@ void DepsgraphNodeBuilder::begin_build() entry_tag.name_tag = op_node->name_tag; saved_entry_tags_.push_back(entry_tag); } - GSET_FOREACH_END(); /* Make sure graph has no nodes left from previous state. */ graph_->clear_all_nodes(); graph_->operations.clear(); - BLI_gset_clear(graph_->entry_tags, nullptr); + graph_->entry_tags.clear(); } void DepsgraphNodeBuilder::end_build() @@ -482,6 +468,9 @@ void DepsgraphNodeBuilder::build_id(ID *id) case ID_SCE: build_scene_parameters((Scene *)id); break; + case ID_SIM: + build_simulation((Simulation *)id); + break; default: fprintf(stderr, "Unhandled ID %s\n", id->name); BLI_assert(!"Should never happen"); @@ -519,8 +508,7 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti } else if (from_layer_collection == nullptr && !id_node->is_collection_fully_expanded) { /* Initially collection was built from layer now, and was requested - * to not recurs into object. But nw it's asked to recurs into all - * objects. */ + * to not recurs into object. But now it's asked to recurs into all objects. */ } else { return; @@ -616,21 +604,21 @@ void DepsgraphNodeBuilder::build_object(int base_index, BuilderWalkUserData data; data.builder = this; data.is_parent_visible = is_visible; - modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { BuilderWalkUserData data; data.builder = this; data.is_parent_visible = is_visible; - BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_gpencil_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Shader FX. */ if (object->shader_fx.first != nullptr) { BuilderWalkUserData data; data.builder = this; data.is_parent_visible = is_visible; - BKE_shaderfx_foreachIDLink(object, modifier_walk, &data); + BKE_shaderfx_foreach_ID_link(object, modifier_walk, &data); } /* Constraints. */ if (object->constraints.first != nullptr) { @@ -1161,8 +1149,8 @@ void DepsgraphNodeBuilder::build_particle_systems(Object *object, bool is_object * evaluation context for an object. It acts as the container * for all the nodes associated with a particular set of particle * systems. - * 2) Particle System Eval Operation - This operation node acts as a - * blackbox evaluation step for one particle system referenced by + * 2) Particle System Evaluation Operation - This operation node acts as a + * black-box evaluation step for one particle system referenced by * the particle systems stack. All dependencies link to this operation. */ /* Component for all particle systems. */ ComponentNode *psys_comp = add_component_node(&object->id, NodeType::PARTICLE_SYSTEM); @@ -1757,6 +1745,16 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound) build_parameters(&sound->id); } +void DepsgraphNodeBuilder::build_simulation(Simulation *simulation) +{ + if (built_map_.checkIsBuiltAndTag(simulation)) { + return; + } + add_id_node(&simulation->id); + build_animdata(&simulation->id); + build_parameters(&simulation->id); +} + void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene) { if (scene->ed == nullptr) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 16beedabc2a..5cd7f7449a2 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -37,7 +37,6 @@ struct Collection; struct FCurve; struct FreestyleLineSet; struct FreestyleLineStyle; -struct GHash; struct ID; struct IDProperty; struct Image; @@ -53,6 +52,7 @@ struct MovieClip; struct Object; struct ParticleSettings; struct Scene; +struct Simulation; struct Speaker; struct Tex; struct World; @@ -221,6 +221,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { virtual void build_lightprobe(LightProbe *probe); virtual void build_speaker(Speaker *speaker); virtual void build_sound(bSound *sound); + virtual void build_simulation(Simulation *simulation); virtual void build_scene_sequencer(Scene *scene); virtual void build_scene_audio(Scene *scene); virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer); @@ -279,7 +280,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { bool is_parent_collection_visible_; /* Indexed by original ID, values are IDInfo. */ - GHash *id_info_hash_; + Map<const ID *, IDInfo *> id_info_hash_; /* Set of IDs which were already build. Makes it easier to keep track of * what was already built and what was not. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index 7a05ae36ea4..ab0a5c13321 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -34,7 +34,6 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -44,7 +43,6 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -143,8 +141,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible) Scene *scene_cow = get_cow_datablock(scene_); Object *object_cow = get_cow_datablock(object); OperationNode *op_node; - /* Animation and/or drivers linking posebones to base-armature used to - * define them. + /* Animation and/or drivers linking pose-bones to base-armature used to define them. * * NOTE: AnimData here is really used to control animated deform properties, * which ideally should be able to be unique across different diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 1aa3c5bf613..58cfb36b4ab 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -34,7 +34,6 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_freestyle_types.h" #include "DNA_layer_types.h" #include "DNA_linestyle_types.h" @@ -45,7 +44,6 @@ extern "C" { #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc index ecacfcf7ee9..a0179181866 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc @@ -26,104 +26,55 @@ #include <stdio.h> #include <string.h> -#include "BLI_ghash.h" #include "BLI_utildefines.h" namespace DEG { -static void free_rootpchanmap_valueset(void *val) -{ - /* Just need to free the set itself - the names stored are all references. */ - GSet *values = (GSet *)val; - BLI_gset_free(values, nullptr); -} - RootPChanMap::RootPChanMap() { - /* Just create empty map. */ - map_ = BLI_ghash_str_new("RootPChanMap"); } RootPChanMap::~RootPChanMap() { - /* Free the map, and all the value sets. */ - BLI_ghash_free(map_, nullptr, free_rootpchanmap_valueset); } /* Debug contents of map */ void RootPChanMap::print_debug() { - GHashIterator it1; - GSetIterator it2; - - printf("Root PChan Map:\n"); - GHASH_ITER (it1, map_) { - const char *item = (const char *)BLI_ghashIterator_getKey(&it1); - GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1); - - printf(" %s : { ", item); - GSET_ITER (it2, values) { - const char *val = (const char *)BLI_gsetIterator_getKey(&it2); - printf("%s, ", val); + map_.foreach_item([](StringRefNull key, const Set<StringRefNull> &values) { + printf(" %s : { ", key.data()); + for (StringRefNull val : values) { + printf("%s, ", val.data()); } printf("}\n"); - } + }); } /* Add a mapping. */ void RootPChanMap::add_bone(const char *bone, const char *root) { - if (BLI_ghash_haskey(map_, bone)) { - /* Add new entry, but only add the root if it doesn't already - * exist in there. */ - GSet *values = (GSet *)BLI_ghash_lookup(map_, bone); - BLI_gset_add(values, (void *)root); - } - else { - /* Create new set and mapping. */ - GSet *values = BLI_gset_new( - BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "RootPChanMap Value Set"); - BLI_ghash_insert(map_, (void *)bone, (void *)values); - - /* Add new entry now. */ - BLI_gset_insert(values, (void *)root); - } + map_.lookup_or_add_default(bone).add(root); } /* Check if there's a common root bone between two bones. */ bool RootPChanMap::has_common_root(const char *bone1, const char *bone2) const { - /* Ensure that both are in the map... */ - if (BLI_ghash_haskey(map_, bone1) == false) { + const Set<StringRefNull> *bone1_roots = map_.lookup_ptr(bone1); + const Set<StringRefNull> *bone2_roots = map_.lookup_ptr(bone2); + + if (bone1_roots == nullptr) { // fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2); // print_debug(); return false; } - if (BLI_ghash_haskey(map_, bone2) == false) { + if (bone2_roots == nullptr) { // fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2); // print_debug(); return false; } - GSet *bone1_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone1); - GSet *bone2_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone2); - - GSetIterator it1, it2; - GSET_ITER (it1, bone1_roots) { - GSET_ITER (it2, bone2_roots) { - const char *v1 = (const char *)BLI_gsetIterator_getKey(&it1); - const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2); - - if (strcmp(v1, v2) == 0) { - // fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2); - return true; - } - } - } - - // fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2); - return false; + return Set<StringRefNull>::Intersects(*bone1_roots, *bone2_roots); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h index 1442f547b08..c3c90e5aae4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h @@ -23,7 +23,7 @@ #pragma once -struct GHash; +#include "intern/depsgraph_type.h" namespace DEG { @@ -42,13 +42,11 @@ struct RootPChanMap { bool has_common_root(const char *bone1, const char *bone2) const; protected: - /* The actual map: - * - Keys are "strings" (const char *) - not dynamically allocated. - * - Values are "sets" (const char *) - not dynamically allocated. - * - * We don't use the C++ maps here, as it's more convenient to use - * Blender's GHash and be able to compare by-value instead of by-ref. */ - struct GHash *map_; + /** + * The strings are only referenced by this map. Users of RootPChanMap have to make sure that the + * life-time of the strings is long enough. + */ + Map<StringRefNull, Set<StringRefNull>> map_; }; } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 9bad796c541..6bdb7500b4a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -28,14 +28,12 @@ #include <cstring> /* required for STREQ later on. */ #include <stdio.h> #include <stdlib.h> -#include <unordered_set> #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -62,6 +60,7 @@ extern "C" { #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -76,7 +75,7 @@ extern "C" { #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil_modifier.h" #include "BKE_idprop.h" #include "BKE_image.h" @@ -99,7 +98,6 @@ extern "C" { #include "RNA_access.h" #include "RNA_types.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -122,8 +120,6 @@ extern "C" { namespace DEG { -using std::unordered_set; - /* ***************** */ /* Relations Builder */ @@ -559,6 +555,9 @@ void DepsgraphRelationBuilder::build_id(ID *id) case ID_SCE: build_scene_parameters((Scene *)id); break; + case ID_SIM: + build_simulation((Simulation *)id); + break; default: fprintf(stderr, "Unhandled ID %s\n", id->name); BLI_assert(!"Should never happen"); @@ -659,19 +658,19 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) if (object->modifiers.first != nullptr) { BuilderWalkUserData data; data.builder = this; - modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { BuilderWalkUserData data; data.builder = this; - BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_gpencil_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Shader FX. */ if (object->shader_fx.first != nullptr) { BuilderWalkUserData data; data.builder = this; - BKE_shaderfx_foreachIDLink(object, modifier_walk, &data); + BKE_shaderfx_foreach_ID_link(object, modifier_walk, &data); } /* Constraints. */ if (object->constraints.first != nullptr) { @@ -1972,7 +1971,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.scene = scene_; ctx.object = object; LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { - const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); if (mti->updateDepsgraph) { DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); @@ -1990,7 +1989,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.scene = scene_; ctx.object = object; LISTBASE_FOREACH (GpencilModifierData *, md, &object->greasepencil_modifiers) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo( + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info( (GpencilModifierType)md->type); if (mti->updateDepsgraph) { DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); @@ -2009,7 +2008,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.scene = scene_; ctx.object = object; LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo((ShaderFxType)fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info((ShaderFxType)fx->type); if (fxi->updateDepsgraph) { DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); @@ -2400,22 +2399,28 @@ void DepsgraphRelationBuilder::build_texture(Tex *texture) return; } /* texture itself */ + ComponentKey texture_key(&texture->id, NodeType::GENERIC_DATABLOCK); build_idproperties(texture->id.properties); build_animdata(&texture->id); build_parameters(&texture->id); + /* texture's nodetree */ build_nodetree(texture->nodetree); + build_nested_nodetree(&texture->id, texture->nodetree); + /* Special cases for different IDs which texture uses. */ if (texture->type == TEX_IMAGE) { if (texture->ima != nullptr) { build_image(texture->ima); + + ComponentKey image_key(&texture->ima->id, NodeType::GENERIC_DATABLOCK); + add_relation(image_key, texture_key, "Texture Image"); } } - build_nested_nodetree(&texture->id, texture->nodetree); + if (check_id_has_anim_component(&texture->id)) { ComponentKey animation_key(&texture->id, NodeType::ANIMATION); - ComponentKey datablock_key(&texture->id, NodeType::GENERIC_DATABLOCK); - add_relation(animation_key, datablock_key, "Datablock Animation"); + add_relation(animation_key, texture_key, "Datablock Animation"); } } @@ -2566,6 +2571,15 @@ void DepsgraphRelationBuilder::build_sound(bSound *sound) build_parameters(&sound->id); } +void DepsgraphRelationBuilder::build_simulation(Simulation *simulation) +{ + if (built_map_.checkIsBuiltAndTag(simulation)) { + return; + } + build_animdata(&simulation->id); + build_parameters(&simulation->id); +} + void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) { if (scene->ed == nullptr) { @@ -2681,7 +2695,7 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) Node *node_cow = find_node(copy_on_write_key); OperationNode *op_cow = node_cow->get_exit_operation(); /* Plug any other components to this one. */ - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { if (comp_node->type == NodeType::COPY_ON_WRITE) { /* Copy-on-write component never depends on itself. */ continue; @@ -2724,11 +2738,11 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) rel->flag |= rel_flag; } /* All dangling operations should also be executed after copy-on-write. */ - GHASH_FOREACH_BEGIN (OperationNode *, op_node, comp_node->operations_map) { + for (OperationNode *op_node : comp_node->operations_map->values()) { if (op_node == op_entry) { continue; } - if (op_node->inlinks.size() == 0) { + if (op_node->inlinks.is_empty()) { Relation *rel = graph_->add_new_relation(op_cow, op_node, "CoW Dependency"); rel->flag |= rel_flag; } @@ -2750,7 +2764,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) } } } - GHASH_FOREACH_END(); /* NOTE: We currently ignore implicit relations to an external * data-blocks for copy-on-write operations. This means, for example, * copy-on-write component of Object will not wait for copy-on-write @@ -2759,7 +2772,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) * evaluation step needs geometry, it will have transitive dependency * to Mesh copy-on-write already. */ } - GHASH_FOREACH_END(); /* TODO(sergey): This solves crash for now, but causes too many * updates potentially. */ if (GS(id_orig->name) == ID_OB) { @@ -2808,7 +2820,7 @@ static bool is_reachable(const Node *const from, const Node *const to) // Perform a graph walk from 'to' towards its incoming connections. // Walking from 'from' towards its outgoing connections is 10x slower on the Spring rig. deque<const Node *> queue; - unordered_set<const Node *> seen; + Set<const Node *> seen; queue.push_back(to); while (!queue.empty()) { // Visit the next node to inspect. @@ -2822,7 +2834,7 @@ static bool is_reachable(const Node *const from, const Node *const to) // Queue all incoming relations that we haven't seen before. for (Relation *relation : visit->inlinks) { const Node *prev_node = relation->from; - if (seen.insert(prev_node).second) { + if (seen.add(prev_node)) { queue.push_back(prev_node); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 3c9bd8a9856..aa6d8ababd3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -69,6 +69,7 @@ struct Object; struct ParticleSettings; struct ParticleSystem; struct Scene; +struct Simulation; struct Speaker; struct Tex; struct ViewLayer; @@ -286,6 +287,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { virtual void build_lightprobe(LightProbe *probe); virtual void build_speaker(Speaker *speaker); virtual void build_sound(bSound *sound); + virtual void build_simulation(Simulation *simulation); virtual void build_scene_sequencer(Scene *scene); virtual void build_scene_audio(Scene *scene); virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer); 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 eeeb58100b0..5983627fafc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h @@ -25,10 +25,8 @@ #include "intern/node/deg_node_id.h" -extern "C" { #include "DNA_ID.h" #include "DNA_object_types.h" -} namespace DEG { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index ff2bc2ac3ea..fe9adecbf0a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -34,7 +34,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -45,7 +44,6 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -69,7 +67,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object, RootPChanMap *root_map) { if ((con->flag & CONSTRAINT_DISABLE) != 0) { - /* Do not add disabled IK constraints to the relations. If these needs to be temporarly + /* Do not add disabled IK constraints to the relations. If these needs to be temporarily * enabled, they will be added as temporary constraints during transform. */ return; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index d3bdaccd404..e132ba30e67 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -34,7 +34,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_linestyle_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -43,7 +42,6 @@ extern "C" { #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc b/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc index 2ce1f1f1c1d..c6545362bb1 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc @@ -43,7 +43,7 @@ static inline bool is_unused_noop(OperationNode *op_node) if (op_node->flag & OperationFlag::DEPSOP_FLAG_PINNED) { return false; } - return op_node->is_noop() && op_node->outlinks.empty(); + return op_node->is_noop() && op_node->outlinks.is_empty(); } void deg_graph_remove_unused_noops(Depsgraph *graph) @@ -61,7 +61,7 @@ void deg_graph_remove_unused_noops(Depsgraph *graph) OperationNode *to_remove = queue.front(); queue.pop_front(); - while (!to_remove->inlinks.empty()) { + while (!to_remove->inlinks.is_empty()) { Relation *rel_in = to_remove->inlinks[0]; Node *dependency = rel_in->from; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 73f6730be03..9fa663b9b6d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -27,18 +27,15 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_key_types.h" #include "DNA_object_types.h" #include "DNA_sequence_types.h" -} #include "BKE_constraint.h" @@ -57,37 +54,33 @@ namespace DEG { class RNANodeQueryIDData { public: - explicit RNANodeQueryIDData(const ID *id) : id_(id), contraint_to_pchan_map_(nullptr) + explicit RNANodeQueryIDData(const ID *id) : id_(id), constraint_to_pchan_map_(nullptr) { } ~RNANodeQueryIDData() { - if (contraint_to_pchan_map_ != nullptr) { - BLI_ghash_free(contraint_to_pchan_map_, nullptr, nullptr); - } + delete constraint_to_pchan_map_; } const bPoseChannel *get_pchan_for_constraint(const bConstraint *constraint) { ensure_constraint_to_pchan_map(); - return static_cast<bPoseChannel *>(BLI_ghash_lookup(contraint_to_pchan_map_, constraint)); + return constraint_to_pchan_map_->lookup_default(constraint, nullptr); } void ensure_constraint_to_pchan_map() { - if (contraint_to_pchan_map_ != nullptr) { + if (constraint_to_pchan_map_ != nullptr) { return; } BLI_assert(GS(id_->name) == ID_OB); const Object *object = reinterpret_cast<const Object *>(id_); - contraint_to_pchan_map_ = BLI_ghash_ptr_new("id data pchan constraint map"); + constraint_to_pchan_map_ = new Map<const bConstraint *, const bPoseChannel *>(); if (object->pose != nullptr) { LISTBASE_FOREACH (const bPoseChannel *, pchan, &object->pose->chanbase) { LISTBASE_FOREACH (const bConstraint *, constraint, &pchan->constraints) { - BLI_ghash_insert(contraint_to_pchan_map_, - const_cast<bConstraint *>(constraint), - const_cast<bPoseChannel *>(pchan)); + constraint_to_pchan_map_->add_new(constraint, pchan); } } } @@ -99,7 +92,7 @@ class RNANodeQueryIDData { /* indexed by bConstraint*, returns pose channel which contains that * constraint. */ - GHash *contraint_to_pchan_map_; + Map<const bConstraint *, const bPoseChannel *> *constraint_to_pchan_map_; }; /* ***************************** Node Identifier **************************** */ @@ -121,26 +114,13 @@ bool RNANodeIdentifier::is_valid() const /* ********************************** Query ********************************* */ -namespace { - -void ghash_id_data_free_func(void *value) -{ - RNANodeQueryIDData *id_data = static_cast<RNANodeQueryIDData *>(value); - OBJECT_GUARDED_DELETE(id_data, RNANodeQueryIDData); -} - -} // namespace - RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph, DepsgraphBuilder *builder) - : depsgraph_(depsgraph), - builder_(builder), - id_data_map_(BLI_ghash_ptr_new("rna node query id data hash")) + : depsgraph_(depsgraph), builder_(builder) { } RNANodeQuery::~RNANodeQuery() { - BLI_ghash_free(id_data_map_, nullptr, ghash_id_data_free_func); } Node *RNANodeQuery::find_node(const PointerRNA *ptr, @@ -384,12 +364,9 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, RNANodeQueryIDData *RNANodeQuery::ensure_id_data(const ID *id) { - RNANodeQueryIDData **id_data_ptr; - if (!BLI_ghash_ensure_p( - id_data_map_, const_cast<ID *>(id), reinterpret_cast<void ***>(&id_data_ptr))) { - *id_data_ptr = OBJECT_GUARDED_NEW(RNANodeQueryIDData, id); - } - return *id_data_ptr; + unique_ptr<RNANodeQueryIDData> &id_data = id_data_map_.lookup_or_add( + id, [&]() { return BLI::make_unique<RNANodeQueryIDData>(id); }); + return id_data.get(); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h index 8a79d9abef9..bd806ce058a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h @@ -26,7 +26,6 @@ #include "intern/node/deg_node.h" #include "intern/node/deg_node_operation.h" -struct GHash; struct ID; struct PointerRNA; struct PropertyRNA; @@ -83,7 +82,7 @@ class RNANodeQuery { DepsgraphBuilder *builder_; /* Indexed by an ID, returns RNANodeQueryIDData associated with that ID. */ - GHash *id_data_map_; + Map<const ID *, unique_ptr<RNANodeQueryIDData>> id_data_map_; /* Construct identifier of the node which corresponds given configuration * of RNA property. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc index 3f828ef5bb0..22ceac899b8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc @@ -72,6 +72,8 @@ static void deg_graph_tag_paths_recursive(Node *node) void deg_graph_transitive_reduction(Depsgraph *graph) { int num_removed_relations = 0; + Vector<Relation *> relations_to_remove; + for (OperationNode *target : graph->operations) { /* Clear tags. */ for (OperationNode *node : graph->operations) { @@ -85,25 +87,24 @@ void deg_graph_transitive_reduction(Depsgraph *graph) deg_graph_tag_paths_recursive(rel->from); } /* Remove redundant paths to the target. */ - for (Node::Relations::const_iterator it_rel = target->inlinks.begin(); - it_rel != target->inlinks.end();) { - Relation *rel = *it_rel; + for (Relation *rel : target->inlinks) { if (rel->from->type == NodeType::TIMESOURCE) { /* HACK: time source nodes don't get "custom_flags" flag * set/cleared. */ /* TODO: there will be other types in future, so iterators above * need modifying. */ - ++it_rel; + continue; } else if (rel->from->custom_flags & OP_REACHABLE) { - rel->unlink(); - OBJECT_GUARDED_DELETE(rel, Relation); - num_removed_relations++; - } - else { - ++it_rel; + relations_to_remove.append(rel); } } + for (Relation *rel : relations_to_remove) { + rel->unlink(); + OBJECT_GUARDED_DELETE(rel, Relation); + } + num_removed_relations += relations_to_remove.size(); + relations_to_remove.clear(); } DEG_DEBUG_PRINTF((::Depsgraph *)graph, BUILD, "Removed %d relations\n", num_removed_relations); } 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 7080f8a1a9b..bde48affc28 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -25,12 +25,9 @@ #include <cstdarg> -#include "BLI_ghash.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_listBase.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -407,15 +404,14 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, const Node *node) switch (node->type) { case NodeType::ID_REF: { const IDNode *id_node = (const IDNode *)node; - if (BLI_ghash_len(id_node->components) == 0) { + if (id_node->components.is_empty()) { deg_debug_graphviz_node_single(ctx, node); } else { deg_debug_graphviz_node_cluster_begin(ctx, node); - GHASH_FOREACH_BEGIN (const ComponentNode *, comp, id_node->components) { + for (const ComponentNode *comp : id_node->components.values()) { deg_debug_graphviz_node(ctx, comp); } - GHASH_FOREACH_END(); deg_debug_graphviz_node_cluster_end(ctx); } break; @@ -472,7 +468,7 @@ static bool deg_debug_graphviz_is_cluster(const Node *node) switch (node->type) { case NodeType::ID_REF: { const IDNode *id_node = (const IDNode *)node; - return BLI_ghash_len(id_node->components) > 0; + return !id_node->components.is_empty(); } case NodeType::PARAMETERS: case NodeType::ANIMATION: @@ -568,12 +564,11 @@ static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, const Depsgr static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, const Depsgraph *graph) { for (IDNode *id_node : graph->id_nodes) { - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { for (OperationNode *op_node : comp_node->operations) { deg_debug_graphviz_node_relations(ctx, op_node); } } - GHASH_FOREACH_END(); } TimeSourceNode *time_source = graph->find_time_source(); diff --git a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc index c37188bc3ca..7bef5fda636 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc @@ -32,9 +32,7 @@ #include "intern/depsgraph.h" #include "intern/node/deg_node_id.h" -extern "C" { #include "DNA_ID.h" -} /* extern "C" */ #define NL "\r\n" diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 6d88782d68c..d4a6b0a8b76 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -31,15 +31,12 @@ #include "MEM_guardedalloc.h" #include "BLI_console.h" -#include "BLI_ghash.h" #include "BLI_hash.h" #include "BLI_utildefines.h" -extern "C" { #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_scene.h" -} #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -60,12 +57,6 @@ extern "C" { namespace DEG { -/* TODO(sergey): Find a better place for this. */ -template<typename T> static void remove_from_vector(vector<T> *vector, const T &value) -{ - vector->erase(std::remove(vector->begin(), vector->end(), value), vector->end()); -} - Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode) : time_source(nullptr), need_update(true), @@ -81,8 +72,6 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati is_render_pipeline_depsgraph(false) { BLI_spin_init(&lock); - id_hash = BLI_ghash_ptr_new("Depsgraph id hash"); - entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags"); memset(id_type_updated, 0, sizeof(id_type_updated)); memset(id_type_exist, 0, sizeof(id_type_exist)); memset(physics_relations, 0, sizeof(physics_relations)); @@ -91,8 +80,6 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati Depsgraph::~Depsgraph() { clear_id_nodes(); - BLI_ghash_free(id_hash, nullptr, nullptr); - BLI_gset_free(entry_tags, nullptr); if (time_source != nullptr) { OBJECT_GUARDED_DELETE(time_source, TimeSourceNode); } @@ -117,7 +104,7 @@ TimeSourceNode *Depsgraph::find_time_source() const IDNode *Depsgraph::find_id_node(const ID *id) const { - return reinterpret_cast<IDNode *>(BLI_ghash_lookup(id_hash, id)); + return id_hash.lookup_default(id, nullptr); } IDNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint) @@ -132,7 +119,7 @@ IDNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint) * * NOTE: We address ID nodes by the original ID pointer they are * referencing to. */ - BLI_ghash_insert(id_hash, id, id_node); + id_hash.add_new(id, id_node); id_nodes.push_back(id_node); id_type_exist[BKE_idtype_idcode_to_index(GS(id->name))] = 1; @@ -170,7 +157,7 @@ void Depsgraph::clear_id_nodes() OBJECT_GUARDED_DELETE(id_node, IDNode); } /* Clear containers. */ - BLI_ghash_clear(id_hash, nullptr, nullptr); + id_hash.clear(); id_nodes.clear(); /* Clear physics relation caches. */ clear_physics_relations(this); @@ -233,7 +220,7 @@ void Depsgraph::add_entry_tag(OperationNode *node) * from. * NOTE: this is necessary since we have several thousand nodes to play * with. */ - BLI_gset_insert(entry_tags, node); + entry_tags.add(node); } void Depsgraph::clear_all_nodes() @@ -320,9 +307,9 @@ void DEG_graph_free(Depsgraph *graph) OBJECT_GUARDED_DELETE(deg_depsgraph, Depsgraph); } -bool DEG_is_evaluating(struct Depsgraph *depsgraph) +bool DEG_is_evaluating(const struct Depsgraph *depsgraph) { - DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph); + const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(depsgraph); return deg_graph->is_evaluating; } diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 7801f95e008..672f202338e 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -43,8 +43,6 @@ #include "intern/debug/deg_debug.h" #include "intern/depsgraph_type.h" -struct GHash; -struct GSet; struct ID; struct Scene; struct ViewLayer; @@ -97,7 +95,7 @@ struct Depsgraph { /* <ID : IDNode> mapping from ID blocks to nodes representing these * blocks, used for quick lookups. */ - GHash *id_hash; + Map<const ID *, IDNode *> id_hash; /* Ordered list of ID nodes, order matches ID allocation order. * Used for faster iteration, especially for areas which are critical to @@ -119,7 +117,7 @@ struct Depsgraph { /* Quick-Access Temp Data ............. */ /* Nodes which have been tagged as "directly modified". */ - GSet *entry_tags; + Set<OperationNode *> entry_tags; /* Special entry tag for time source. Allows to tag invisible dependency graphs for update when * scene frame changes, so then when dependency graph becomes visible it is on a proper state. */ @@ -169,7 +167,7 @@ struct Depsgraph { /* Cached list of colliders/effectors for collections and the scene * created along with relations, for fast lookup during evaluation. */ - GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM]; + Map<const ID *, ListBase *> *physics_relations[DEG_PHYSICS_RELATIONS_NUM]; }; } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index d78bc07ac5e..9e12d00b42f 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -25,21 +25,18 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "PIL_time.h" #include "PIL_time_utildefines.h" -extern "C" { #include "DNA_cachefile_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BKE_main.h" #include "BKE_scene.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc index c713a4a3fb1..8f5117ec0f6 100644 --- a/source/blender/depsgraph/intern/depsgraph_debug.cc +++ b/source/blender/depsgraph/intern/depsgraph_debug.cc @@ -23,12 +23,9 @@ * Implementation of tools for debugging the depsgraph */ -#include "BLI_ghash.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_scene_types.h" -} /* extern "C" */ #include "DNA_object_types.h" @@ -198,10 +195,10 @@ bool DEG_debug_consistency_check(Depsgraph *graph) /* ------------------------------------------------ */ /** - * Obtain simple statistics about the complexity of the depsgraph - * \param[out] r_outer The number of outer nodes in the graph - * \param[out] r_operations The number of operation nodes in the graph - * \param[out] r_relations The number of relations between (executable) nodes in the graph + * Obtain simple statistics about the complexity of the depsgraph. + * \param[out] r_outer: The number of outer nodes in the graph + * \param[out] r_operations: The number of operation nodes in the graph + * \param[out] r_relations: The number of relations between (executable) nodes in the graph */ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer, @@ -224,13 +221,12 @@ void DEG_stats_simple(const Depsgraph *graph, for (DEG::IDNode *id_node : deg_graph->id_nodes) { tot_outer++; - GHASH_FOREACH_BEGIN (DEG::ComponentNode *, comp_node, id_node->components) { + for (DEG::ComponentNode *comp_node : id_node->components.values()) { tot_outer++; for (DEG::OperationNode *op_node : comp_node->operations) { tot_rels += op_node->inlinks.size(); } } - GHASH_FOREACH_END(); } DEG::TimeSourceNode *time_source = deg_graph->find_time_source(); diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc index 9251d975125..b6c6129e9ba 100644 --- a/source/blender/depsgraph/intern/depsgraph_eval.cc +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -25,16 +25,13 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" -extern "C" { #include "BKE_scene.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -87,5 +84,5 @@ void DEG_evaluate_on_framechange(Main *bmain, Depsgraph *graph, float ctime) bool DEG_needs_eval(Depsgraph *graph) { DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph); - return BLI_gset_len(deg_graph->entry_tags) != 0 || deg_graph->need_update_time; + return !deg_graph->entry_tags.is_empty() || deg_graph->need_update_time; } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc index d7c09780845..a9391e5fe8b 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.cc +++ b/source/blender/depsgraph/intern/depsgraph_physics.cc @@ -28,14 +28,11 @@ #include "MEM_guardedalloc.h" #include "BLI_compiler_compat.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" -extern "C" { #include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_modifier.h" -} /* extern "C" */ #include "DNA_collection_types.h" #include "DNA_object_force_types.h" @@ -72,8 +69,8 @@ ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collect } ID *collection_orig = DEG_get_original_id(&collection->id); - return (ListBase *)BLI_ghash_lookup(deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR], - collection_orig); + return deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR]->lookup_default(collection_orig, + nullptr); } ListBase *DEG_get_collision_relations(const Depsgraph *graph, @@ -86,7 +83,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph, return nullptr; } ID *collection_orig = DEG_get_original_id(&collection->id); - return (ListBase *)BLI_ghash_lookup(deg_graph->physics_relations[type], collection_orig); + return deg_graph->physics_relations[type]->lookup_default(collection_orig, nullptr); } /********************** Depsgraph Building API ************************/ @@ -107,7 +104,7 @@ void DEG_add_collision_relations(DepsNodeHandle *handle, continue; } if (filter_function == nullptr || - filter_function(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) { + filter_function(ob1, BKE_modifiers_findby_type(ob1, (ModifierType)modifier_type))) { DEG_add_object_pointcache_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name); DEG_add_object_pointcache_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name); } @@ -165,19 +162,15 @@ namespace DEG { ListBase *build_effector_relations(Depsgraph *graph, Collection *collection) { - GHash *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR]; + Map<const ID *, ListBase *> *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR]; if (hash == nullptr) { - graph->physics_relations[DEG_PHYSICS_EFFECTOR] = BLI_ghash_ptr_new( - "Depsgraph physics relations hash"); + graph->physics_relations[DEG_PHYSICS_EFFECTOR] = new Map<const ID *, ListBase *>(); hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR]; } - ListBase *relations = reinterpret_cast<ListBase *>(BLI_ghash_lookup(hash, collection)); - if (relations == nullptr) { + return hash->lookup_or_add(&collection->id, [&]() { ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph); - relations = BKE_effector_relations_create(depsgraph, graph->view_layer, collection); - BLI_ghash_insert(hash, &collection->id, relations); - } - return relations; + return BKE_effector_relations_create(depsgraph, graph->view_layer, collection); + }); } ListBase *build_collision_relations(Depsgraph *graph, @@ -185,52 +178,41 @@ ListBase *build_collision_relations(Depsgraph *graph, unsigned int modifier_type) { const ePhysicsRelationType type = modifier_to_relation_type(modifier_type); - GHash *hash = graph->physics_relations[type]; + Map<const ID *, ListBase *> *hash = graph->physics_relations[type]; if (hash == nullptr) { - graph->physics_relations[type] = BLI_ghash_ptr_new("Depsgraph physics relations hash"); + graph->physics_relations[type] = new Map<const ID *, ListBase *>(); hash = graph->physics_relations[type]; } - ListBase *relations = reinterpret_cast<ListBase *>(BLI_ghash_lookup(hash, collection)); - if (relations == nullptr) { + return hash->lookup_or_add(&collection->id, [&]() { ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph); - relations = BKE_collision_relations_create(depsgraph, collection, modifier_type); - BLI_ghash_insert(hash, &collection->id, relations); - } - return relations; -} - -namespace { - -void free_effector_relations(void *value) -{ - BKE_effector_relations_free(reinterpret_cast<ListBase *>(value)); + return BKE_collision_relations_create(depsgraph, collection, modifier_type); + }); } -void free_collision_relations(void *value) -{ - BKE_collision_relations_free(reinterpret_cast<ListBase *>(value)); -} - -} // namespace - void clear_physics_relations(Depsgraph *graph) { for (int i = 0; i < DEG_PHYSICS_RELATIONS_NUM; i++) { - if (graph->physics_relations[i]) { + Map<const ID *, ListBase *> *hash = graph->physics_relations[i]; + if (hash) { const ePhysicsRelationType type = (ePhysicsRelationType)i; switch (type) { case DEG_PHYSICS_EFFECTOR: - BLI_ghash_free(graph->physics_relations[i], nullptr, free_effector_relations); + for (ListBase *list : hash->values()) { + BKE_effector_relations_free(list); + } break; case DEG_PHYSICS_COLLISION: case DEG_PHYSICS_SMOKE_COLLISION: case DEG_PHYSICS_DYNAMIC_BRUSH: - BLI_ghash_free(graph->physics_relations[i], nullptr, free_collision_relations); + for (ListBase *list : hash->values()) { + BKE_collision_relations_free(list); + } break; case DEG_PHYSICS_RELATIONS_NUM: break; } + delete hash; graph->physics_relations[i] = nullptr; } } diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 6e85b2e8bd9..3c760e71197 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -25,10 +25,8 @@ #include "MEM_guardedalloc.h" -extern "C" { #include <string.h> // XXX: memcpy -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" @@ -37,8 +35,6 @@ extern "C" { #include "BKE_idtype.h" #include "BKE_main.h" -} /* extern "C" */ - #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -271,7 +267,7 @@ ID *DEG_get_original_id(ID *id) return (ID *)id->orig_id; } -bool DEG_is_original_id(ID *id) +bool DEG_is_original_id(const ID *id) { /* Some explanation of the logic. * @@ -296,17 +292,17 @@ bool DEG_is_original_id(ID *id) return true; } -bool DEG_is_original_object(Object *object) +bool DEG_is_original_object(const Object *object) { return DEG_is_original_id(&object->id); } -bool DEG_is_evaluated_id(ID *id) +bool DEG_is_evaluated_id(const ID *id) { return !DEG_is_original_id(id); } -bool DEG_is_evaluated_object(Object *object) +bool DEG_is_evaluated_object(const Object *object) { return !DEG_is_original_object(object); } @@ -319,7 +315,7 @@ bool DEG_is_fully_evaluated(const struct Depsgraph *depsgraph) return false; } /* Check whether IDs are up to date. */ - if (BLI_gset_len(deg_graph->entry_tags) > 0) { + if (!deg_graph->entry_tags.is_empty()) { return false; } return true; diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc index efd7d6e77ef..b68c4b91fcc 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc @@ -23,14 +23,9 @@ * Implementation of Querying and Filtering API's */ -#include <unordered_set> - #include "MEM_guardedalloc.h" -extern "C" { -#include "BLI_ghash.h" #include "BLI_utildefines.h" -} /* extern "C" */ #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -50,8 +45,6 @@ extern "C" { namespace DEG { namespace { -using std::unordered_set; - typedef deque<OperationNode *> TraversalQueue; typedef void (*DEGForeachOperation)(OperationNode *op_node, void *user_data); @@ -66,11 +59,12 @@ bool deg_foreach_needs_visit(const OperationNode *op_node, const int flags) return true; } -static void deg_foreach_dependent_operation(const IDNode *target_id_node, - eDepsObjectComponentType source_component_type, - int flags, - DEGForeachOperation callback, - void *user_data) +void deg_foreach_dependent_operation(const Depsgraph *UNUSED(graph), + const IDNode *target_id_node, + eDepsObjectComponentType source_component_type, + int flags, + DEGForeachOperation callback, + void *user_data) { if (target_id_node == nullptr) { /* TODO(sergey): Shall we inform or assert here about attempt to start @@ -79,8 +73,8 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, } /* Start with scheduling all operations from ID node. */ TraversalQueue queue; - unordered_set<OperationNode *> scheduled; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, target_id_node->components) { + Set<OperationNode *> scheduled; + for (ComponentNode *comp_node : target_id_node->components.values()) { if (source_component_type != DEG_OB_COMP_ANY && nodeTypeToObjectComponent(comp_node->type) != source_component_type) { continue; @@ -90,10 +84,9 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, continue; } queue.push_back(op_node); - scheduled.insert(op_node); + scheduled.add(op_node); } } - GHASH_FOREACH_END(); /* Process the queue. */ while (!queue.empty()) { /* get next operation node to process. */ @@ -104,9 +97,8 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, /* Schedule outgoing operation nodes. */ if (op_node->outlinks.size() == 1) { OperationNode *to_node = (OperationNode *)op_node->outlinks[0]->to; - if (scheduled.find(to_node) == scheduled.end() && - deg_foreach_needs_visit(to_node, flags)) { - scheduled.insert(to_node); + if (!scheduled.contains(to_node) && deg_foreach_needs_visit(to_node, flags)) { + scheduled.add_new(to_node); op_node = to_node; } else { @@ -116,10 +108,9 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, else { for (Relation *rel : op_node->outlinks) { OperationNode *to_node = (OperationNode *)rel->to; - if (scheduled.find(to_node) == scheduled.end() && - deg_foreach_needs_visit(to_node, flags)) { + if (!scheduled.contains(to_node) && deg_foreach_needs_visit(to_node, flags)) { queue.push_front(to_node); - scheduled.insert(to_node); + scheduled.add_new(to_node); } } break; @@ -132,7 +123,7 @@ struct ForeachIDComponentData { DEGForeachIDComponentCallback callback; void *user_data; IDNode *target_id_node; - unordered_set<ComponentNode *> visited; + Set<ComponentNode *> visited; }; void deg_foreach_dependent_component_callback(OperationNode *op_node, void *user_data_v) @@ -140,11 +131,10 @@ void deg_foreach_dependent_component_callback(OperationNode *op_node, void *user ForeachIDComponentData *user_data = reinterpret_cast<ForeachIDComponentData *>(user_data_v); ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; - if (id_node != user_data->target_id_node && - user_data->visited.find(comp_node) == user_data->visited.end()) { + if (id_node != user_data->target_id_node && !user_data->visited.contains(comp_node)) { user_data->callback( id_node->id_orig, nodeTypeToObjectComponent(comp_node->type), user_data->user_data); - user_data->visited.insert(comp_node); + user_data->visited.add_new(comp_node); } } @@ -159,7 +149,8 @@ void deg_foreach_dependent_ID_component(const Depsgraph *graph, data.callback = callback; data.user_data = user_data; data.target_id_node = graph->find_id_node(id); - deg_foreach_dependent_operation(data.target_id_node, + deg_foreach_dependent_operation(graph, + data.target_id_node, source_component_type, flags, deg_foreach_dependent_component_callback, @@ -170,7 +161,7 @@ struct ForeachIDData { DEGForeachIDCallback callback; void *user_data; IDNode *target_id_node; - unordered_set<IDNode *> visited; + Set<IDNode *> visited; }; void deg_foreach_dependent_ID_callback(OperationNode *op_node, void *user_data_v) @@ -178,10 +169,9 @@ void deg_foreach_dependent_ID_callback(OperationNode *op_node, void *user_data_v ForeachIDData *user_data = reinterpret_cast<ForeachIDData *>(user_data_v); ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; - if (id_node != user_data->target_id_node && - user_data->visited.find(id_node) == user_data->visited.end()) { + if (id_node != user_data->target_id_node && !user_data->visited.contains(id_node)) { user_data->callback(id_node->id_orig, user_data->user_data); - user_data->visited.insert(id_node); + user_data->visited.add_new(id_node); } } @@ -195,7 +185,7 @@ void deg_foreach_dependent_ID(const Depsgraph *graph, data.user_data = user_data; data.target_id_node = graph->find_id_node(id); deg_foreach_dependent_operation( - data.target_id_node, DEG_OB_COMP_ANY, 0, deg_foreach_dependent_ID_callback, &data); + graph, data.target_id_node, DEG_OB_COMP_ANY, 0, deg_foreach_dependent_ID_callback, &data); } void deg_foreach_ancestor_ID(const Depsgraph *graph, @@ -212,16 +202,15 @@ void deg_foreach_ancestor_ID(const Depsgraph *graph, } /* Start with scheduling all operations from ID node. */ TraversalQueue queue; - unordered_set<OperationNode *> scheduled; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, target_id_node->components) { + Set<OperationNode *> scheduled; + for (ComponentNode *comp_node : target_id_node->components.values()) { for (OperationNode *op_node : comp_node->operations) { queue.push_back(op_node); - scheduled.insert(op_node); + scheduled.add(op_node); } } - GHASH_FOREACH_END(); - unordered_set<IDNode *> visited; - visited.insert(target_id_node); + Set<IDNode *> visited; + visited.add_new(target_id_node); /* Process the queue. */ while (!queue.empty()) { /* get next operation node to process. */ @@ -231,18 +220,17 @@ void deg_foreach_ancestor_ID(const Depsgraph *graph, /* Check whether we need to inform callee about corresponding ID node. */ ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; - if (visited.find(id_node) == visited.end()) { + if (!visited.contains(id_node)) { /* TODO(sergey): Is it orig or CoW? */ callback(id_node->id_orig, user_data); - visited.insert(id_node); + visited.add_new(id_node); } /* Schedule incoming operation nodes. */ if (op_node->inlinks.size() == 1) { Node *from = op_node->inlinks[0]->from; if (from->get_class() == NodeClass::OPERATION) { OperationNode *from_node = (OperationNode *)from; - if (scheduled.find(from_node) == scheduled.end()) { - scheduled.insert(from_node); + if (scheduled.add(from_node)) { op_node = from_node; } else { @@ -255,9 +243,8 @@ void deg_foreach_ancestor_ID(const Depsgraph *graph, Node *from = rel->from; if (from->get_class() == NodeClass::OPERATION) { OperationNode *from_node = (OperationNode *)from; - if (scheduled.find(from_node) == scheduled.end()) { + if (scheduled.add(from_node)) { queue.push_front(from_node); - scheduled.insert(from_node); } } } diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index c4b53bd8176..1eb07206465 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -28,15 +28,14 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_duplilist.h" #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_node.h" #include "BKE_object.h" + #include "BLI_math.h" #include "BLI_utildefines.h" -} /* extern "C" */ #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/depsgraph/intern/depsgraph_registry.cc b/source/blender/depsgraph/intern/depsgraph_registry.cc index ad60b1bc4cf..3b0a0b3ea19 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.cc +++ b/source/blender/depsgraph/intern/depsgraph_registry.cc @@ -29,46 +29,33 @@ namespace DEG { -typedef set<Depsgraph *> DepsgraphStorage; -typedef map<Main *, DepsgraphStorage> MainDepsgraphMap; - -static MainDepsgraphMap g_graph_registry; +static Map<Main *, VectorSet<Depsgraph *>> g_graph_registry; void register_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; - MainDepsgraphMap::iterator it = g_graph_registry.find(bmain); - if (it == g_graph_registry.end()) { - it = g_graph_registry.insert(make_pair(bmain, DepsgraphStorage())).first; - } - DepsgraphStorage &storage = it->second; - storage.insert(depsgraph); + g_graph_registry.lookup_or_add_default(bmain).add_new(depsgraph); } void unregister_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; - MainDepsgraphMap::iterator it = g_graph_registry.find(bmain); - BLI_assert(it != g_graph_registry.end()); - - // Remove dependency graph from storage. - DepsgraphStorage &storage = it->second; - storage.erase(depsgraph); + VectorSet<Depsgraph *> &graphs = g_graph_registry.lookup(bmain); + graphs.remove(depsgraph); // If this was the last depsgraph associated with the main, remove the main entry as well. - if (storage.empty()) { - g_graph_registry.erase(bmain); + if (graphs.is_empty()) { + g_graph_registry.remove(bmain); } } -const set<Depsgraph *> &get_all_registered_graphs(Main *bmain) +ArrayRef<Depsgraph *> get_all_registered_graphs(Main *bmain) { - MainDepsgraphMap::iterator it = g_graph_registry.find(bmain); - if (it == g_graph_registry.end()) { - static DepsgraphStorage empty_storage; - return empty_storage; + VectorSet<Depsgraph *> *graphs = g_graph_registry.lookup_ptr(bmain); + if (graphs != nullptr) { + return *graphs; } - return it->second; + return {}; } } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_registry.h b/source/blender/depsgraph/intern/depsgraph_registry.h index 7517b6a0b2a..f8e5b9543f2 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.h +++ b/source/blender/depsgraph/intern/depsgraph_registry.h @@ -33,6 +33,6 @@ struct Depsgraph; void register_graph(Depsgraph *depsgraph); void unregister_graph(Depsgraph *depsgraph); -const set<Depsgraph *> &get_all_registered_graphs(Main *bmain); +ArrayRef<Depsgraph *> get_all_registered_graphs(Main *bmain); } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_relation.cc b/source/blender/depsgraph/intern/depsgraph_relation.cc index cff62540ca8..a4ec48658f5 100644 --- a/source/blender/depsgraph/intern/depsgraph_relation.cc +++ b/source/blender/depsgraph/intern/depsgraph_relation.cc @@ -30,12 +30,6 @@ namespace DEG { -/* TODO(sergey): Find a better place for this. */ -template<typename T> static void remove_from_vector(vector<T> *vector, const T &value) -{ - vector->erase(std::remove(vector->begin(), vector->end(), value), vector->end()); -} - Relation::Relation(Node *from, Node *to, const char *description) : from(from), to(to), name(description), flag(0) { @@ -52,8 +46,8 @@ Relation::Relation(Node *from, Node *to, const char *description) * * - Un-registering relation is not a cheap operation, so better to have it * as an explicit call if we need this. */ - from->outlinks.push_back(this); - to->inlinks.push_back(this); + from->outlinks.append(this); + to->inlinks.append(this); } Relation::~Relation() @@ -66,8 +60,8 @@ void Relation::unlink() { /* Sanity check. */ BLI_assert(from != nullptr && to != nullptr); - remove_from_vector(&from->outlinks, this); - remove_from_vector(&to->inlinks, this); + from->outlinks.remove_first_occurrence_and_reorder(this); + to->inlinks.remove_first_occurrence_and_reorder(this); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 1c56808ea82..0ee86088e43 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -33,7 +33,6 @@ #include "BLI_task.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" @@ -54,7 +53,6 @@ extern "C" { #define new new_ #include "BKE_screen.h" #undef new -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -495,13 +493,13 @@ void deg_graph_node_tag_zero(Main *bmain, ID *id = id_node->id_orig; /* TODO(sergey): Which recalc flags to set here? */ id_node->id_cow->recalc |= deg_recalc_flags_for_legacy_zero(); - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + + for (ComponentNode *comp_node : id_node->components.values()) { if (comp_node->type == NodeType::ANIMATION) { continue; } comp_node->tag_update(graph, update_source); } - GHASH_FOREACH_END(); deg_graph_id_tag_legacy_compat(bmain, graph, id, (IDRecalcFlag)0, update_source); } diff --git a/source/blender/depsgraph/intern/depsgraph_type.cc b/source/blender/depsgraph/intern/depsgraph_type.cc index 559bf8dfdab..92d775b0ae4 100644 --- a/source/blender/depsgraph/intern/depsgraph_type.cc +++ b/source/blender/depsgraph/intern/depsgraph_type.cc @@ -25,7 +25,6 @@ #include <cstdlib> // for BLI_assert() -#include "BLI_ghash.h" #include "BLI_utildefines.h" #include "DNA_customdata_types.h" diff --git a/source/blender/depsgraph/intern/depsgraph_type.h b/source/blender/depsgraph/intern/depsgraph_type.h index fbf5c2fd381..7016d07ae72 100644 --- a/source/blender/depsgraph/intern/depsgraph_type.h +++ b/source/blender/depsgraph/intern/depsgraph_type.h @@ -38,9 +38,14 @@ #include <map> #include <set> #include <string> -#include <unordered_map> #include <vector> +#include "BLI_map.hh" +#include "BLI_set.hh" +#include "BLI_string_ref.hh" +#include "BLI_vector.hh" +#include "BLI_vector_set.hh" + struct Depsgraph; struct CustomData_MeshMasks; @@ -48,12 +53,19 @@ struct CustomData_MeshMasks; namespace DEG { /* Commonly used types. */ +using BLI::ArrayRef; +using BLI::Map; +using BLI::Set; +using BLI::StringRef; +using BLI::StringRefNull; +using BLI::Vector; +using BLI::VectorSet; using std::deque; using std::map; using std::pair; using std::set; using std::string; -using std::unordered_map; +using std::unique_ptr; using std::vector; /* Commonly used functions. */ diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index c7f3c5cb2b6..189beb506b3 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -28,7 +28,6 @@ #include "PIL_time.h" #include "BLI_compiler_attrs.h" -#include "BLI_ghash.h" #include "BLI_gsqueue.h" #include "BLI_task.h" #include "BLI_utildefines.h" @@ -61,18 +60,17 @@ namespace { struct DepsgraphEvalState; -void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id); +void deg_task_run_func(TaskPool *pool, void *taskdata); template<typename ScheduleFunction, typename... ScheduleFunctionArgs> void schedule_children(DepsgraphEvalState *state, OperationNode *node, - const int thread_id, ScheduleFunction *schedule_function, ScheduleFunctionArgs... schedule_function_args); -void schedule_node_to_pool(OperationNode *node, const int thread_id, TaskPool *pool) +void schedule_node_to_pool(OperationNode *node, const int UNUSED(thread_id), TaskPool *pool) { - BLI_task_pool_push_from_thread(pool, deg_task_run_func, node, false, NULL, thread_id); + BLI_task_pool_push(pool, deg_task_run_func, node, false, NULL); } /* Denotes which part of dependency graph is being evaluated. */ @@ -116,9 +114,9 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod } } -void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id) +void deg_task_run_func(TaskPool *pool, void *taskdata) { - void *userdata_v = BLI_task_pool_userdata(pool); + void *userdata_v = BLI_task_pool_user_data(pool); DepsgraphEvalState *state = (DepsgraphEvalState *)userdata_v; /* Evaluate node. */ @@ -126,9 +124,7 @@ void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id) evaluate_node(state, operation_node); /* Schedule children. */ - BLI_task_pool_delayed_push_begin(pool, thread_id); - schedule_children(state, operation_node, thread_id, schedule_node_to_pool, pool); - BLI_task_pool_delayed_push_end(pool, thread_id); + schedule_children(state, operation_node, schedule_node_to_pool, pool); } bool check_operation_node_visible(OperationNode *op_node) @@ -238,7 +234,6 @@ template<typename ScheduleFunction, typename... ScheduleFunctionArgs> void schedule_node(DepsgraphEvalState *state, OperationNode *node, bool dec_parents, - const int thread_id, ScheduleFunction *schedule_function, ScheduleFunctionArgs... schedule_function_args) { @@ -271,11 +266,11 @@ void schedule_node(DepsgraphEvalState *state, if (!is_scheduled) { if (node->is_noop()) { /* skip NOOP node, schedule children right away */ - schedule_children(state, node, thread_id, schedule_function, schedule_function_args...); + schedule_children(state, node, schedule_function, schedule_function_args...); } else { /* children are scheduled once this task is completed */ - schedule_function(node, thread_id, schedule_function_args...); + schedule_function(node, 0, schedule_function_args...); } } } @@ -286,14 +281,13 @@ void schedule_graph(DepsgraphEvalState *state, ScheduleFunctionArgs... schedule_function_args) { for (OperationNode *node : state->graph->operations) { - schedule_node(state, node, false, -1, schedule_function, schedule_function_args...); + schedule_node(state, node, false, schedule_function, schedule_function_args...); } } template<typename ScheduleFunction, typename... ScheduleFunctionArgs> void schedule_children(DepsgraphEvalState *state, OperationNode *node, - const int thread_id, ScheduleFunction *schedule_function, ScheduleFunctionArgs... schedule_function_args) { @@ -307,7 +301,6 @@ void schedule_children(DepsgraphEvalState *state, schedule_node(state, child, (rel->flag & RELATION_FLAG_CYCLIC) == 0, - thread_id, schedule_function, schedule_function_args...); } @@ -330,7 +323,7 @@ void evaluate_graph_single_threaded(DepsgraphEvalState *state) BLI_gsqueue_pop(evaluation_queue, &operation_node); evaluate_node(state, operation_node); - schedule_children(state, operation_node, 0, schedule_node_to_queue, evaluation_queue); + schedule_children(state, operation_node, schedule_node_to_queue, evaluation_queue); } BLI_gsqueue_free(evaluation_queue); @@ -354,6 +347,16 @@ void depsgraph_ensure_view_layer(Depsgraph *graph) } // namespace +static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state) +{ + if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) { + return BLI_task_pool_create_no_threads(state); + } + else { + return BLI_task_pool_create_suspended(state, TASK_PRIORITY_HIGH); + } +} + /** * Evaluate all nodes tagged for updating, * \warning This is usually done as part of main loop, but may also be @@ -364,7 +367,7 @@ void depsgraph_ensure_view_layer(Depsgraph *graph) void deg_evaluate_on_refresh(Depsgraph *graph) { /* Nothing to update, early out. */ - if (BLI_gset_len(graph->entry_tags) == 0) { + if (graph->entry_tags.is_empty()) { return; } @@ -377,30 +380,20 @@ void deg_evaluate_on_refresh(Depsgraph *graph) state.graph = graph; state.do_stats = graph->debug.do_time_debug(); state.need_single_thread_pass = false; - /* Set up task scheduler and pull for threaded evaluation. */ - TaskScheduler *task_scheduler; - bool need_free_scheduler; - if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) { - task_scheduler = BLI_task_scheduler_create(1); - need_free_scheduler = true; - } - else { - task_scheduler = BLI_task_scheduler_get(); - need_free_scheduler = false; - } - TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state, TASK_PRIORITY_HIGH); /* Prepare all nodes for evaluation. */ initialize_execution(&state, graph); /* Do actual evaluation now. */ - /* First, process all Copy-On-Write nodes. */ state.stage = EvaluationStage::COPY_ON_WRITE; + TaskPool *task_pool = deg_evaluate_task_pool_create(&state); schedule_graph(&state, schedule_node_to_pool, task_pool); - BLI_task_pool_work_wait_and_reset(task_pool); + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); /* After that, process all other nodes. */ state.stage = EvaluationStage::THREADED_EVALUATION; + task_pool = deg_evaluate_task_pool_create(&state); schedule_graph(&state, schedule_node_to_pool, task_pool); BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); @@ -418,9 +411,6 @@ void deg_evaluate_on_refresh(Depsgraph *graph) } /* Clear any uncleared tags - just in case. */ deg_graph_clear_tags(graph); - if (need_free_scheduler) { - BLI_task_scheduler_free(task_scheduler); - } graph->is_evaluating = false; graph->debug.end_graph_evaluation(); 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 b87a877ae99..2f2e05d410e 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 @@ -53,7 +53,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_ID.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -92,7 +91,6 @@ extern "C" { #include "BKE_pointcache.h" #include "BKE_sequencer.h" #include "BKE_sound.h" -} #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_nodes.h" diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 990002cf2e8..ee543dcf25d 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -27,7 +27,6 @@ #include <cmath> -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math_vector.h" #include "BLI_task.h" @@ -36,12 +35,10 @@ #include "BKE_object.h" #include "BKE_scene.h" -extern "C" { #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DRW_engine.h" -} /* extern "C" */ #include "DEG_depsgraph.h" @@ -94,9 +91,9 @@ void flush_init_id_node_func(void *__restrict data_v, Depsgraph *graph = (Depsgraph *)data_v; IDNode *id_node = graph->id_nodes[i]; id_node->custom_flags = ID_STATE_NONE; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) + for (ComponentNode *comp_node : id_node->components.values()) { comp_node->custom_flags = COMPONENT_STATE_NONE; - GHASH_FOREACH_END(); + } } BLI_INLINE void flush_prepare(Depsgraph *graph) @@ -116,7 +113,7 @@ BLI_INLINE void flush_prepare(Depsgraph *graph) BLI_INLINE void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue) { - GSET_FOREACH_BEGIN (OperationNode *, op_node, graph->entry_tags) { + for (OperationNode *op_node : graph->entry_tags) { queue->push_back(op_node); op_node->scheduled = true; DEG_DEBUG_PRINTF((::Depsgraph *)graph, @@ -124,7 +121,6 @@ BLI_INLINE void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue) "Operation is entry point for update: %s\n", op_node->identifier().c_str()); } - GSET_FOREACH_END(); } BLI_INLINE void flush_handle_id_node(IDNode *id_node) @@ -231,7 +227,7 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd ID *id_orig = id_node->id_orig; ID *id_cow = id_node->id_cow; /* Gather recalc flags from all changed components. */ - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (DEG::ComponentNode *comp_node : id_node->components.values()) { if (comp_node->custom_flags != COMPONENT_STATE_DONE) { continue; } @@ -239,7 +235,6 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd BLI_assert(factory != nullptr); id_cow->recalc |= factory->id_recalc_tag(); } - GHASH_FOREACH_END(); DEG_DEBUG_PRINTF((::Depsgraph *)graph, EVAL, "Accumulated recalc bits for %s: %u\n", @@ -307,7 +302,7 @@ void invalidate_tagged_evaluated_data(Depsgraph *graph) if (!deg_copy_on_write_is_expanded(id_cow)) { continue; } - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { if (comp_node->custom_flags != COMPONENT_STATE_DONE) { continue; } @@ -322,7 +317,6 @@ void invalidate_tagged_evaluated_data(Depsgraph *graph) break; } } - GHASH_FOREACH_END(); } #else (void)graph; @@ -347,7 +341,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) graph->ctime = ctime; time_source->tag_update(graph, DEG::DEG_UPDATE_SOURCE_TIME); } - if (BLI_gset_len(graph->entry_tags) == 0) { + if (graph->entry_tags.is_empty()) { return; } /* Reset all flags, get ready for the flush. */ @@ -393,7 +387,7 @@ void deg_graph_clear_tags(Depsgraph *graph) DEPSOP_FLAG_USER_MODIFIED); } /* Clear any entry tags which haven't been flushed. */ - BLI_gset_clear(graph->entry_tags, nullptr); + graph->entry_tags.clear(); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index 2f45ea45197..2b172f824b6 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -166,7 +166,7 @@ void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) if (value.second == nullptr) { continue; } - const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); + const ModifierTypeInfo *modifier_type_info = BKE_modifier_get_info(modifier_data_id.type); BLI_assert(modifier_type_info != nullptr); modifier_type_info->freeRuntimeData(runtime); } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_stats.cc b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc index f164560ac24..9d3b1356570 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_stats.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc @@ -23,7 +23,6 @@ #include "intern/eval/deg_eval_stats.h" -#include "BLI_ghash.h" #include "BLI_utildefines.h" #include "intern/depsgraph.h" @@ -41,10 +40,9 @@ void deg_eval_stats_aggregate(Depsgraph *graph) * Those are not filled in by the evaluation engine. */ for (Node *node : graph->id_nodes) { IDNode *id_node = (IDNode *)node; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { comp_node->stats.reset_current(); } - GHASH_FOREACH_END(); id_node->stats.reset_current(); } /* Now accumulate operation timings to components and IDs. */ diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h index ffa37341ea6..ad1eba2f7ba 100644 --- a/source/blender/depsgraph/intern/node/deg_node.h +++ b/source/blender/depsgraph/intern/node/deg_node.h @@ -163,7 +163,7 @@ struct Node { * The reason why all depsgraph nodes are descended from this type (apart * from basic serialization benefits - from the typeinfo) is that we can * have relationships between these nodes. */ - typedef vector<Relation *> Relations; + typedef Vector<Relation *> Relations; string name; /* Identifier - mainly for debugging purposes. */ NodeType type; /* Structural type of node. */ diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index 54796b8965b..e2c1f74ec46 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -26,14 +26,11 @@ #include <cstring> /* required for STREQ later on. */ #include <stdio.h> -#include "BLI_ghash.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_object_types.h" #include "BKE_action.h" -} /* extern "C" */ #include "intern/node/deg_node_factory.h" #include "intern/node/deg_node_id.h" @@ -72,41 +69,10 @@ bool ComponentNode::OperationIDKey::operator==(const OperationIDKey &other) cons return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag); } -static unsigned int comp_node_hash_key(const void *key_v) -{ - const ComponentNode::OperationIDKey *key = - reinterpret_cast<const ComponentNode::OperationIDKey *>(key_v); - int opcode_as_int = static_cast<int>(key->opcode); - return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int), - BLI_ghashutil_strhash_p(key->name)); -} - -static bool comp_node_hash_key_cmp(const void *a, const void *b) -{ - const ComponentNode::OperationIDKey *key_a = - reinterpret_cast<const ComponentNode::OperationIDKey *>(a); - const ComponentNode::OperationIDKey *key_b = - reinterpret_cast<const ComponentNode::OperationIDKey *>(b); - return !(*key_a == *key_b); -} - -static void comp_node_hash_key_free(void *key_v) -{ - typedef ComponentNode::OperationIDKey OperationIDKey; - OperationIDKey *key = reinterpret_cast<OperationIDKey *>(key_v); - OBJECT_GUARDED_DELETE(key, OperationIDKey); -} - -static void comp_node_hash_value_free(void *value_v) -{ - OperationNode *op_node = reinterpret_cast<OperationNode *>(value_v); - OBJECT_GUARDED_DELETE(op_node, OperationNode); -} - ComponentNode::ComponentNode() : entry_operation(nullptr), exit_operation(nullptr), affects_directly_visible(false) { - operations_map = BLI_ghash_new(comp_node_hash_key, comp_node_hash_key_cmp, "Depsgraph id hash"); + operations_map = new Map<ComponentNode::OperationIDKey, OperationNode *>(); } /* Initialize 'component' node - from pointer data given */ @@ -121,7 +87,7 @@ ComponentNode::~ComponentNode() { clear_operations(); if (operations_map != nullptr) { - BLI_ghash_free(operations_map, comp_node_hash_key_free, comp_node_hash_value_free); + delete operations_map; } } @@ -137,7 +103,7 @@ OperationNode *ComponentNode::find_operation(OperationIDKey key) const { OperationNode *node = nullptr; if (operations_map != nullptr) { - node = (OperationNode *)BLI_ghash_lookup(operations_map, &key); + node = operations_map->lookup_default(key, nullptr); } else { for (OperationNode *op_node : operations) { @@ -203,8 +169,8 @@ OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op, op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name); /* register opnode in this component's operation set */ - OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag); - BLI_ghash_insert(operations_map, key, op_node); + OperationIDKey key(opcode, name, name_tag); + operations_map->add(key, op_node); /* set backlink */ op_node->owner = this; @@ -242,7 +208,10 @@ void ComponentNode::set_exit_operation(OperationNode *op_node) void ComponentNode::clear_operations() { if (operations_map != nullptr) { - BLI_ghash_clear(operations_map, comp_node_hash_key_free, comp_node_hash_value_free); + for (OperationNode *op_node : operations_map->values()) { + OBJECT_GUARDED_DELETE(op_node, OperationNode); + } + operations_map->clear(); } for (OperationNode *op_node : operations) { OBJECT_GUARDED_DELETE(op_node, OperationNode); @@ -261,10 +230,9 @@ void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source) } // It is possible that tag happens before finalization. if (operations_map != nullptr) { - GHASH_FOREACH_BEGIN (OperationNode *, op_node, operations_map) { + for (OperationNode *op_node : operations_map->values()) { op_node->tag_update(graph, source); } - GHASH_FOREACH_END(); } } @@ -273,13 +241,12 @@ OperationNode *ComponentNode::get_entry_operation() if (entry_operation) { return entry_operation; } - else if (operations_map != nullptr && BLI_ghash_len(operations_map) == 1) { + else if (operations_map != nullptr && operations_map->size() == 1) { OperationNode *op_node = nullptr; /* TODO(sergey): This is somewhat slow. */ - GHASH_FOREACH_BEGIN (OperationNode *, tmp, operations_map) { + for (OperationNode *tmp : operations_map->values()) { op_node = tmp; } - GHASH_FOREACH_END(); /* Cache for the subsequent usage. */ entry_operation = op_node; return op_node; @@ -295,13 +262,12 @@ OperationNode *ComponentNode::get_exit_operation() if (exit_operation) { return exit_operation; } - else if (operations_map != nullptr && BLI_ghash_len(operations_map) == 1) { + else if (operations_map != nullptr && operations_map->size() == 1) { OperationNode *op_node = nullptr; /* TODO(sergey): This is somewhat slow. */ - GHASH_FOREACH_BEGIN (OperationNode *, tmp, operations_map) { + for (OperationNode *tmp : operations_map->values()) { op_node = tmp; } - GHASH_FOREACH_END(); /* Cache for the subsequent usage. */ exit_operation = op_node; return op_node; @@ -314,12 +280,11 @@ OperationNode *ComponentNode::get_exit_operation() void ComponentNode::finalize_build(Depsgraph * /*graph*/) { - operations.reserve(BLI_ghash_len(operations_map)); - GHASH_FOREACH_BEGIN (OperationNode *, op_node, operations_map) { + operations.reserve(operations_map->size()); + for (OperationNode *op_node : operations_map->values()) { operations.push_back(op_node); } - GHASH_FOREACH_END(); - BLI_ghash_free(operations_map, comp_node_hash_key_free, nullptr); + delete operations_map; operations_map = nullptr; } diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index 38ea4005a72..41d5c130ffd 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -26,10 +26,11 @@ #include "intern/node/deg_node.h" #include "intern/node/deg_node_operation.h" +#include "BLI_ghash.h" +#include "BLI_hash.hh" #include "BLI_string.h" #include "BLI_utildefines.h" -struct GHash; struct ID; struct bPoseChannel; @@ -115,7 +116,7 @@ struct ComponentNode : public Node { /* Operations stored as a hash map, for faster build. * This hash map will be freed when graph is fully built. */ - GHash *operations_map; + Map<ComponentNode::OperationIDKey, OperationNode *> *operations_map; /* This is a "normal" list of operations, used by evaluation * and other routines after construction. */ @@ -203,3 +204,18 @@ struct BoneComponentNode : public ComponentNode { void deg_register_component_depsnodes(); } // namespace DEG + +namespace BLI { + +template<> struct DefaultHash<DEG::ComponentNode::OperationIDKey> { + uint32_t operator()(const DEG::ComponentNode::OperationIDKey &key) const + { + const int opcode_as_int = static_cast<int>(key.opcode); + return BLI_ghashutil_combine_hash( + key.name_tag, + BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int), + BLI_ghashutil_strhash_p(key.name))); + } +}; + +} // namespace BLI diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 4b6120a6985..4a7e5c4568b 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -26,16 +26,13 @@ #include <cstring> /* required for STREQ later on. */ #include <stdio.h> -#include "BLI_ghash.h" #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_ID.h" #include "DNA_anim_types.h" #include "BKE_lib_id.h" -} #include "DEG_depsgraph.h" @@ -69,34 +66,6 @@ bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const return type == other.type && STREQ(name, other.name); } -static unsigned int id_deps_node_hash_key(const void *key_v) -{ - const IDNode::ComponentIDKey *key = reinterpret_cast<const IDNode::ComponentIDKey *>(key_v); - const int type_as_int = static_cast<int>(key->type); - return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int), - BLI_ghashutil_strhash_p(key->name)); -} - -static bool id_deps_node_hash_key_cmp(const void *a, const void *b) -{ - const IDNode::ComponentIDKey *key_a = reinterpret_cast<const IDNode::ComponentIDKey *>(a); - const IDNode::ComponentIDKey *key_b = reinterpret_cast<const IDNode::ComponentIDKey *>(b); - return !(*key_a == *key_b); -} - -static void id_deps_node_hash_key_free(void *key_v) -{ - typedef IDNode::ComponentIDKey ComponentIDKey; - ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v); - OBJECT_GUARDED_DELETE(key, ComponentIDKey); -} - -static void id_deps_node_hash_value_free(void *value_v) -{ - ComponentNode *comp_node = reinterpret_cast<ComponentNode *>(value_v); - OBJECT_GUARDED_DELETE(comp_node, ComponentNode); -} - /* Initialize 'id' node - from pointer data given. */ void IDNode::init(const ID *id, const char *UNUSED(subdata)) { @@ -116,9 +85,6 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata)) visible_components_mask = 0; previously_visible_components_mask = 0; - - components = BLI_ghash_new( - id_deps_node_hash_key, id_deps_node_hash_key_cmp, "Depsgraph id components hash"); } void IDNode::init_copy_on_write(ID *id_cow_hint) @@ -158,7 +124,9 @@ void IDNode::destroy() return; } - BLI_ghash_free(components, id_deps_node_hash_key_free, id_deps_node_hash_value_free); + for (ComponentNode *comp_node : components.values()) { + OBJECT_GUARDED_DELETE(comp_node, ComponentNode); + } /* Free memory used by this CoW ID. */ if (id_cow != id_orig && id_cow != nullptr) { @@ -185,7 +153,7 @@ string IDNode::identifier() const ComponentNode *IDNode::find_component(NodeType type, const char *name) const { ComponentIDKey key(type, name); - return reinterpret_cast<ComponentNode *>(BLI_ghash_lookup(components, &key)); + return components.lookup_default(key, nullptr); } ComponentNode *IDNode::add_component(NodeType type, const char *name) @@ -196,8 +164,8 @@ ComponentNode *IDNode::add_component(NodeType type, const char *name) comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name); /* Register. */ - ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name); - BLI_ghash_insert(components, key, comp_node); + ComponentIDKey key(type, name); + components.add_new(key, comp_node); comp_node->owner = this; } return comp_node; @@ -205,7 +173,7 @@ ComponentNode *IDNode::add_component(NodeType type, const char *name) void IDNode::tag_update(Depsgraph *graph, eUpdateSource source) { - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) { + for (ComponentNode *comp_node : components.values()) { /* Relations update does explicit animation update when needed. Here we ignore animation * component to avoid loss of possible unkeyed changes. */ if (comp_node->type == NodeType::ANIMATION && source == DEG_UPDATE_SOURCE_RELATIONS) { @@ -213,30 +181,27 @@ void IDNode::tag_update(Depsgraph *graph, eUpdateSource source) } comp_node->tag_update(graph, source); } - GHASH_FOREACH_END(); } void IDNode::finalize_build(Depsgraph *graph) { /* Finalize build of all components. */ - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) { + for (ComponentNode *comp_node : components.values()) { comp_node->finalize_build(graph); } - GHASH_FOREACH_END(); visible_components_mask = get_visible_components_mask(); } IDComponentsMask IDNode::get_visible_components_mask() const { IDComponentsMask result = 0; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) { + for (ComponentNode *comp_node : components.values()) { if (comp_node->affects_directly_visible) { const int component_type_as_int = static_cast<int>(comp_node->type); BLI_assert(component_type_as_int < 64); result |= (1ULL << component_type_as_int); } } - GHASH_FOREACH_END(); return result; } diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index 80bb67f182f..c7663b50c6f 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -23,12 +23,11 @@ #pragma once +#include "BLI_ghash.h" #include "BLI_sys_types.h" #include "DNA_ID.h" #include "intern/node/deg_node.h" -struct GHash; - namespace DEG { struct ComponentNode; @@ -82,7 +81,7 @@ struct IDNode : public Node { ID *id_cow; /* Hash to make it faster to look up components. */ - GHash *components; + Map<ComponentIDKey, ComponentNode *> components; /* Additional flags needed for scene evaluation. * TODO(sergey): Only needed for until really granular updates @@ -116,3 +115,16 @@ struct IDNode : public Node { }; } // namespace DEG + +namespace BLI { + +template<> struct DefaultHash<DEG::IDNode::ComponentIDKey> { + uint32_t operator()(const DEG::IDNode::ComponentIDKey &key) const + { + const int type_as_int = static_cast<int>(key.type); + return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int), + BLI_ghashutil_strhash_p(key.name)); + } +}; + +} // namespace BLI diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 1e03d51f557..d327e1da8a1 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -25,7 +25,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_utildefines.h" #include "intern/depsgraph.h" diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 1bdc3bc5a03..6c835c6d7ae 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -23,12 +23,16 @@ #ifndef __DRW_ENGINE_H__ #define __DRW_ENGINE_H__ +#include "BLI_sys_types.h" /* for bool */ + +#include "DNA_object_enums.h" + +#include "DRW_engine_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" /* for bool */ - struct ARegion; struct DRWInstanceDataList; struct Depsgraph; @@ -47,9 +51,6 @@ struct ViewLayer; struct bContext; struct rcti; -#include "DNA_object_enums.h" -#include "DRW_engine_types.h" - void DRW_engines_register(void); void DRW_engines_free(void); @@ -77,7 +78,7 @@ typedef bool (*DRW_SelectPassFn)(eDRWSelectStage stage, void *user_data); typedef bool (*DRW_ObjectFilterFn)(struct Object *ob, void *user_data); void DRW_draw_view(const struct bContext *C); -void DRW_draw_region_engine_info(int xoffset, int yoffset); +void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height); void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, struct RenderEngineType *engine_type, diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index 13927cd5124..a6e6b30a6b1 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -73,8 +73,7 @@ static void eevee_motion_blur_camera_get_matrix_at_time(Scene *scene, /* Past matrix */ /* FIXME : This is a temporal solution that does not take care of parent animations */ /* Recalc Anim manually */ - BKE_animsys_evaluate_animdata( - scene, &camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false); + BKE_animsys_evaluate_animdata(&camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false); BKE_object_where_is_calc_time(draw_ctx->depsgraph, scene, &cam_cpy, time); /* Compute winmat */ diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 63c96ac8c25..ad90c52b08e 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -487,8 +487,8 @@ static bool eevee_volume_object_mesh_init(Scene *scene, /* Smoke Simulation */ if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && - (md = modifiers_findByType(ob, eModifierType_Fluid)) && - (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && + (md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && + (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) && ((FluidModifierData *)md)->domain != NULL) { FluidModifierData *mmd = (FluidModifierData *)md; FluidDomainSettings *mds = mmd->domain; diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index bbcfcaf777d..624eef8fa47 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -2204,7 +2204,7 @@ void OVERLAY_armature_cache_populate(OVERLAY_Data *vedata, Object *ob) static bool POSE_is_driven_by_active_armature(Object *ob) { - Object *ob_arm = modifiers_isDeformedByArmature(ob); + Object *ob_arm = BKE_modifiers_is_deformed_by_armature(ob); if (ob_arm) { const DRWContextState *draw_ctx = DRW_context_state_get(); bool is_active = OVERLAY_armature_is_pose_mode(ob_arm, draw_ctx); @@ -2214,7 +2214,7 @@ static bool POSE_is_driven_by_active_armature(Object *ob) return is_active; } else { - Object *ob_mesh_deform = modifiers_isDeformedByMeshDeform(ob); + Object *ob_mesh_deform = BKE_modifiers_is_deformed_by_meshdeform(ob); if (ob_mesh_deform) { /* Recursive. */ return POSE_is_driven_by_active_armature(ob_mesh_deform); diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index 32085890f20..af54e524445 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -1506,8 +1506,9 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob) const bool draw_xform = draw_ctx->object_mode == OB_MODE_OBJECT && (scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) && (ob->base_flag & BASE_SELECTED) && !is_select_mode; - const bool draw_volume = !from_dupli && (md = modifiers_findByType(ob, eModifierType_Fluid)) && - (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && + const bool draw_volume = !from_dupli && + (md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && + (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) && (((FluidModifierData *)md)->domain != NULL); float *color; diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 2e8119fca2f..7b08e97ac31 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -250,6 +250,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) wpd->shading = v3d->shading; if (wpd->shading.type < OB_SOLID) { + wpd->shading.light = V3D_LIGHTING_FLAT; + wpd->shading.color_type = V3D_SHADING_OBJECT_COLOR; wpd->shading.xray_alpha = 0.0f; } else if (XRAY_ENABLED(v3d)) { diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index cb0dfc0a8bf..e75ba80608b 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -321,8 +321,8 @@ void workbench_cache_populate(void *ved, Object *ob) } if (!(ob->base_flag & BASE_FROM_DUPLI)) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid); - if (md && modifier_isEnabled(wpd->scene, md, eModifierMode_Realtime)) { + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid); + if (md && BKE_modifier_is_enabled(wpd->scene, md, eModifierMode_Realtime)) { FluidModifierData *fmd = (FluidModifierData *)md; if (fmd->domain && fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) { workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 40687306b4e..401f5c76a02 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -4509,7 +4509,7 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, } } -static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) +static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata) { ExtractTaskData *data = taskdata; mesh_extract_iter( @@ -4595,7 +4595,7 @@ static void extract_task_create(TaskPool *task_pool, else { /* Single threaded extraction. */ (*task_counter)++; - extract_run(NULL, taskdata, -1); + extract_run(NULL, taskdata); MEM_freeN(taskdata); } } @@ -4685,11 +4685,11 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, double rdata_end = PIL_check_seconds_timer(); #endif - TaskScheduler *task_scheduler; TaskPool *task_pool; - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create_suspended(task_scheduler, NULL, TASK_PRIORITY_HIGH); + /* Create a suspended pool as the finalize method could be called too early. + * See `extract_run`. */ + task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH); size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t); int32_t *task_counters = MEM_callocN(counters_size, __func__); diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index 547a9a54b55..62ce34fe556 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -544,7 +544,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ ED_gpencil_tpoint_to_point(region, origin, &tpoints[i], &gps->points[i]); mul_m4_v3(ob->imat, &gps->points[i].x); bGPDspoint *pt = &gps->points[i]; - copy_v4_v4(pt->vert_color, gpd->runtime.vert_color); + copy_v4_v4(pt->vert_color, tpoints[i].vert_color); } /* Calc uv data along the stroke. */ BKE_gpencil_stroke_uv_update(gps); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 1aaead27ee7..649bcd7bbaa 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1362,7 +1362,8 @@ void DRW_mesh_batch_cache_create_requested( } /* Meh loose Scene const correctness here. */ - const bool use_subsurf_fdots = scene ? modifiers_usesSubsurfFacedots((Scene *)scene, ob) : false; + const bool use_subsurf_fdots = scene ? BKE_modifiers_uses_subsurf_facedots((Scene *)scene, ob) : + false; if (do_uvcage) { mesh_buffer_cache_create_requested(cache, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 9f84d47a4fb..639c62e5e44 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1068,7 +1068,7 @@ static void drw_engines_draw_text(void) } /* Draw render engine info. */ -void DRW_draw_region_engine_info(int xoffset, int yoffset) +void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height) { LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { DrawEngineType *engine = link->data; @@ -1091,8 +1091,8 @@ void DRW_draw_region_engine_info(int xoffset, int yoffset) if (*chr_current == '\n') { char info[GPU_INFO_SIZE]; BLI_strncpy(info, chr_start, line_len + 1); - yoffset -= U.widget_unit; - BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info)); + *yoffset -= line_height; + BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); /* Re-start counting. */ chr_start = chr_current + 1; @@ -1102,8 +1102,8 @@ void DRW_draw_region_engine_info(int xoffset, int yoffset) char info[GPU_INFO_SIZE]; BLI_strncpy(info, chr_start, line_len + 1); - yoffset -= U.widget_unit; - BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info)); + *yoffset -= line_height; + BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); BLF_disable(font_id, BLF_SHADOW); } @@ -2027,7 +2027,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact); if (obweight) { /* Only use Armature pose selection, when connected armature is in pose mode. */ - Object *ob_armature = modifiers_isDeformedByArmature(obweight); + Object *ob_armature = BKE_modifiers_is_deformed_by_armature(obweight); if (ob_armature && ob_armature->mode == OB_MODE_POSE) { obpose = ob_armature; } diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index b451cfb1d05..7eac082a9e1 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -99,6 +99,10 @@ static void drw_deferred_shader_compilation_exec(void *custom_data, DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data; void *gl_context = comp->gl_context; +#if TRUST_NO_ONE + BLI_assert(gl_context != NULL); +#endif + WM_opengl_context_activate(gl_context); while (true) { diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index d48e09e0504..cd17a490240 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -51,6 +51,7 @@ #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" #include "DNA_volume_types.h" @@ -3033,6 +3034,83 @@ static bAnimChannelType ACF_DSVOLUME = { acf_dsvolume_setting_ptr /* pointer for setting */ }; +/* Simulation Expander ----------------------------------------- */ + +static int acf_dssimulation_icon(bAnimListElem *UNUSED(ale)) +{ + /* TODO: Use correct icon. */ + return ICON_PHYSICS; +} + +static int acf_dssimulation_setting_flag(bAnimContext *UNUSED(ac), + eAnimChannel_Settings setting, + bool *neg) +{ + /* clear extra return data first */ + *neg = false; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return SIM_DS_EXPAND; + + case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ + return ADT_NLA_EVAL_OFF; + + case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ + *neg = true; + return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; + + default: /* unsupported */ + return 0; + } +} + +static void *acf_dssimulation_setting_ptr(bAnimListElem *ale, + eAnimChannel_Settings setting, + short *type) +{ + Simulation *simulation = (Simulation *)ale->data; + + /* clear extra return data first */ + *type = 0; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return GET_ACF_FLAG_PTR(simulation->flag, type); + + case ACHANNEL_SETTING_SELECT: /* selected */ + case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ + case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ + if (simulation->adt) + return GET_ACF_FLAG_PTR(simulation->adt->flag, type); + return NULL; + + default: /* unsupported */ + return NULL; + } +} + +static bAnimChannelType ACF_DSSIMULATION = { + "Simulation Expander", /* type name */ + ACHANNEL_ROLE_EXPANDER, /* role */ + + acf_generic_dataexpand_color, /* backdrop color */ + acf_generic_dataexpand_backdrop, /* backdrop */ + acf_generic_indention_1, /* indent level */ + acf_generic_basic_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_generic_idblock_name_prop, /* name prop */ + acf_dssimulation_icon, /* icon */ + + acf_generic_dataexpand_setting_valid, /* has setting */ + acf_dssimulation_setting_flag, /* flag for setting */ + acf_dssimulation_setting_ptr /* pointer for setting */ +}; + /* GPencil Expander ------------------------------------------- */ // TODO: just get this from RNA? @@ -4049,6 +4127,7 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_DSHAIR; /* Hair Channel */ animchannelTypeInfo[type++] = &ACF_DSPOINTCLOUD; /* PointCloud Channel */ animchannelTypeInfo[type++] = &ACF_DSVOLUME; /* Volume Channel */ + animchannelTypeInfo[type++] = &ACF_DSSIMULATION; /* Simulation Channel */ animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 4e3dc3cb220..a7ca84eb6c6 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -138,7 +138,8 @@ void ANIM_set_active_channel(bAnimContext *ac, case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* need to verify that this data is valid for now */ if (ale->adt) { ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE); @@ -194,7 +195,8 @@ void ANIM_set_active_channel(bAnimContext *ac, case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* need to verify that this data is valid for now */ if (ale && ale->adt) { ale->adt->flag |= ADT_UI_ACTIVE; @@ -332,7 +334,8 @@ void ANIM_deselect_anim_channels( case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) { sel = ACHANNEL_SETFLAG_CLEAR; } @@ -428,7 +431,8 @@ void ANIM_deselect_anim_channels( case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* need to verify that this data is valid for now */ if (ale->adt) { ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED); @@ -2965,7 +2969,8 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* sanity checking... */ if (ale->adt) { /* select/deselect */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 4dc0bef3a1b..2b9dfe105bc 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -67,6 +67,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" #include "DNA_userdef_types.h" @@ -86,6 +87,7 @@ #include "BKE_collection.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_key.h" #include "BKE_layer.h" @@ -826,6 +828,18 @@ static bAnimListElem *make_new_animlistelem(void *data, ale->adt = BKE_animdata_from_id(data); break; } + case ANIMTYPE_DSSIMULATION: { + Simulation *simulation = (Simulation *)data; + AnimData *adt = simulation->adt; + + ale->flag = FILTER_SIMULATION_OBJD(simulation); + + ale->key_data = (adt) ? adt->action : NULL; + ale->datatype = ALE_ACT; + + ale->adt = BKE_animdata_from_id(data); + break; + } case ANIMTYPE_DSSKEY: { Key *key = (Key *)data; AnimData *adt = key->adt; @@ -2414,7 +2428,7 @@ static size_t animdata_filter_ds_modifiers( afm.filter_mode = filter_mode; /* 2) walk over dependencies */ - modifiers_foreachIDLink(ob, animfilter_modifier_idpoin_cb, &afm); + BKE_modifiers_foreach_ID_link(ob, animfilter_modifier_idpoin_cb, &afm); /* 3) extract data from the context, merging it back into the standard list */ if (afm.items) { diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 2db381dfc69..40cd368e02b 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -73,15 +73,9 @@ static bool change_frame_poll(bContext *C) * this shouldn't show up in 3D editor (or others without 2D timeline view) via search */ if (area) { - if (ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) { + if (ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP, SPACE_GRAPH)) { return true; } - else if (area->spacetype == SPACE_GRAPH) { - /* NOTE: Graph Editor has special version which does some extra stuff. - * No need to show the generic error message for that case though! - */ - return false; - } } CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active"); diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 3ae4e3bf998..82e24eaa6e3 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -40,6 +40,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_report.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index e22fddc6d67..2dae4e8b4c5 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -633,7 +633,7 @@ bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const BLI_rctf_transform_pt_v(data_lasso->rectf_view, data_lasso->rectf_scaled, xy_view, xy); if (BLI_lasso_is_point_inside( - data_lasso->mcords, data_lasso->mcords_tot, xy_view[0], xy_view[1], INT_MAX)) { + data_lasso->mcoords, data_lasso->mcoords_len, xy_view[0], xy_view[1], INT_MAX)) { return true; } } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 49e936d22aa..04061ceea51 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -50,6 +50,7 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_key.h" diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index aa1bceb2674..544d86d4c47 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -265,7 +265,7 @@ void ED_armature_bone_rename(Main *bmain, } } - if (modifiers_usesArmature(ob, arm)) { + if (BKE_modifiers_uses_armature(ob, arm)) { bDeformGroup *dg = BKE_object_defgroup_find_name(ob, oldname); if (dg) { BLI_strncpy(dg->name, newname, MAXBONENAME); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index bc854747a68..5f3b876efaf 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -42,7 +42,7 @@ #include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_context.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_report.h" diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index b637a57f7c0..61d8856afbc 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -418,7 +418,7 @@ static void add_verts_to_dgroups(ReportList *reports, BKE_mesh_foreach_mapped_vert_coords_get(me_eval, verts, mesh->totvert); vertsfilled = 1; } - else if (modifiers_findByType(ob, eModifierType_Subsurf)) { + else if (BKE_modifiers_findby_type(ob, eModifierType_Subsurf)) { /* is subsurf on? Lets use the verts on the limit surface then. * = same amount of vertices as mesh, but vertices moved to the * subsurfed position, like for 'optimal'. */ diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 6028ddb216f..d8a6a22a7df 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1549,7 +1549,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind } } else { - modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)"); + BKE_modifier_set_error(&mmd->modifier, "Failed to find bind solution (increase precision?)"); error("Mesh Deform: failed to find bind solution."); break; } @@ -1753,7 +1753,7 @@ void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd, int totvert, float cagemat[4][4]) { - MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)modifier_get_original( + MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)BKE_modifier_get_original( &mmd->modifier); MeshDeformBind mdb; MVert *mvert; @@ -1799,7 +1799,7 @@ void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd, MEM_freeN(mdb.vertexcos); /* compact weights */ - modifier_mdef_compact_influences((ModifierData *)mmd_orig); + BKE_modifier_mdef_compact_influences((ModifierData *)mmd_orig); end_progress_bar(); waitcursor(0); diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index ce652b0eaf4..9525fcf2154 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -263,7 +263,7 @@ void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_se Object *ob_active = OBACT(view_layer); BLI_assert(ob_active && (ob_active->mode & OB_MODE_WEIGHT_PAINT)); VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob_active, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob_active, &virtualModifierData); for (; md; md = md->next) { if (md->type == eModifierType_Armature) { ArmatureModifierData *amd = (ArmatureModifierData *)md; diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index ae08aee3c47..481282d6df3 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -544,71 +544,56 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) /* only if all channels exist, proceed */ if (fcu_w && fcu_x && fcu_y && fcu_z) { - float quat_prev[4], quat_prev_orig[4]; - float quat_next[4], quat_next_orig[4]; - float quat_curr[4], quat_curr_orig[4]; float quat_final[4]; - copy_qt_qt(quat_curr_orig, pchan->quat); - - /* get 2 quats */ - quat_prev_orig[0] = evaluate_fcurve(fcu_w, prevFrameF); - quat_prev_orig[1] = evaluate_fcurve(fcu_x, prevFrameF); - quat_prev_orig[2] = evaluate_fcurve(fcu_y, prevFrameF); - quat_prev_orig[3] = evaluate_fcurve(fcu_z, prevFrameF); - - quat_next_orig[0] = evaluate_fcurve(fcu_w, nextFrameF); - quat_next_orig[1] = evaluate_fcurve(fcu_x, nextFrameF); - quat_next_orig[2] = evaluate_fcurve(fcu_y, nextFrameF); - quat_next_orig[3] = evaluate_fcurve(fcu_z, nextFrameF); - - normalize_qt_qt(quat_prev, quat_prev_orig); - normalize_qt_qt(quat_next, quat_next_orig); - normalize_qt_qt(quat_curr, quat_curr_orig); - /* perform blending */ if (pso->mode == POSESLIDE_BREAKDOWN) { /* Just perform the interpolation between quat_prev and * quat_next using pso->percentage as a guide. */ - interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage); - } - else if (pso->mode == POSESLIDE_PUSH) { - float quat_diff[4]; + float quat_prev[4]; + float quat_next[4]; + + quat_prev[0] = evaluate_fcurve(fcu_w, prevFrameF); + quat_prev[1] = evaluate_fcurve(fcu_x, prevFrameF); + quat_prev[2] = evaluate_fcurve(fcu_y, prevFrameF); + quat_prev[3] = evaluate_fcurve(fcu_z, prevFrameF); - /* calculate the delta transform from the previous to the current */ - /* TODO: investigate ways to favor one transform more? */ - sub_qt_qtqt(quat_diff, quat_curr, quat_prev); + quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF); + quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF); + quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF); + quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF); - /* increase the original by the delta transform, by an amount determined by percentage */ - add_qt_qtqt(quat_final, quat_curr, quat_diff, pso->percentage); + normalize_qt(quat_prev); + normalize_qt(quat_next); - normalize_qt(quat_final); + interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage); } else { - BLI_assert(pso->mode == POSESLIDE_RELAX); - float quat_interp[4], quat_final_prev[4]; - /* TODO: maybe a sensitivity ctrl on top of this is needed */ - int iters = (int)ceil(10.0f * pso->percentage); + /* POSESLIDE_PUSH and POSESLIDE_RELAX. */ + float quat_breakdown[4]; + float quat_curr[4]; - copy_qt_qt(quat_final, quat_curr); + copy_qt_qt(quat_curr, pchan->quat); - /* perform this blending several times until a satisfactory result is reached */ - while (iters-- > 0) { - /* calculate the interpolation between the endpoints */ - interp_qt_qtqt(quat_interp, - quat_prev, - quat_next, - (cframe - pso->prevFrame) / (pso->nextFrame - pso->prevFrame)); + quat_breakdown[0] = evaluate_fcurve(fcu_w, cframe); + quat_breakdown[1] = evaluate_fcurve(fcu_x, cframe); + quat_breakdown[2] = evaluate_fcurve(fcu_y, cframe); + quat_breakdown[3] = evaluate_fcurve(fcu_z, cframe); - normalize_qt_qt(quat_final_prev, quat_final); + normalize_qt(quat_breakdown); + normalize_qt(quat_curr); - /* tricky interpolations - blending between original and new */ - interp_qt_qtqt(quat_final, quat_final_prev, quat_interp, 1.0f / 6.0f); + if (pso->mode == POSESLIDE_PUSH) { + interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + pso->percentage); + } + else { + BLI_assert(pso->mode == POSESLIDE_RELAX); + interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->percentage); } } /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */ - quat_to_compatible_quat(pchan->quat, quat_final, quat_curr_orig); + quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat); } /* free the path now */ diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 31c89ca9f43..1d2bf152777 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -1240,7 +1240,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) workob.adt = ob->adt; workob.pose = dummyPose; - BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false); /* copy back values, but on selected bones only */ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index adaf4ab2459..22df7bbbf31 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -90,14 +90,54 @@ typedef enum eDrawStrokeFlags { /* ----- Tool Buffer Drawing ------ */ +static void annotation_draw_stroke_arrow_buffer(uint pos, + const float *corner_point, + const float *arrow_coords, + const int arrow_style) +{ + immBeginAtMost(GPU_PRIM_LINE_STRIP, arrow_style); + + switch (arrow_style) { + case GP_STROKE_ARROWSTYLE_SEGMENT: + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + break; + case GP_STROKE_ARROWSTYLE_CLOSED: + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + immVertex2f(pos, arrow_coords[4], arrow_coords[5]); + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + break; + case GP_STROKE_ARROWSTYLE_OPEN: + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, corner_point[0], corner_point[1]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + break; + case GP_STROKE_ARROWSTYLE_SQUARE: + immVertex2f(pos, corner_point[0], corner_point[1]); + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, arrow_coords[4], arrow_coords[5]); + immVertex2f(pos, arrow_coords[6], arrow_coords[7]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + immVertex2f(pos, corner_point[0], corner_point[1]); + break; + default: + break; + } + immEnd(); +} + /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ -static void annotation_draw_stroke_buffer(const tGPspoint *points, - int totpoints, +static void annotation_draw_stroke_buffer(bGPdata *gps, short thickness, short dflag, - short sflag, const float ink[4]) { + bGPdata_Runtime runtime = gps->runtime; + const tGPspoint *points = runtime.sbuffer; + int totpoints = runtime.sbuffer_used; + short sflag = runtime.sbuffer_sflag; + int draw_points = 0; /* error checking */ @@ -176,6 +216,26 @@ static void annotation_draw_stroke_buffer(const tGPspoint *points, } immEnd(); + + /* Draw arrow stroke. */ + if (totpoints > 1) { + /* Draw ending arrow stroke. */ + if ((sflag & GP_STROKE_USE_ARROW_END) && + (runtime.arrow_end_style != GP_STROKE_ARROWSTYLE_NONE)) { + float end[2]; + copy_v2_fl2(end, points[1].x, points[1].y); + annotation_draw_stroke_arrow_buffer(pos, end, runtime.arrow_end, runtime.arrow_end_style); + } + /* Draw starting arrow stroke. */ + if ((sflag & GP_STROKE_USE_ARROW_START) && + (runtime.arrow_start_style != GP_STROKE_ARROWSTYLE_NONE)) { + float start[2]; + copy_v2_fl2(start, points[0].x, points[0].y); + annotation_draw_stroke_arrow_buffer( + pos, start, runtime.arrow_start, runtime.arrow_start_style); + } + } + immUnbindProgram(); } @@ -524,131 +584,6 @@ static void annotation_draw_strokes(const bGPDframe *gpf, GPU_program_point_size(false); } -/* Draw selected verts for strokes being edited */ -static void annotation_draw_strokes_edit(bGPDlayer *gpl, - const bGPDframe *gpf, - int offsx, - int offsy, - int winx, - int winy, - short dflag, - float alpha) -{ - /* if alpha 0 do not draw */ - if (alpha == 0.0f) { - return; - } - - const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0; - int mask_orig = 0; - - /* set up depth masks... */ - if (dflag & GP_DRAWDATA_ONLY3D) { - if (no_xray) { - glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); - glDepthMask(0); - GPU_depth_test(true); - - /* first arg is normally rv3d->dist, but this isn't - * available here and seems to work quite well without */ - bglPolygonOffset(1.0f, 1.0f); - } - } - - GPU_program_point_size(true); - - /* draw stroke verts */ - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* check if stroke can be drawn */ - if (annotation_can_draw_stroke(gps, dflag) == false) { - continue; - } - - /* Optimization: only draw points for selected strokes - * We assume that selected points can only occur in - * strokes that are selected too. - */ - if ((gps->flag & GP_STROKE_SELECT) == 0) { - continue; - } - - /* Get size of verts: - * - The selected state needs to be larger than the unselected state so that - * they stand out more. - * - We use the theme setting for size of the unselected verts - */ - float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE); - float vsize; - if ((int)bsize > 8) { - vsize = 10.0f; - bsize = 8.0f; - } - else { - vsize = bsize + 2; - } - - /* Why? */ - UNUSED_VARS(vsize); - - float selectColor[4]; - UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor); - selectColor[3] = alpha; - - GPUVertFormat *format = immVertexFormat(); - uint pos; /* specified later */ - uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - - if (gps->flag & GP_STROKE_3DSPACE) { - pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); - } - else { - pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR); - } - - immBegin(GPU_PRIM_POINTS, gps->totpoints); - - /* Draw all the stroke points (selected or not) */ - bGPDspoint *pt = gps->points; - for (int i = 0; i < gps->totpoints; i++, pt++) { - /* size and color first */ - immAttr3fv(color, gpl->color); - immAttr1f(size, bsize); - - /* then position */ - if (gps->flag & GP_STROKE_3DSPACE) { - immVertex3fv(pos, &pt->x); - } - else { - float co[2]; - annotation_calc_2d_stroke_fxy(&pt->x, gps->flag, offsx, offsy, winx, winy, co); - immVertex2fv(pos, co); - } - } - - immEnd(); - immUnbindProgram(); - } - - GPU_program_point_size(false); - - /* clear depth mask */ - if (dflag & GP_DRAWDATA_ONLY3D) { - if (no_xray) { - glDepthMask(mask_orig); - GPU_depth_test(false); - - bglPolygonOffset(0.0, 0.0); -#if 0 - glDisable(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(0, 0); -#endif - } - } -} - /* ----- General Drawing ------ */ /* draw onion-skinning for a layer */ static void annotation_draw_onionskins( @@ -724,7 +659,7 @@ static void annotation_draw_onionskins( /* loop over gpencil data layers, drawing them */ static void annotation_draw_data_layers( - bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, float alpha) + bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { float ink[4]; @@ -767,21 +702,6 @@ static void annotation_draw_data_layers( /* draw the strokes already in active frame */ annotation_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, lthick, ink); - /* Draw verts of selected strokes: - * - when doing OpenGL renders, we don't want to be showing these, as that ends up - * flickering - * - locked layers can't be edited, so there's no point showing these verts - * as they will have no bearings on what gets edited - * - only show when in editmode, since operators shouldn't work otherwise - * (NOTE: doing it this way means that the toggling editmode - * shows visible change immediately). - */ - /* XXX: perhaps we don't want to show these when users are drawing... */ - if ((G.f & G_FLAG_RENDER_VIEWPORT) == 0 && (gpl->flag & GP_LAYER_LOCKED) == 0 && - (gpd->flag & GP_DATA_STROKE_EDITMODE)) { - annotation_draw_strokes_edit(gpl, gpf, offsx, offsy, winx, winy, dflag, alpha); - } - /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) */ @@ -793,67 +713,14 @@ static void annotation_draw_data_layers( * It should also be noted that sbuffer contains temporary point types * i.e. tGPspoints NOT bGPDspoints */ - annotation_draw_stroke_buffer(gpd->runtime.sbuffer, - gpd->runtime.sbuffer_used, - lthick, - dflag, - gpd->runtime.sbuffer_sflag, - ink); + annotation_draw_stroke_buffer(gpd, lthick, dflag, ink); } } } -/* draw a short status message in the top-right corner */ -static void annotation_draw_status_text(const bGPdata *gpd, ARegion *region) -{ - - /* Cannot draw any status text when drawing OpenGL Renders */ - if (G.f & G_FLAG_RENDER_VIEWPORT) { - return; - } - - /* Get bounds of region - Necessary to avoid problems with region overlap */ - const rcti *rect = ED_region_visible_rect(region); - - /* for now, this should only be used to indicate when we are in stroke editmode */ - if (gpd->flag & GP_DATA_STROKE_EDITMODE) { - const char *printable = IFACE_("GPencil Stroke Editing"); - float printable_size[2]; - - int font_id = BLF_default(); - - BLF_width_and_height( - font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - - int xco = (rect->xmax - U.widget_unit) - (int)printable_size[0]; - int yco = (rect->ymax - U.widget_unit); - - /* text label */ - UI_FontThemeColor(font_id, TH_TEXT_HI); -#ifdef WITH_INTERNATIONAL - BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); -#else - BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); -#endif - - /* grease pencil icon... */ - // XXX: is this too intrusive? - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - - xco -= U.widget_unit; - yco -= (int)printable_size[1] / 2; - - UI_icon_draw(xco, yco, ICON_GREASEPENCIL); - - GPU_blend(false); - } -} - /* draw grease-pencil datablock */ static void annotation_draw_data( - bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, float alpha) + bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { /* turn on smooth lines (i.e. anti-aliasing) */ GPU_line_smooth(true); @@ -864,7 +731,7 @@ static void annotation_draw_data( GPU_blend(true); /* draw! */ - annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha); + annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag); /* turn off alpha blending, then smooth lines */ GPU_blend(false); // alpha blending @@ -884,7 +751,6 @@ static void annotation_draw_data_all(Scene *scene, const char spacetype) { bGPdata *gpd_source = NULL; - float alpha = 1.0f; if (scene) { if (spacetype == SPACE_VIEW3D) { @@ -897,14 +763,14 @@ static void annotation_draw_data_all(Scene *scene, } if (gpd_source) { - annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag, alpha); + annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag); } } /* scene/clip data has already been drawn, only object/track data is drawn here * if gpd_source == gpd, we don't have any object/track data and we can skip */ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) { - annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha); + annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag); } } @@ -1026,11 +892,6 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d) annotation_draw_data_all( scene, gpd, 0, 0, region->winx, region->winy, CFRA, dflag, area->spacetype); - - /* draw status text (if in screen/pixel-space) */ - if (!onlyv2d) { - annotation_draw_status_text(gpd, region); - } } /* draw annotations sketches to specified 3d-view assuming that matrices are already set diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 8d50e24b7f0..c53b90fbfee 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -100,6 +100,9 @@ typedef enum eGPencil_PaintFlags { GP_PAINTFLAG_STROKEADDED = (1 << 1), GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2), GP_PAINTFLAG_SELECTMASK = (1 << 3), + /* Flags used to indicate if stabilization is being used. */ + GP_PAINTFLAG_USE_STABILIZER = (1 << 7), + GP_PAINTFLAG_USE_STABILIZER_TEMP = (1 << 8), } eGPencil_PaintFlags; /* Temporary 'Stroke' Operation data @@ -148,6 +151,11 @@ typedef struct tGPsdata { /** radius of influence for eraser. */ short radius; + /* Stabilizer. */ + float stabilizer_factor; + char stabilizer_radius; + void *stabilizer_cursor; + /** current mouse-position. */ float mval[2]; /** previous recorded mouse-position. */ @@ -278,6 +286,18 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2 * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand */ } + /* If lazy mouse, check minimum distance. */ + else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + if ((dx * dx + dy * dy) > (p->stabilizer_radius * p->stabilizer_radius)) { + return true; + } + else { + /* If the mouse is moving within the radius of the last move, + * don't update the mouse position. This allows sharp turns. */ + copy_v2_v2(p->mval, p->mvalo); + return false; + } + } else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) { return true; @@ -418,6 +438,85 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) copy_v2_v2(&ptc->x, c); } +static void gp_stroke_arrow_calc_points_segment(float stroke_points[8], + const float ref_point[2], + const float dir_cw[2], + const float dir_ccw[2], + const float lenght, + const float sign) +{ + stroke_points[0] = ref_point[0] + dir_cw[0] * lenght * sign; + stroke_points[1] = ref_point[1] + dir_cw[1] * lenght * sign; + stroke_points[2] = ref_point[0] + dir_ccw[0] * lenght * sign; + stroke_points[3] = ref_point[1] + dir_ccw[1] * lenght * sign; +} + +static void gp_stroke_arrow_calc_points(tGPspoint *point, + const float stroke_dir[2], + float corner[2], + float stroke_points[8], + const int arrow_style) +{ + const int arrow_lenght = 8; + float norm_dir[2]; + copy_v2_v2(norm_dir, stroke_dir); + normalize_v2(norm_dir); + const float inv_norm_dir_clockwise[2] = {norm_dir[1], -norm_dir[0]}; + const float inv_norm_dir_counterclockwise[2] = {-norm_dir[1], norm_dir[0]}; + + switch (arrow_style) { + case GP_STROKE_ARROWSTYLE_OPEN: + mul_v2_fl(norm_dir, arrow_lenght); + stroke_points[0] = corner[0] + inv_norm_dir_clockwise[0] * arrow_lenght + norm_dir[0]; + stroke_points[1] = corner[1] + inv_norm_dir_clockwise[1] * arrow_lenght + norm_dir[1]; + stroke_points[2] = corner[0] + inv_norm_dir_counterclockwise[0] * arrow_lenght + norm_dir[0]; + stroke_points[3] = corner[1] + inv_norm_dir_counterclockwise[1] * arrow_lenght + norm_dir[1]; + break; + case GP_STROKE_ARROWSTYLE_SEGMENT: + gp_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght, + 1.0f); + break; + case GP_STROKE_ARROWSTYLE_CLOSED: + mul_v2_fl(norm_dir, arrow_lenght); + if (point != NULL) { + add_v2_v2(&point->x, norm_dir); + copy_v2_v2(corner, &point->x); + } + gp_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght, + -1.0f); + stroke_points[4] = corner[0] - norm_dir[0]; + stroke_points[5] = corner[1] - norm_dir[1]; + break; + case GP_STROKE_ARROWSTYLE_SQUARE: + mul_v2_fl(norm_dir, arrow_lenght * 1.5f); + if (point != NULL) { + add_v2_v2(&point->x, norm_dir); + copy_v2_v2(corner, &point->x); + } + gp_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght * 0.75f, + -1.0f); + stroke_points[4] = stroke_points[0] - norm_dir[0]; + stroke_points[5] = stroke_points[1] - norm_dir[1]; + stroke_points[6] = stroke_points[2] - norm_dir[0]; + stroke_points[7] = stroke_points[3] - norm_dir[1]; + break; + default: + break; + } +} + /* add current stroke-point to buffer (returns whether point was successfully added) */ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime) { @@ -457,6 +556,32 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */ gpd->runtime.sbuffer_used = 2; + + /* Arrows. */ + if (gpd->runtime.sbuffer_sflag & (GP_STROKE_USE_ARROW_START | GP_STROKE_USE_ARROW_END)) { + /* Store start and end point coords for arrows. */ + float end[2]; + copy_v2_v2(end, &pt->x); + pt = ((tGPspoint *)(gpd->runtime.sbuffer)); + float start[2]; + copy_v2_v2(start, &pt->x); + + /* Arrow end corner. */ + if (gpd->runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_END) { + pt++; + float e_heading[2] = {start[0] - end[0], start[1] - end[1]}; + /* Calculate points for ending arrow. */ + gp_stroke_arrow_calc_points( + pt, e_heading, end, gpd->runtime.arrow_end, gpd->runtime.arrow_end_style); + } + /* Arrow start corner. */ + if (gpd->runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) { + float s_heading[2] = {end[0] - start[0], end[1] - start[1]}; + /* Calculate points for starting arrow. */ + gp_stroke_arrow_calc_points( + NULL, s_heading, start, gpd->runtime.arrow_start, gpd->runtime.arrow_start_style); + } + } } /* can keep carrying on this way :) */ @@ -481,16 +606,20 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* increment counters */ gpd->runtime.sbuffer_used++; - /* smooth while drawing previous points with a reduction factor for previous */ - for (int s = 0; s < 3; s++) { - gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s); + + /* Don't smooth if stabilizer is on. */ + if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { + /* smooth while drawing previous points with a reduction factor for previous */ + for (int s = 0; s < 3; s++) { + gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s); + } } return GP_STROKEADD_NORMAL; } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { /* get pointer to destination point */ - pt = (tGPspoint *)(gpd->runtime.sbuffer); + pt = (tGPspoint *)gpd->runtime.sbuffer; /* store settings */ copy_v2_v2(&pt->x, mval); @@ -552,6 +681,123 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure return GP_STROKEADD_INVALID; } +static void gp_stroke_arrow_init_point_default(bGPDspoint *pt) +{ + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt->time = 1.0f; +} + +static void gp_stroke_arrow_init_conv_point(bGPDspoint *pt, const float point[3]) +{ + copy_v3_v3(&pt->x, point); + gp_stroke_arrow_init_point_default(pt); +} + +static void gp_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]. */ + float real_co[2] = {co[co_idx], co[co_idx + 1]}; + copy_v2_v2(&ptc->x, real_co); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gp_stroke_arrow_init_point_default(pt); +} + +static void gp_stroke_arrow_allocate(bGPDstroke *gps, const int totpoints) +{ + /* Copy appropriate settings for stroke. */ + gps->totpoints = totpoints; + /* Allocate enough memory for a continuous array for storage points. */ + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); +} + +static void gp_arrow_create_open(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float corner_point[3], + const float arrow_points[8]) +{ + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_conv_point(pt, corner_point); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); +} + +static void gp_arrow_create_segm(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float arrow_points[8]) +{ + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); +} + +static void gp_arrow_create_closed(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float arrow_points[8]) +{ + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); +} + +static void gp_arrow_create_square(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float corner_point[3], + const float arrow_points[8]) +{ + gp_stroke_arrow_init_conv_point(pt, corner_point); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 6); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + pt++; + gp_stroke_arrow_init_conv_point(pt, corner_point); +} + +static void gp_arrow_create(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + bGPDstroke *arrow_stroke, + const float arrow_points[8], + const int style) +{ + float corner_conv[3]; + copy_v3_v3(corner_conv, &pt->x); + + switch (style) { + case GP_STROKE_ARROWSTYLE_SEGMENT: + gp_arrow_create_segm(p, ptc, pt, arrow_points); + break; + case GP_STROKE_ARROWSTYLE_CLOSED: + gp_arrow_create_closed(p, ptc, pt, arrow_points); + break; + case GP_STROKE_ARROWSTYLE_OPEN: + gp_arrow_create_open(p, ptc, pt, corner_conv, arrow_points); + break; + case GP_STROKE_ARROWSTYLE_SQUARE: + gp_arrow_create_square(p, ptc, pt, corner_conv, arrow_points); + break; + default: + break; + } + /* Link stroke to frame. */ + BLI_addtail(&p->gpf->strokes, arrow_stroke); +} + /* make a new stroke from the buffer data */ static void gp_stroke_newfrombuffer(tGPsdata *p) { @@ -637,17 +883,61 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } if (totelem == 2) { - /* last point if applicable */ - ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1); + bGPdata_Runtime runtime = gpd->runtime; - /* convert screen-coordinates to appropriate coordinates (and store them) */ + /* Last point if applicable. */ + ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1); + + /* Convert screen-coordinates to appropriate coordinates (and store them). */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure and time */ + /* Copy pressure and time. */ pt->pressure = ptc->pressure; pt->strength = ptc->strength; CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt->time = ptc->time; + + /** Create arrow strokes. **/ + /* End arrow stroke. */ + if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_END) && + (runtime.arrow_end_style != GP_STROKE_ARROWSTYLE_NONE)) { + int totarrowpoints = runtime.arrow_end_style; + + /* Setting up arrow stroke. */ + bGPDstroke *e_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false); + gp_stroke_arrow_allocate(e_arrow_gps, totarrowpoints); + + /* Set pointer to first non-initialized point. */ + pt = e_arrow_gps->points + (e_arrow_gps->totpoints - totarrowpoints); + + /* End point. */ + ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gp_stroke_arrow_init_point_default(pt); + + /* Fill and convert arrow points to create arrow shape. */ + gp_arrow_create(p, ptc, pt, e_arrow_gps, runtime.arrow_end, runtime.arrow_end_style); + } + /* Start arrow stroke. */ + if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) && + (runtime.arrow_start_style != GP_STROKE_ARROWSTYLE_NONE)) { + int totarrowpoints = runtime.arrow_start_style; + + /* Setting up arrow stroke. */ + bGPDstroke *s_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false); + gp_stroke_arrow_allocate(s_arrow_gps, totarrowpoints); + + /* Set pointer to first non-initialized point. */ + pt = s_arrow_gps->points + (s_arrow_gps->totpoints - totarrowpoints); + + /* Start point. */ + ptc = runtime.sbuffer; + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gp_stroke_arrow_init_point_default(pt); + + /* Fill and convert arrow points to create arrow shape. */ + gp_arrow_create(p, ptc, pt, s_arrow_gps, runtime.arrow_start, runtime.arrow_start_style); + } } } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { @@ -1456,6 +1746,67 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en p); } } +static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) +{ + ARegion *region = CTX_wm_region(C); + tGPsdata *p = (tGPsdata *)p_ptr; + bGPdata_Runtime runtime = p->gpd->runtime; + const tGPspoint *points = runtime.sbuffer; + int totpoints = runtime.sbuffer_used; + if (totpoints < 2) { + return; + } + const tGPspoint *pt = &points[totpoints - 1]; + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + GPU_line_smooth(true); + GPU_blend(true); + GPU_line_width(1.25f); + const float color[3] = {1.0f, 0.39f, 0.39f}; + + /* default radius and color */ + float darkcolor[3]; + const float radius = 4.0f; + + /* Inner Ring: Color from UI panel */ + immUniformColor4f(color[0], color[1], color[2], 0.8f); + imm_draw_circle_wire_2d(pos, x, y, radius, 40); + + /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */ + mul_v3_v3fl(darkcolor, color, 0.40f); + immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f); + imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40); + + /* Rope Simple. */ + immUniformColor4f(color[0], color[1], color[2], 0.8f); + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, pt->x + region->winrct.xmin, pt->y + region->winrct.ymin); + immVertex2f(pos, x, y); + immEnd(); + + /* Returns back all GPU settings */ + GPU_blend(false); + GPU_line_smooth(false); + + immUnbindProgram(); +} + +/* Turn *stabilizer* brush cursor in 3D view on/off */ +static void gpencil_draw_toggle_stabilizer_cursor(bContext *C, tGPsdata *p, short enable) +{ + if (p->stabilizer_cursor && !enable) { + /* clear cursor */ + WM_paint_cursor_end(CTX_wm_manager(C), p->stabilizer_cursor); + p->stabilizer_cursor = NULL; + } + else if (enable && !p->stabilizer_cursor) { + /* enable cursor */ + p->stabilizer_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p); + } +} /* Check if tablet eraser is being used (when processing events) */ static bool gpencil_is_tablet_eraser_active(const wmEvent *event) @@ -1479,6 +1830,9 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* turn off radial brush cursor */ gpencil_draw_toggle_eraser_cursor(C, p, false); } + else if (p->paintmode == GP_PAINTMODE_DRAW) { + gpencil_draw_toggle_stabilizer_cursor(C, p, false); + } /* always store the new eraser size to be used again next time * NOTE: Do this even when not in eraser mode, as eraser may @@ -1566,8 +1920,8 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p) "ESC/Enter to end (or click outside this area)")); break; default: - /* Do nothing - the others are self explanatory, exit quickly once the mouse is released - * Showing any text would just be annoying as it would flicker. + /* Do nothing - the others are self explanatory, exit quickly once the mouse is + * released Showing any text would just be annoying as it would flicker. */ break; } @@ -1632,6 +1986,16 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph /* Only add current point to buffer if mouse moved * (even though we got an event, it might be just noise). */ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { + /* If lazy mouse, interpolate the last and current mouse positions. */ + if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + float now_mouse[2]; + float last_mouse[2]; + copy_v2_v2(now_mouse, p->mval); + copy_v2_v2(last_mouse, p->mvalo); + interp_v2_v2v2(now_mouse, now_mouse, last_mouse, min_ff(p->stabilizer_factor, .995f)); + copy_v2_v2(p->mval, now_mouse); + } + /* try to add point */ short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); @@ -1675,7 +2039,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph /* handle draw event */ static void annotation_draw_apply_event( - wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) + bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) { tGPsdata *p = op->customdata; PointerRNA itemptr; @@ -1687,8 +2051,23 @@ static void annotation_draw_apply_event( p->mval[0] = (float)event->mval[0] - x; p->mval[1] = (float)event->mval[1] - y; + /* Key to toggle stabilization. */ + if (event->shift > 0 && p->paintmode == GP_PAINTMODE_DRAW) { + /* Using permanent stabilization, shift will deactivate the flag. */ + if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) { + if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + gpencil_draw_toggle_stabilizer_cursor(C, p, false); + p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; + } + } + /* Not using any stabilization flag. Activate temporal one. */ + else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { + p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + } + } /* verify key status for straight lines */ - if ((event->ctrl > 0) || (event->alt > 0)) { + else if ((event->ctrl > 0) || (event->alt > 0)) { if (p->straight[0] == 0) { int dx = abs((int)(p->mval[0] - p->mvalo[0])); int dy = abs((int)(p->mval[1] - p->mvalo[1])); @@ -1709,6 +2088,22 @@ static void annotation_draw_apply_event( } else { p->straight[0] = 0; + /* We were using shift while having permanent stabilization actived, + so activate the temp flag back again. */ + if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { + if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; + } + } + /* We are using the temporal stabilizer flag atm, + but shift is not pressed as well as the permanent flag is not used, + so we don't need the cursor anymore. */ + else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + /* Reset temporal stabilizer flag and remove cursor. */ + p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, false); + } } p->curtime = PIL_check_seconds_timer(); @@ -1896,12 +2291,35 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* TODO: set any additional settings that we can take from the events? * TODO? if tablet is erasing, force eraser to be on? */ - /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */ + /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... + */ /* if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { gpencil_draw_toggle_eraser_cursor(C, p, true); } + else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { + if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) { + p->gpd->runtime.sbuffer_sflag |= GP_STROKE_USE_ARROW_START; + p->gpd->runtime.arrow_start_style = RNA_enum_get(op->ptr, "arrowstyle_start"); + } + if (RNA_enum_get(op->ptr, "arrowstyle_end") != GP_STROKE_ARROWSTYLE_NONE) { + p->gpd->runtime.sbuffer_sflag |= GP_STROKE_USE_ARROW_END; + p->gpd->runtime.arrow_end_style = RNA_enum_get(op->ptr, "arrowstyle_end"); + } + } + else if (p->paintmode == GP_PAINTMODE_DRAW) { + p->stabilizer_factor = RNA_float_get(op->ptr, "stabilizer_factor"); + p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius"); + if (RNA_boolean_get(op->ptr, "use_stabilizer")) { + p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + } + else if (event->shift > 0) { + p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + } + } /* set cursor * NOTE: This may change later (i.e. intentionally via brush toggle, * or unintentionally if the user scrolls outside the area)... @@ -1915,7 +2333,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ - annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); op->flag |= OP_IS_MODAL_CURSOR_REGION; } else { @@ -2007,7 +2425,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, 0.5f); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); } else if (dist >= factor) { int slices = 2 + (int)((dist - 1.0) / factor); @@ -2016,7 +2434,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, n * i); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); } } } @@ -2106,7 +2524,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* toggle painting mode upon mouse-button movement - * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only) + * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox + * only) * - RIGHTMOUSE = polyline (hotkey) / eraser (all) * (Disabling RIGHTMOUSE case here results in bugs like [#32647]) * also making sure we have a valid event value, to not exit too early @@ -2262,7 +2681,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* TODO(sergey): Possibly evaluating dependency graph from modal operator? */ - annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event( + C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); /* finish painting operation if anything went wrong just now */ if (p->status == GP_STATUS_ERROR) { @@ -2370,6 +2790,19 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem arrow_types[] = { + {GP_STROKE_ARROWSTYLE_NONE, "NONE", 0, "None", "Don't use any arrow/style in corner"}, + {GP_STROKE_ARROWSTYLE_CLOSED, "ARROW", 0, "Arrow", "Use closed arrow style"}, + {GP_STROKE_ARROWSTYLE_OPEN, "ARROW_OPEN", 0, "Open Arrow", "Use open arrow style"}, + {GP_STROKE_ARROWSTYLE_SEGMENT, + "ARROW_OPEN_INVERTED", + 0, + "Segment", + "Use perpendicular segment style"}, + {GP_STROKE_ARROWSTYLE_SQUARE, "DIAMOND", 0, "Square", "Use square style"}, + {0, NULL, 0, NULL, NULL}, +}; + void GPENCIL_OT_annotate(wmOperatorType *ot) { PropertyRNA *prop; @@ -2393,6 +2826,37 @@ void GPENCIL_OT_annotate(wmOperatorType *ot) ot->prop = RNA_def_enum( ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); + /* properties */ + prop = RNA_def_enum( + ot->srna, "arrowstyle_start", arrow_types, 0, "Start Arrow Style", "Stroke start style"); + prop = RNA_def_enum( + ot->srna, "arrowstyle_end", arrow_types, 0, "End Arrow Style", "Stroke end style"); + prop = RNA_def_boolean(ot->srna, + "use_stabilizer", + false, + "Stabilize Stroke", + "Helper to draw smooth and clean lines. Press Shift for an invert effect " + "(even if this option is not active)"); + prop = RNA_def_float(ot->srna, + "stabilizer_factor", + 0.75f, + 0.0f, + 1.0f, + "Stabilizer Stroke Factor", + "Higher values gives a smoother stroke", + 0.0f, + 1.0f); + prop = RNA_def_int(ot->srna, + "stabilizer_radius", + 35, + 0, + 200, + "Stabilizer Stroke Radius", + "Minimun distance from last point before stroke continues", + 1, + 100); + RNA_def_property_subtype(prop, PROP_PIXEL); + prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index ab8b1a9719b..962a74d9e6f 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -491,7 +491,7 @@ bool ED_gpencil_add_armature(const bContext *C, ReportList *reports, Object *ob, } /* if no armature modifier, add a new one */ - GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Armature); + GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Armature); if (md == NULL) { md = ED_object_gpencil_modifier_add( reports, bmain, scene, ob, "Armature", eGpencilModifierType_Armature); @@ -590,8 +590,8 @@ static int gpencil_generate_weights_exec(bContext *C, wmOperator *op) } else { /* get armature from modifier */ - GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob_eval, - eGpencilModifierType_Armature); + GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob_eval, + eGpencilModifierType_Armature); if (md == NULL) { BKE_report(op->reports, RPT_ERROR, "The grease pencil object need an Armature modifier"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index e89903adf5f..5441d4e24a6 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -162,7 +162,7 @@ static void gp_strokepoint_convertcoords(bContext *C, View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); /* TODO(sergey): This function might be called from a loop, but no tagging is happening in it, - * so it's not that expensive to ensure evaluated depsgraph here. However, ideally all the + * so it's not that expensive to ensure evaluated depsgraph here. However, ideally all the * parameters are to wrapped into a context style struct and queried from Context once.*/ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *obact = CTX_data_active_object(C); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index c05162510d7..a7e7246ee82 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -55,7 +55,7 @@ #include "BKE_brush.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_lib_id.h" @@ -2619,7 +2619,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) /* Apply all GP modifiers before */ LISTBASE_FOREACH (GpencilModifierData *, md, &ob_iter->greasepencil_modifiers) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->bakeModifier) { mti->bakeModifier(bmain, depsgraph, md, ob_iter); } @@ -3193,7 +3193,7 @@ void GPENCIL_OT_material_unlock_all(wmOperatorType *ot) /* ***************** Select all strokes using color ************************ */ -static int gpencil_select_material_exec(bContext *C, wmOperator *op) +static int gpencil_material_select_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Object *ob = CTX_data_active_object(C); @@ -3263,15 +3263,15 @@ static int gpencil_select_material_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GPENCIL_OT_select_material(wmOperatorType *ot) +void GPENCIL_OT_material_select(wmOperatorType *ot) { /* identifiers */ ot->name = "Select Material"; - ot->idname = "GPENCIL_OT_select_material"; + ot->idname = "GPENCIL_OT_material_select"; ot->description = "Select/Deselect all Grease Pencil strokes using current material"; /* callbacks */ - ot->exec = gpencil_select_material_exec; + ot->exec = gpencil_material_select_exec; ot->poll = gpencil_active_material_poll; /* flags */ @@ -3282,6 +3282,48 @@ void GPENCIL_OT_select_material(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/* ***************** Set active material ************************* */ +static int gpencil_material_set_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + int slot = RNA_enum_get(op->ptr, "slot"); + + /* Try to get material */ + if ((slot < 1) || (slot > ob->totcol)) { + BKE_reportf( + op->reports, RPT_ERROR, "Cannot change to non-existent material (index = %d)", slot); + return OPERATOR_CANCELLED; + } + + /* Set active material. */ + ob->actcol = slot; + + /* updates */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_material_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Material"; + ot->idname = "GPENCIL_OT_material_set"; + ot->description = "Set active material"; + + /* callbacks */ + ot->exec = gpencil_material_set_exec; + ot->poll = gpencil_active_material_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Material to use (dynamic enum) */ + ot->prop = RNA_def_enum(ot->srna, "slot", DummyRNA_DEFAULT_items, 0, "Material Slot", ""); + RNA_def_enum_funcs(ot->prop, ED_gpencil_material_enum_itemf); +} + /* ***************** Set selected stroke material the active material ************************ */ static int gpencil_set_active_material_exec(bContext *C, wmOperator *op) @@ -3344,7 +3386,7 @@ bool ED_gpencil_add_lattice_modifier(const bContext *C, } /* if no lattice modifier, add a new one */ - GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Lattice); + GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Lattice); if (md == NULL) { md = ED_object_gpencil_modifier_add( reports, bmain, scene, ob, "Lattice", eGpencilModifierType_Lattice); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 77e45642939..2d53679b61a 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -90,8 +90,9 @@ #include "gpencil_intern.h" -/* ************************************************ */ -/* Stroke Edit Mode Management */ +/* -------------------------------------------------------------------- */ +/** \name Stroke Edit Mode Management + * \{ */ /* poll callback for all stroke editing operators */ static bool gp_stroke_edit_poll(bContext *C) @@ -138,6 +139,12 @@ static bool gpencil_editmode_toggle_poll(bContext *C) return ED_gpencil_data_get_active(C) != NULL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Edit Mode Operator + * \{ */ + static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *op) { const int back = RNA_boolean_get(op->ptr, "back"); @@ -223,6 +230,12 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Select Mode Operator + * \{ */ + /* set select mode */ static bool gpencil_selectmode_toggle_poll(bContext *C) { @@ -298,7 +311,11 @@ void GPENCIL_OT_selectmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* Stroke Paint Mode Management */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Stroke Paint Mode Operator + * \{ */ static bool gpencil_paintmode_toggle_poll(bContext *C) { @@ -402,7 +419,11 @@ void GPENCIL_OT_paintmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* Stroke Sculpt Mode Management */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Stroke Sculpt Mode Operator + * \{ */ static bool gpencil_sculptmode_toggle_poll(bContext *C) { @@ -479,6 +500,12 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Weight Paint Mode Operator + * \{ */ + void GPENCIL_OT_sculptmode_toggle(wmOperatorType *ot) { PropertyRNA *prop; @@ -600,7 +627,11 @@ void GPENCIL_OT_weightmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* Vertex Paint Mode Management */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Vertex Paint Mode Operator + * \{ */ static bool gpencil_vertexmode_toggle_poll(bContext *C) { @@ -698,10 +729,11 @@ void GPENCIL_OT_vertexmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* ************************************************ */ -/* Stroke Editing Operators */ +/** \} */ -/* ************ Stroke Hide selection Toggle ************** */ +/* -------------------------------------------------------------------- */ +/** \name Stroke Hide Selection Toggle Operator + * \{ */ static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -740,7 +772,11 @@ void GPENCIL_OT_selection_opacity_toggle(wmOperatorType *ot) ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; } -/* ************** Duplicate Selected Strokes **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Selected Strokes Operator + * \{ */ /* Make copies of selected point segments in a selected stroke */ static void gp_duplicate_points(const bGPDstroke *gps, @@ -917,7 +953,11 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ************** Extrude Selected Strokes **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Selected Strokes Operator + * \{ */ /* helper to copy a point to temp area */ static void copy_move_point(bGPDstroke *gps, @@ -1138,14 +1178,18 @@ void GPENCIL_OT_extrude(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* Copy/Paste Strokes ************************* */ -/* Grease Pencil stroke data copy/paste buffer: +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy/Paste Strokes Utilities + * + * Grease Pencil stroke data copy/paste buffer: * - The copy operation collects all segments of selected strokes, * dumping "ready to be copied" copies of the strokes into the buffer. * - The paste operation makes a copy of those elements, and adds them * to the active layer. This effectively flattens down the strokes * from several different layers into a single layer. - */ + * \{ */ /* list of bGPDstroke instances */ /* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */ @@ -1257,8 +1301,11 @@ GHash *gp_copybuf_validate_colormap(bContext *C) return new_colors; } -/* --------------------- */ -/* Copy selected strokes */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy Selected Strokes Operator + * \{ */ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) { @@ -1375,8 +1422,11 @@ void GPENCIL_OT_copy(wmOperatorType *ot) // ot->flag = OPTYPE_REGISTER; } -/* --------------------- */ -/* Paste selected strokes */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste Selected Strokes Operator + * \{ */ static bool gp_strokes_paste_poll(bContext *C) { @@ -1547,7 +1597,11 @@ void GPENCIL_OT_paste(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Move To Layer ****************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move To Layer Operator + * \{ */ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) { @@ -1667,7 +1721,11 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* ********************* Add Blank Frame *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Blank Frame Operator + * \{ */ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) { @@ -1741,7 +1799,11 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Delete Active Frame ************************ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Active Frame Operator + * \{ */ static bool gp_actframe_delete_poll(bContext *C) { @@ -1822,7 +1884,12 @@ void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot) ot->exec = gp_actframe_delete_exec; ot->poll = gp_annotation_actframe_delete_poll; } -/* **************** Delete All Active Frames ****************** */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete All Active Frames + * \{ */ static bool gp_actframe_delete_all_poll(bContext *C) { @@ -1883,7 +1950,11 @@ void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot) ot->poll = gp_actframe_delete_all_poll; } -/* ******************* Delete Operator ************************ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete/Dissolve Utilities + * \{ */ typedef enum eGP_DeleteMode { /* delete selected stroke points */ @@ -1903,8 +1974,6 @@ typedef enum eGP_DissolveMode { GP_DISSOLVE_UNSELECT = 2, } eGP_DissolveMode; -/* ----------------------------------- */ - /* Delete selected strokes */ static int gp_delete_selected_strokes(bContext *C) { @@ -2498,7 +2567,11 @@ int gp_delete_selected_point_wrap(bContext *C) return gp_delete_selected_points(C); } -/* ----------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static int gp_delete_exec(bContext *C, wmOperator *op) { @@ -2557,6 +2630,12 @@ void GPENCIL_OT_delete(wmOperatorType *ot) "Method used for deleting Grease Pencil data"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dissolve Operator + * \{ */ + static int gp_dissolve_exec(bContext *C, wmOperator *op) { eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type"); @@ -2599,7 +2678,11 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot) "Method used for dissolving Stroke points"); } -/* ****************** Snapping - Strokes <-> Cursor ************************ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snapping Selection to Grid Operator + * \{ */ /* Poll callback for snap operators */ /* NOTE: For now, we only allow these in the 3D view, as other editors do not @@ -2614,8 +2697,6 @@ static bool gp_snap_poll(bContext *C) ((area != NULL) && (area->spacetype == SPACE_VIEW3D)); } -/* --------------------------------- */ - static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -2690,7 +2771,11 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snapping Selection to Cursor Operator + * \{ */ static int gp_snap_to_cursor(bContext *C, wmOperator *op) { @@ -2782,7 +2867,11 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot) "Offset the entire stroke instead of selected points only"); } -/* ------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snapping Cursor to Selection Operator + * \{ */ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) { @@ -2873,7 +2962,11 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* Apply layer thickness change to strokes ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Apply Layer Thickness Change to Strokes Operator + * \{ */ static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2920,7 +3013,11 @@ void GPENCIL_OT_stroke_apply_thickness(wmOperatorType *ot) ot->poll = gp_active_layer_poll; } -/* ******************* Close Strokes ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Toggle Cyclic Operator + * \{ */ enum { GP_STROKE_CYCLIC_CLOSE = 1, @@ -3040,7 +3137,11 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Flat Stroke Caps ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Toggle Flat Caps Operator + * \{ */ enum { GP_STROKE_CAPS_TOGGLE_BOTH = 0, @@ -3136,7 +3237,11 @@ void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", toggle_type, GP_STROKE_CAPS_TOGGLE_BOTH, "Type", ""); } -/* ******************* Stroke join ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Join Operator + * \{ */ /* Helper: flip stroke */ static void gpencil_flip_stroke(bGPDstroke *gps) @@ -3186,8 +3291,8 @@ static void gpencil_flip_stroke(bGPDstroke *gps) /* Helper: copy point between strokes */ static void gpencil_stroke_copy_point(bGPDstroke *gps, + MDeformVert *dvert, bGPDspoint *point, - int idx, const float delta[3], float pressure, float strength, @@ -3199,6 +3304,13 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, if (gps->dvert != NULL) { gps->dvert = 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__); + } + } + gps->totpoints++; newpoint = &gps->points[gps->totpoints - 1]; @@ -3212,11 +3324,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, copy_v4_v4(newpoint->vert_color, point->vert_color); if (gps->dvert != NULL) { - MDeformVert *dvert = &gps->dvert[idx]; MDeformVert *newdvert = &gps->dvert[gps->totpoints - 1]; - newdvert->totweight = dvert->totweight; - newdvert->dw = MEM_dupallocN(dvert->dw); + if (dvert != NULL) { + newdvert->totweight = dvert->totweight; + newdvert->dw = MEM_dupallocN(dvert->dw); + } + else { + newdvert->totweight = 0; + newdvert->dw = NULL; + } } } @@ -3267,16 +3384,18 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, /* 1st: add one tail point to start invisible area */ point = gps_a->points[gps_a->totpoints - 1]; deltatime = point.time; - gpencil_stroke_copy_point(gps_a, &point, gps_a->totpoints - 1, delta, 0.0f, 0.0f, 0.0f); + + gpencil_stroke_copy_point(gps_a, NULL, &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, &point, 0, delta, 0.0f, 0.0f, deltatime); + gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime); } /* 3rd: add all points */ for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { - gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime); + MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL; + gpencil_stroke_copy_point(gps_a, dvert, pt, delta, pt->pressure, pt->strength, deltatime); } } @@ -3422,7 +3541,11 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot) "Leave gaps between joined strokes instead of linking them"); } -/* ******************* Stroke flip ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Flip Operator + * \{ */ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -3481,7 +3604,11 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ***************** Reproject Strokes ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Re-project Operator + * \{ */ typedef enum eGP_ReprojectModes { /* Axis */ @@ -3719,7 +3846,6 @@ static int gp_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op)) void GPENCIL_OT_recalc_geometry(wmOperatorType *ot) { - /* identifiers */ ot->name = "Recalculate internal geometry"; ot->idname = "GPENCIL_OT_recalc_geometry"; @@ -3733,7 +3859,12 @@ void GPENCIL_OT_recalc_geometry(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* Stroke subdivide ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Subdivide Operator + * \{ */ + /* helper to smooth */ static void gp_smooth_stroke(bContext *C, wmOperator *op) { @@ -4114,7 +4245,12 @@ void GPENCIL_OT_stroke_sample(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Stroke trim ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Trim Operator + * \{ */ + static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -4179,7 +4315,12 @@ void GPENCIL_OT_stroke_trim(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ***************** Separate Strokes ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Separate Operator + * \{ */ + typedef enum eGP_SeparateModes { /* Points */ GP_SEPARATE_POINT = 0, @@ -4397,7 +4538,12 @@ void GPENCIL_OT_stroke_separate(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "mode", separate_type, GP_SEPARATE_POINT, "Mode", ""); } -/* ***************** Split Strokes ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Split Operator + * \{ */ + static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = CTX_data_active_object(C); @@ -4494,6 +4640,12 @@ void GPENCIL_OT_stroke_split(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Smooth Operator + * \{ */ + static int gp_stroke_smooth_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -4544,11 +4696,17 @@ void GPENCIL_OT_stroke_smooth(wmOperatorType *ot) RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Cutter Operator + * \{ */ + /* smart stroke cutter for trimming stroke ends */ struct GP_SelectLassoUserData { rcti rect; - const int (*mcords)[2]; - int mcords_len; + const int (*mcoords)[2]; + int mcoords_len; }; static bool gpencil_test_lasso(bGPDstroke *gps, @@ -4564,7 +4722,7 @@ static bool gpencil_test_lasso(bGPDstroke *gps, gp_point_to_xy(gsc, gps, &pt2, &x0, &y0); /* test if in lasso */ return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) && - BLI_lasso_is_point_inside(data->mcords, data->mcords_len, x0, y0, INT_MAX)); + BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX)); } typedef bool (*GPencilTestFn)(bGPDstroke *gps, @@ -4742,19 +4900,19 @@ static int gpencil_cutter_exec(bContext *C, wmOperator *op) } struct GP_SelectLassoUserData data = {0}; - data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len); + data.mcoords = WM_gesture_lasso_path_to_array(C, op, &data.mcoords_len); /* Sanity check. */ - if (data.mcords == NULL) { + if (data.mcoords == NULL) { return OPERATOR_PASS_THROUGH; } /* Compute boundbox of lasso (for faster testing later). */ - BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len); + BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len); gpencil_cutter_lasso_select(C, op, gpencil_test_lasso, &data); - MEM_freeN((void *)data.mcords); + MEM_freeN((void *)data.mcoords); return OPERATOR_FINISHED; } @@ -4800,7 +4958,12 @@ bool ED_object_gpencil_exit(struct Main *bmain, Object *ob) return ok; } -/* ** merge by distance *** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Merge By Distance Operator + * \{ */ + static bool gp_merge_by_distance_poll(bContext *C) { Object *ob = CTX_data_active_object(C); @@ -4869,3 +5032,5 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot) ot->srna, "use_unselected", 0, "Unselected", "Use whole stroke, not only selected points"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } + +/** \} */ diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index c24f7150cbb..dd7ad8d1767 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1152,7 +1152,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) pt->time = 0.0f; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, NULL); if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) { MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr); diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index c5e5a0b79ef..a98ccb1cba6 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -68,6 +68,17 @@ struct PropertyRNA; /* Internal Operator-State Data ------------------------ */ +/** Random settings by stroke */ +typedef struct GpRandomSettings { + /** Pressure used for evaluated curves. */ + float pen_press; + + float hsv[3]; + float pressure; + float strength; + float uv; +} GpRandomSettings; + /* Temporary draw data (no draw manager mode) */ typedef struct tGPDdraw { struct RegionView3D *rv3d; /* region to draw */ @@ -230,6 +241,10 @@ typedef struct tGPDprimitive { /** size in pixels for uv calculation */ float totpixlen; + + /** Random settings by stroke */ + GpRandomSettings random_settings; + } tGPDprimitive; /* Modal Operator Drawing Callbacks ------------------------ */ @@ -345,6 +360,10 @@ const struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(struct bCon struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); +const struct EnumPropertyItem *ED_gpencil_material_enum_itemf(struct bContext *C, + struct PointerRNA *ptr, + struct PropertyRNA *prop, + bool *r_free); /* ***************************************************** */ /* Operator Defines */ @@ -550,7 +569,8 @@ void GPENCIL_OT_material_reveal(struct wmOperatorType *ot); void GPENCIL_OT_material_lock_all(struct wmOperatorType *ot); void GPENCIL_OT_material_unlock_all(struct wmOperatorType *ot); void GPENCIL_OT_material_lock_unused(struct wmOperatorType *ot); -void GPENCIL_OT_select_material(struct wmOperatorType *ot); +void GPENCIL_OT_material_select(struct wmOperatorType *ot); +void GPENCIL_OT_material_set(struct wmOperatorType *ot); void GPENCIL_OT_set_active_material(struct wmOperatorType *ot); /* convert old 2.7 files to 2.8 */ diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 0171a81f5eb..94c86572fd3 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -653,7 +653,8 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_material_reveal); WM_operatortype_append(GPENCIL_OT_material_lock_all); WM_operatortype_append(GPENCIL_OT_material_unlock_all); - WM_operatortype_append(GPENCIL_OT_select_material); + WM_operatortype_append(GPENCIL_OT_material_select); + WM_operatortype_append(GPENCIL_OT_material_set); /* Editing (Time) --------------- */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 961c4e05a28..cb72553c68b 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -255,6 +255,10 @@ typedef struct tGPsdata { tGPguide guide; ReportList *reports; + + /** Random settings by stroke */ + GpRandomSettings random_settings; + } tGPsdata; /* ------ */ @@ -687,6 +691,78 @@ static void gp_smooth_segment(bGPdata *gpd, const float inf, int from_idx, int t } } +static void gp_apply_randomness(tGPsdata *p, + BrushGpencilSettings *brush_settings, + tGPspoint *pt, + const bool press, + const bool strength, + const bool uv) +{ + bGPdata *gpd = p->gpd; + GpRandomSettings random_settings = p->random_settings; + float value = 0.0f; + /* Apply randomness to pressure. */ + if ((brush_settings->draw_random_press > 0.0f) && (press)) { + if ((brush_settings->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; + value = 1.0 + rand * 2.0 * brush_settings->draw_random_press; + } + else { + value = 1.0 + random_settings.pressure * brush_settings->draw_random_press; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) { + value *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_pressure, 0, random_settings.pen_press); + } + + pt->pressure *= value; + CLAMP(pt->pressure, 0.1f, 1.0f); + } + + /* Apply randomness to color strength. */ + if ((brush_settings->draw_random_strength) && (strength)) { + if ((brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; + value = 1.0 + rand * brush_settings->draw_random_strength; + } + else { + value = 1.0 + random_settings.strength * brush_settings->draw_random_strength; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) { + value *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_pressure, 0, random_settings.pen_press); + } + + pt->strength *= value; + CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); + } + + /* Apply randomness to uv texture rotation. */ + if ((brush_settings->uv_random > 0.0f) && (uv)) { + if ((brush_settings->flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) { + float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used)) * 2.0f - + 1.0f; + value = rand * M_PI_2 * brush_settings->uv_random; + } + else { + value = random_settings.uv * M_PI_2 * brush_settings->uv_random; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_UV_RAND_PRESS) { + value *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_uv, 0, random_settings.pen_press); + } + + pt->uv_rot += value; + CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); + } +} + /* add current stroke-point to buffer (returns whether point was successfully added) */ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime) { @@ -744,10 +820,6 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure return GP_STROKEADD_INVALID; } - /* Set vertex colors for buffer. */ - ED_gpencil_sbuffer_vertex_color_set( - p->depsgraph, p->ob, p->scene->toolsettings, p->brush, p->material); - /* get pointer to destination point */ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used); @@ -768,6 +840,15 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); } + /* Set vertex colors for buffer. */ + ED_gpencil_sbuffer_vertex_color_set(p->depsgraph, + p->ob, + p->scene->toolsettings, + p->brush, + p->material, + p->random_settings.hsv, + p->random_settings.pen_press); + if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) { /* Apply jitter to position */ if (brush_settings->draw_jitter > 0.0f) { @@ -781,26 +862,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure const float fac = rand * square_f(exp_factor) * jitpress; gp_brush_jitter(gpd, pt, fac); } - /* apply randomness to pressure */ - if (brush_settings->draw_random_press > 0.0f) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press; - CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f); - } - /* apply randomness to uv texture rotation */ - if (brush_settings->uv_random > 0.0f) { - float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used)) * - 2.0f - - 1.0f; - pt->uv_rot += rand * M_PI_2 * brush_settings->uv_random; - CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); - } - /* apply randomness to color strength */ - if (brush_settings->draw_random_strength) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->strength *= 1.0 + rand * brush_settings->draw_random_strength; - CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); - } + + /* Apply other randomness. */ + gp_apply_randomness(p, brush_settings, pt, true, true, true); } /* apply angle of stroke to brush size */ @@ -959,9 +1023,10 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) pt->pressure = ptc->pressure; pt->strength = ptc->strength; CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); + copy_v4_v4(pt->vert_color, ptc->vert_color); pt->time = ptc->time; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc); pt++; @@ -994,7 +1059,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt->time = ptc->time; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc); if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) { BKE_gpencil_dvert_ensure(gps); @@ -1113,11 +1178,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) pt->pressure = ptc->pressure; pt->strength = ptc->strength; CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); + copy_v4_v4(pt->vert_color, ptc->vert_color); pt->time = ptc->time; pt->uv_fac = ptc->uv_fac; pt->uv_rot = ptc->uv_rot; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc); if (dvert != NULL) { dvert->totweight = 0; @@ -1751,10 +1817,16 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p) BKE_brush_gpencil_paint_presets(bmain, ts); changed = true; } - /* be sure curves are initializated */ + /* Be sure curves are initializated. */ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_sensitivity); BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_strength); BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_jitter); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_pressure); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_strength); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_uv); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_hue); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_saturation); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_value); /* assign to temp tGPsdata */ p->brush = paint->brush; @@ -2700,6 +2772,8 @@ static void gpencil_draw_apply_event(bContext *C, /* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */ p->pressure = event->tablet.pressure; + /* By default use pen pressure for random curves but attenuated. */ + p->random_settings.pen_press = pow(p->pressure, 3.0f); /* Hack for pressure sensitive eraser on D+RMB when using a tablet: * The pen has to float over the tablet surface, resulting in @@ -3052,6 +3126,8 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event else { p = op->customdata; } + /* Init random settings. */ + ED_gpencil_init_random_settings(p->brush, event->mval, &p->random_settings); /* TODO: set any additional settings that we can take from the events? * if eraser is on, draw radial aid */ @@ -3175,10 +3251,17 @@ static void gp_brush_angle_segment(tGPsdata *p, tGPspoint *pt_prev, tGPspoint *p static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) { bGPdata *gpd = p->gpd; + BrushGpencilSettings *brush_settings = p->brush->gpencil_settings; + if (gpd->runtime.sbuffer_used < 3) { + tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer; + /* Apply other randomness to first points. */ + for (int i = 0; i < gpd->runtime.sbuffer_used; i++) { + tGPspoint *pt = &points[i]; + gp_apply_randomness(p, brush_settings, pt, false, false, true); + } return; } - BrushGpencilSettings *brush_settings = p->brush->gpencil_settings; int idx_prev = gpd->runtime.sbuffer_used; /* Add space for new arc points. */ @@ -3233,6 +3316,7 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) corner[0] = midpoint[0] - (cp1[0] - midpoint[0]); corner[1] = midpoint[1] - (cp1[1] - midpoint[1]); + float stepcolor = 1.0f / segments; tGPspoint *pt_step = pt_prev; for (int i = 0; i < segments; i++) { @@ -3243,6 +3327,9 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) /* Set pressure and strength equals to previous. It will be smoothed later. */ pt->pressure = pt_prev->pressure; pt->strength = pt_prev->strength; + /* Interpolate vertex color. */ + interp_v4_v4v4( + pt->vert_color, pt_before->vert_color, pt_prev->vert_color, stepcolor * (i + 1)); /* Apply angle of stroke to brush size to interpolated points but slightly attenuated.. */ if (brush_settings->draw_angle_factor != 0.0f) { @@ -3252,26 +3339,8 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) pt_step = pt; } - /* Apply randomness to pressure. */ - if (brush_settings->draw_random_press > 0.0f) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press; - CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f); - } - /* Apply randomness to color strength. */ - if (brush_settings->draw_random_strength) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->strength *= 1.0 + rand * brush_settings->draw_random_strength; - CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); - } - /* Apply randomness to uv texture rotation. */ - if (brush_settings->uv_random > 0.0f) { - float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used + i)) * - 2.0f - - 1.0f; - pt->uv_rot += rand * M_PI_2 * brush_settings->uv_random; - CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); - } + /* Apply other randomness. */ + gp_apply_randomness(p, brush_settings, pt, false, false, true); a += step; } @@ -3323,6 +3392,7 @@ static void gpencil_add_guide_points(const tGPsdata *p, /* Set pressure and strength equals to previous. It will be smoothed later. */ pt->pressure = pt_before->pressure; pt->strength = pt_before->strength; + copy_v4_v4(pt->vert_color, pt_before->vert_color); } } else { @@ -3339,6 +3409,7 @@ static void gpencil_add_guide_points(const tGPsdata *p, /* Set pressure and strength equals to previous. It will be smoothed later. */ pt->pressure = pt_before->pressure; pt->strength = pt_before->strength; + copy_v4_v4(pt->vert_color, pt_before->vert_color); } } } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 11aeeba5a24..1778162c1a3 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -124,8 +124,13 @@ static void gp_session_validatebuffer(tGPDprimitive *p) gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE; /* Set vertex colors for buffer. */ - ED_gpencil_sbuffer_vertex_color_set( - p->depsgraph, p->ob, p->scene->toolsettings, p->brush, p->material); + ED_gpencil_sbuffer_vertex_color_set(p->depsgraph, + p->ob, + p->scene->toolsettings, + p->brush, + p->material, + p->random_settings.hsv, + 1.0f); if (ELEM(p->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) { gpd->runtime.sbuffer_sflag |= GP_STROKE_CYCLIC; @@ -681,6 +686,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) ToolSettings *ts = tgpi->scene->toolsettings; bGPdata *gpd = tgpi->gpd; Brush *brush = tgpi->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + GpRandomSettings random_settings = tgpi->random_settings; bGPDstroke *gps = tgpi->gpf->strokes.first; GP_Sculpt_Settings *gset = &ts->gp_sculpt; int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0; @@ -735,11 +742,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) { BKE_curvemapping_initialize(ts->gp_sculpt.cur_primitive); } - if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { - BKE_curvemapping_initialize(tgpi->brush->gpencil_settings->curve_jitter); + if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { + BKE_curvemapping_initialize(brush_settings->curve_jitter); } - if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { - BKE_curvemapping_initialize(tgpi->brush->gpencil_settings->curve_strength); + if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { + BKE_curvemapping_initialize(brush_settings->curve_strength); } /* get an array of depths, far depths are blended */ @@ -841,10 +848,9 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) tGPspoint *p2d = &points2D[i]; /* set rnd value for reuse */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && (p2d->rnd_dirty != true)) { + if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (p2d->rnd_dirty != true)) { p2d->rnd[0] = BLI_rng_get_float(tgpi->rng); p2d->rnd[1] = BLI_rng_get_float(tgpi->rng); - p2d->rnd[2] = BLI_rng_get_float(tgpi->rng); p2d->rnd_dirty = true; } @@ -858,7 +864,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* calc pressure */ float curve_pressure = 1.0; float pressure = 1.0; - float strength = brush->gpencil_settings->draw_strength; + float strength = brush_settings->draw_strength; /* normalize value to evaluate curve */ if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) { @@ -868,20 +874,18 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) } /* apply jitter to position */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && - (brush->gpencil_settings->draw_jitter > 0.0f)) { + if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (brush_settings->draw_jitter > 0.0f)) { float jitter; - if (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { - jitter = BKE_curvemapping_evaluateF( - brush->gpencil_settings->curve_jitter, 0, curve_pressure); + if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { + jitter = BKE_curvemapping_evaluateF(brush_settings->curve_jitter, 0, curve_pressure); } else { - jitter = brush->gpencil_settings->draw_jitter; + jitter = brush_settings->draw_jitter; } /* exponential value */ - const float exfactor = square_f(brush->gpencil_settings->draw_jitter + 2.0f); + const float exfactor = square_f(brush_settings->draw_jitter + 2.0f); const float fac = p2d->rnd[0] * exfactor * jitter; /* vector */ @@ -906,47 +910,68 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) add_v2_v2(&p2d->x, svec); } - /* apply randomness to pressure */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && - (brush->gpencil_settings->draw_random_press > 0.0f)) { - if (p2d->rnd[0] > 0.5f) { - pressure -= (brush->gpencil_settings->draw_random_press * 2.0f) * p2d->rnd[1]; - } - else { - pressure += (brush->gpencil_settings->draw_random_press * 2.0f) * p2d->rnd[2]; - } - } - /* color strength */ - if (brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { - float curvef = BKE_curvemapping_evaluateF( - brush->gpencil_settings->curve_strength, 0, curve_pressure); + if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { + float curvef = BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, curve_pressure); strength *= curvef; - strength *= brush->gpencil_settings->draw_strength; + strength *= brush_settings->draw_strength; } CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f); - /* apply randomness to color strength */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && - (brush->gpencil_settings->draw_random_strength > 0.0f)) { - if (p2d->rnd[2] > 0.5f) { - strength -= strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[0]; + if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) { + /* Apply randomness to pressure. */ + if (brush_settings->draw_random_press > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f; + pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press; + } + else { + pressure *= 1.0 + random_settings.pressure * brush_settings->draw_random_press; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) { + pressure *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_pressure, 0, pressure); + } + + CLAMP(pressure, 0.1f, 1.0f); } - else { - strength += strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[1]; + + /* Apply randomness to color strength. */ + if (brush_settings->draw_random_strength) { + if ((brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f; + strength *= 1.0 + rand * brush_settings->draw_random_strength; + } + else { + strength *= 1.0 + random_settings.strength * brush_settings->draw_random_strength; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) { + strength *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_strength, 0, pressure); + } + + CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f); } - CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f); } copy_v2_v2(&tpt->x, &p2d->x); - CLAMP_MIN(pressure, 0.1f); - tpt->pressure = pressure; tpt->strength = strength; tpt->time = p2d->time; + /* Set vertex colors for buffer. */ + ED_gpencil_sbuffer_vertex_color_set(tgpi->depsgraph, + tgpi->ob, + tgpi->scene->toolsettings, + tgpi->brush, + tgpi->material, + tgpi->random_settings.hsv, + strength); + /* point uv */ if (gpd->runtime.sbuffer_used > 0) { tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1; @@ -994,8 +1019,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) pt->time = 0.0f; pt->flag = 0; pt->uv_fac = tpt->uv_fac; - /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + copy_v4_v4(pt->vert_color, tpt->vert_color); if (gps->dvert != NULL) { MDeformVert *dvert = &gps->dvert[i]; @@ -1159,6 +1183,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) /* Set Draw brush. */ Brush *brush = BKE_paint_toolslots_brush_get(paint, 0); + BKE_brush_tool_set(brush, paint, 0); BKE_paint_brush_set(paint, brush); tgpi->brush = brush; @@ -1226,6 +1251,9 @@ static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent * gpencil_primitive_init(C, op); tgpi = op->customdata; + /* Init random settings. */ + ED_gpencil_init_random_settings(tgpi->brush, event->mval, &tgpi->random_settings); + const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); if (!is_modal) { tgpi->flag = IN_PROGRESS; @@ -1262,6 +1290,7 @@ static void gpencil_primitive_interaction_end(bContext *C, ToolSettings *ts = tgpi->scene->toolsettings; 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); @@ -1285,8 +1314,8 @@ static void gpencil_primitive_interaction_end(bContext *C, gps = tgpi->gpf->strokes.first; if (gps) { gps->thickness = brush->size; - gps->hardeness = brush->gpencil_settings->hardeness; - copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio); + gps->hardeness = brush_settings->hardeness; + copy_v2_v2(gps->aspect_ratio, brush_settings->aspect_ratio); /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(gps); @@ -1449,23 +1478,25 @@ static void gpencil_primitive_edit_event_handling( static void gpencil_primitive_strength(tGPDprimitive *tgpi, bool reset) { Brush *brush = tgpi->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + if (brush) { if (reset) { - brush->gpencil_settings->draw_strength = tgpi->brush_strength; + brush_settings->draw_strength = tgpi->brush_strength; tgpi->brush_strength = 0.0f; } else { if (tgpi->brush_strength == 0.0f) { - tgpi->brush_strength = brush->gpencil_settings->draw_strength; + tgpi->brush_strength = brush_settings->draw_strength; } float move[2]; sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo); float adjust = (move[1] > 0.0f) ? 0.01f : -0.01f; - brush->gpencil_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move)); + brush_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move)); } /* limit low limit because below 0.2f the stroke is invisible */ - CLAMP(brush->gpencil_settings->draw_strength, 0.2f, 1.0f); + CLAMP(brush_settings->draw_strength, 0.2f, 1.0f); } } diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index e25576f32aa..69d22b52ded 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -1327,8 +1327,8 @@ void GPENCIL_OT_select_box(wmOperatorType *ot) struct GP_SelectLassoUserData { rcti rect; - const int (*mcords)[2]; - int mcords_len; + const int (*mcoords)[2]; + int mcoords_len; }; static bool gpencil_test_lasso(bGPDstroke *gps, @@ -1344,25 +1344,25 @@ static bool gpencil_test_lasso(bGPDstroke *gps, gp_point_to_xy(gsc, gps, &pt2, &x0, &y0); /* test if in lasso boundbox + within the lasso noose */ return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) && - BLI_lasso_is_point_inside(data->mcords, data->mcords_len, x0, y0, INT_MAX)); + BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX)); } static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) { struct GP_SelectLassoUserData data = {0}; - data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len); + data.mcoords = WM_gesture_lasso_path_to_array(C, op, &data.mcoords_len); /* Sanity check. */ - if (data.mcords == NULL) { + if (data.mcoords == NULL) { return OPERATOR_PASS_THROUGH; } /* Compute boundbox of lasso (for faster testing later). */ - BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len); + BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len); int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data); - MEM_freeN((void *)data.mcords); + MEM_freeN((void *)data.mcoords); return ret; } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 3d571773bc8..03deab15b1e 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -30,11 +30,14 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" +#include "BLI_hash.h" #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" #include "BLT_translation.h" +#include "PIL_time.h" + #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" #include "DNA_meshdata_types.h" @@ -74,6 +77,7 @@ #include "ED_object.h" #include "ED_screen.h" #include "ED_select_utils.h" +#include "ED_transform_snap_object_context.h" #include "ED_view3d.h" #include "GPU_immediate.h" @@ -481,6 +485,40 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, return item; } +/* Just existing Materials */ +const EnumPropertyItem *ED_gpencil_material_enum_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + Object *ob = CTX_data_active_object(C); + EnumPropertyItem *item = NULL, item_tmp = {0}; + int totitem = 0; + int i = 0; + + if (ELEM(NULL, C, ob)) { + return DummyRNA_DEFAULT_items; + } + + /* Existing materials */ + for (i = 1; i <= ob->totcol; i++) { + Material *ma = BKE_object_material_get(ob, i); + if (ma) { + item_tmp.identifier = ma->id.name + 2; + item_tmp.name = ma->id.name + 2; + item_tmp.value = i; + item_tmp.icon = ma->preview->icon_id; + + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; +} + /* ******************************************************** */ /* Brush Tool Core */ @@ -670,8 +708,8 @@ void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, /** * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D) * - * \param[out] r_x The screen-space x-coordinate of the point - * \param[out] r_y The screen-space y-coordinate of the point + * \param[out] r_x: The screen-space x-coordinate of the point + * \param[out] r_y: The screen-space y-coordinate of the point * * \warning This assumes that the caller has already checked * whether the stroke in question can be drawn. @@ -2525,26 +2563,170 @@ void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke } } -void ED_gpencil_point_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDspoint *pt) +void ED_gpencil_point_vertex_color_set(ToolSettings *ts, + Brush *brush, + bGPDspoint *pt, + tGPspoint *tpt) { if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) { - copy_v3_v3(pt->vert_color, brush->rgb); - pt->vert_color[3] = brush->gpencil_settings->vertex_factor; - srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color); + if (tpt == NULL) { + copy_v3_v3(pt->vert_color, brush->rgb); + pt->vert_color[3] = brush->gpencil_settings->vertex_factor; + srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color); + } + else { + copy_v3_v3(pt->vert_color, tpt->vert_color); + pt->vert_color[3] = brush->gpencil_settings->vertex_factor; + } } else { zero_v4(pt->vert_color); } } -void ED_gpencil_sbuffer_vertex_color_set( - Depsgraph *depsgraph, Object *ob, ToolSettings *ts, Brush *brush, Material *material) +void ED_gpencil_init_random_settings(Brush *brush, + const int mval[2], + GpRandomSettings *random_settings) +{ + int seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128; + /* Use mouse position to get randomness. */ + int ix = mval[0] * seed; + int iy = mval[1] * seed; + int iz = ix + iy * seed; + zero_v3(random_settings->hsv); + + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + /* Random to Hue. */ + if (brush_settings->random_hue > 0.0f) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, iy)) * 2.0f - 1.0f; + random_settings->hsv[0] = rand * brush_settings->random_hue * 0.5f; + } + /* Random to Saturation. */ + if (brush_settings->random_saturation > 0.0f) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, ix)) * 2.0f - 1.0f; + random_settings->hsv[1] = rand * brush_settings->random_saturation; + } + /* Random to Value. */ + if (brush_settings->random_value > 0.0f) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(ix * iz, iy * iz)) * 2.0f - 1.0f; + random_settings->hsv[2] = rand * brush_settings->random_value; + } + + /* Random to pressure. */ + if (brush_settings->draw_random_press > 0.0f) { + random_settings->pressure = BLI_hash_int_01(BLI_hash_int_2d(ix + iz, iy + iz)) * 2.0f - 1.0f; + } + + /* Randomn to color strength. */ + if (brush_settings->draw_random_strength) { + random_settings->strength = BLI_hash_int_01(BLI_hash_int_2d(ix + iy, iy + iz + ix)) * 2.0f - + 1.0f; + } + + /* Random to uv texture rotation. */ + if (brush_settings->uv_random > 0.0f) { + random_settings->uv = BLI_hash_int_01(BLI_hash_int_2d(iy + iz, ix * iz)) * 2.0f - 1.0f; + } +} + +static void gpencil_sbuffer_vertex_color_random( + bGPdata *gpd, Brush *brush, tGPspoint *tpt, float random_color[3], float pen_pressure) +{ + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) { + int seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128; + + int ix = (int)(tpt->x * seed); + int iy = (int)(tpt->y * seed); + int iz = ix + iy * seed; + float hsv[3]; + float factor_value[3]; + zero_v3(factor_value); + + /* Apply randomness to Hue. */ + if (brush_settings->random_hue > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) { + + float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f; + factor_value[0] = rand * brush_settings->random_hue * 0.5f; + } + else { + factor_value[0] = random_color[0]; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) { + factor_value[0] *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_hue, 0, pen_pressure); + } + } + + /* Apply randomness to Saturation. */ + if (brush_settings->random_saturation > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f; + factor_value[1] = rand * brush_settings->random_saturation; + } + else { + factor_value[1] = random_color[1]; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) { + factor_value[1] *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_saturation, 0, pen_pressure); + } + } + + /* Apply randomness to Value. */ + if (brush_settings->random_value > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(iz, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f; + factor_value[2] = rand * brush_settings->random_value; + } + else { + factor_value[2] = random_color[2]; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) { + factor_value[2] *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_value, 0, pen_pressure); + } + } + + rgb_to_hsv_v(tpt->vert_color, hsv); + add_v3_v3(hsv, factor_value); + /* For Hue need to cover all range, but for Saturation and Value + * is not logic because the effect is too hard, so the value is just clamped. */ + if (hsv[0] < 0.0f) { + hsv[0] += 1.0f; + } + else if (hsv[0] > 1.0f) { + hsv[0] -= 1.0f; + } + + CLAMP3(hsv, 0.0f, 1.0f); + hsv_to_rgb_v(hsv, tpt->vert_color); + } +} + +void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, + Object *ob, + ToolSettings *ts, + Brush *brush, + Material *material, + float random_color[3], + float pen_pressure) { bGPdata *gpd = (bGPdata *)ob->data; Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &ob->id); bGPdata *gpd_eval = (bGPdata *)ob_eval->data; MaterialGPencilStyle *gp_style = material->gp_style; + int idx = gpd->runtime.sbuffer_used; + tGPspoint *tpt = (tGPspoint *)gpd->runtime.sbuffer + idx; + float vertex_color[4]; copy_v3_v3(vertex_color, brush->rgb); vertex_color[3] = brush->gpencil_settings->vertex_factor; @@ -2559,15 +2741,18 @@ void ED_gpencil_sbuffer_vertex_color_set( } /* Copy stroke vertex color. */ if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) { - copy_v4_v4(gpd->runtime.vert_color, vertex_color); + copy_v4_v4(tpt->vert_color, vertex_color); } else { - copy_v4_v4(gpd->runtime.vert_color, gp_style->stroke_rgba); + copy_v4_v4(tpt->vert_color, gp_style->stroke_rgba); } - /* Copy to eval data because paint operators don't tag refresh until end for speedup painting. */ + /* Random Color. */ + gpencil_sbuffer_vertex_color_random(gpd, brush, tpt, random_color, pen_pressure); + + /* Copy to eval data because paint operators don't tag refresh until end for speedup + painting. */ if (gpd_eval != NULL) { - copy_v4_v4(gpd_eval->runtime.vert_color, gpd->runtime.vert_color); copy_v4_v4(gpd_eval->runtime.vert_color_fill, gpd->runtime.vert_color_fill); gpd_eval->runtime.matid = gpd->runtime.matid; } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index a9b34e3c735..7d38792f332 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -229,6 +229,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_DSHAIR, ANIMTYPE_DSPOINTCLOUD, ANIMTYPE_DSVOLUME, + ANIMTYPE_DSSIMULATION, ANIMTYPE_SHAPEKEY, @@ -356,6 +357,8 @@ typedef enum eAnimFilter_Flags { #define FILTER_HAIR_OBJD(ha) (CHECK_TYPE_INLINE(ha, Hair *), ((ha->flag & HA_DS_EXPAND))) #define FILTER_POINTS_OBJD(pt) (CHECK_TYPE_INLINE(pt, PointCloud *), ((pt->flag & PT_DS_EXPAND))) #define FILTER_VOLUME_OBJD(vo) (CHECK_TYPE_INLINE(vo, Volume *), ((vo->flag & VO_DS_EXPAND))) +#define FILTER_SIMULATION_OBJD(sim) \ + (CHECK_TYPE_INLINE(sim, Simulation *), ((sim->flag & SIM_DS_EXPAND))) /* Variable use expanders */ #define FILTER_NTREE_DATA(ntree) \ (CHECK_TYPE_INLINE(ntree, bNodeTree *), (((ntree)->flag & NTREE_DS_EXPAND))) diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1403ae1f3cc..2dbd979564e 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -40,6 +40,7 @@ struct bGPDspoint; struct bGPDstroke; struct bGPdata; struct tGPspoint; +struct GpRandomSettings; struct ARegion; struct Depsgraph; @@ -48,6 +49,7 @@ struct RegionView3D; struct ReportList; struct Scene; struct ScrArea; +struct SnapObjectContext; struct ToolSettings; struct View3D; struct ViewLayer; @@ -69,14 +71,15 @@ struct wmOperator; * Used as part of the 'stroke cache' used during drawing of new strokes */ typedef struct tGPspoint { - float x, y; /* x and y coordinates of cursor (in relative to area) */ - float pressure; /* pressure of tablet at this point */ - float strength; /* pressure of tablet at this point for alpha factor */ - float time; /* Time relative to stroke start (used when converting to path) */ - float uv_fac; /* factor of uv along the stroke */ - float uv_rot; /* uv rotation for dor mode */ - float rnd[3]; /* rnd value */ - bool rnd_dirty; /* rnd flag */ + float x, y; /* x and y coordinates of cursor (in relative to area) */ + float pressure; /* pressure of tablet at this point */ + float strength; /* pressure of tablet at this point for alpha factor */ + float time; /* Time relative to stroke start (used when converting to path) */ + float uv_fac; /* factor of uv along the stroke */ + float uv_rot; /* uv rotation for dor mode */ + float rnd[3]; /* rnd value */ + bool rnd_dirty; /* rnd flag */ + float vert_color[4]; /* Point vertex color. */ } tGPspoint; /* ----------- Grease Pencil Tools/Context ------------- */ @@ -296,12 +299,18 @@ void ED_gpencil_fill_vertex_color_set(struct ToolSettings *ts, struct bGPDstroke *gps); void ED_gpencil_point_vertex_color_set(struct ToolSettings *ts, struct Brush *brush, - struct bGPDspoint *pt); + struct bGPDspoint *pt, + struct tGPspoint *tpt); void ED_gpencil_sbuffer_vertex_color_set(struct Depsgraph *depsgraph, struct Object *ob, struct ToolSettings *ts, struct Brush *brush, - struct Material *material); + struct Material *material, + float random_color[3], + float pen_pressure); +void ED_gpencil_init_random_settings(struct Brush *brush, + const int mval[2], + struct GpRandomSettings *random_settings); bool ED_gpencil_stroke_check_collision(struct GP_SpaceConversion *gsc, struct bGPDstroke *gps, diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 910cf362a37..a8476e3d1ca 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -69,7 +69,7 @@ void ED_space_image_get_size(struct SpaceImage *sima, int *r_width, int *r_heigh void ED_space_image_get_size_fl(struct SpaceImage *sima, float r_size[2]); void ED_space_image_get_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy); void ED_space_image_get_zoom(struct SpaceImage *sima, - struct ARegion *region, + const struct ARegion *region, float *r_zoomx, float *r_zoomy); void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy); @@ -88,14 +88,18 @@ void ED_image_get_uv_aspect(struct Image *ima, float *r_aspx, float *r_aspy); void ED_image_mouse_pos(struct SpaceImage *sima, - struct ARegion *region, + const struct ARegion *region, const int mval[2], float co[2]); void ED_image_view_center_to_point(struct SpaceImage *sima, float x, float y); -void ED_image_point_pos( - struct SpaceImage *sima, struct ARegion *region, float x, float y, float *r_x, float *r_y); +void ED_image_point_pos(struct SpaceImage *sima, + const struct ARegion *region, + float x, + float y, + float *r_x, + float *r_y); void ED_image_point_pos__reverse(struct SpaceImage *sima, - struct ARegion *region, + const struct ARegion *region, const float co[2], float r_co[2]); bool ED_image_slot_cycle(struct Image *image, int direction); diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h index 82662a6b118..1146c49bef2 100644 --- a/source/blender/editors/include/ED_info.h +++ b/source/blender/editors/include/ED_info.h @@ -31,9 +31,9 @@ struct Main; /* info_stats.c */ void ED_info_stats_clear(struct ViewLayer *view_layer); -const char *ED_info_stats_string(struct Main *bmain, - struct Scene *scene, - struct ViewLayer *view_layer); +const char *ED_info_footer_string(struct ViewLayer *view_layer); +void ED_info_draw_stats( + Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height); #ifdef __cplusplus } diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index 3ae0c254000..28bc0b22790 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -24,12 +24,12 @@ #ifndef __ED_KEYFRAMES_EDIT_H__ #define __ED_KEYFRAMES_EDIT_H__ +#include "ED_anim_api.h" /* for enum eAnimFilter_Flags */ + #ifdef __cplusplus extern "C" { #endif -#include "ED_anim_api.h" /* for enum eAnimFilter_Flags */ - struct BezTriple; struct FCurve; struct Scene; @@ -106,8 +106,8 @@ typedef enum eEditKeyframes_Mirror { typedef struct KeyframeEdit_LassoData { rctf *rectf_scaled; const rctf *rectf_view; - const int (*mcords)[2]; - int mcords_tot; + const int (*mcoords)[2]; + int mcoords_len; } KeyframeEdit_LassoData; /* use with BEZT_OK_REGION_CIRCLE */ diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 4225ecc6f3d..5635ef2800a 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -24,6 +24,9 @@ #ifndef __ED_KEYFRAMING_H__ #define __ED_KEYFRAMING_H__ +#include "DNA_anim_types.h" +#include "RNA_types.h" + #ifdef __cplusplus extern "C" { #endif @@ -50,9 +53,6 @@ struct PropertyRNA; struct NlaKeyframingContext; -#include "DNA_anim_types.h" -#include "RNA_types.h" - /* ************ Keyframing Management **************** */ /* Get the active settings for keyframing settings from context (specifically the given scene) diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 7a1f64b61d4..1dc98cfee2f 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -37,6 +37,7 @@ struct Tex; struct View2D; struct bContext; struct bNode; +struct bNodeSocket; struct bNodeSocketType; struct bNodeTree; struct bNodeTree; @@ -79,6 +80,10 @@ void ED_node_draw_snap( struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos); /* node_draw.c */ +void ED_node_socket_draw(struct bNodeSocket *sock, + const struct rcti *rect, + const float color[4], + float scale); void ED_node_tree_update(const struct bContext *C); void ED_node_tag_update_id(struct ID *id); void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); @@ -94,6 +99,7 @@ void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typein bool ED_node_is_compositor(struct SpaceNode *snode); bool ED_node_is_shader(struct SpaceNode *snode); bool ED_node_is_texture(struct SpaceNode *snode); +bool ED_node_is_simulation(struct SpaceNode *snode); void ED_node_shader_default(const struct bContext *C, struct ID *id); void ED_node_composit_default(const struct bContext *C, struct Scene *scene); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 9d25fff477d..32e62a6436c 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -24,6 +24,9 @@ #ifndef __ED_OBJECT_H__ #define __ED_OBJECT_H__ +#include "BLI_compiler_attrs.h" +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -54,9 +57,6 @@ struct wmOperator; struct wmOperatorType; struct wmWindowManager; -#include "BLI_compiler_attrs.h" -#include "DNA_object_enums.h" - /* object_edit.c */ /* context.object */ struct Object *ED_object_context(struct bContext *C); diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h index beed0f98fb5..d3fc5174dd9 100644 --- a/source/blender/editors/include/ED_outliner.h +++ b/source/blender/editors/include/ED_outliner.h @@ -27,9 +27,9 @@ extern "C" { #endif +struct Base; struct ListBase; struct bContext; -struct Base; bool ED_outliner_collections_editor_poll(struct bContext *C); diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index c8a4dc5b49d..789db5ae56e 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -71,8 +71,8 @@ bool PE_mouse_particles( bool PE_box_select(struct bContext *C, const struct rcti *rect, const int sel_op); bool PE_circle_select(struct bContext *C, const int sel_op, const int mval[2], float rad); int PE_lasso_select(struct bContext *C, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, const int sel_op); bool PE_deselect_all_visible_ex(struct PTCacheEdit *edit); bool PE_deselect_all_visible(struct bContext *C); diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 06c2c3039f5..51f3eea74fa 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -34,11 +34,11 @@ extern "C" { typedef struct ScreenAnimData { ARegion *region; /* do not read from this, only for comparing if region exists */ short redraws; - short flag; /* flags for playback */ - int sfra; /* frame that playback was started from */ - int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */ - double last_duration; /* used for frame dropping */ - bool from_anim_edit; /* playback was invoked from animation editor */ + short flag; /* flags for playback */ + int sfra; /* frame that playback was started from */ + int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */ + double lagging_frame_count; /* used for frame dropping */ + bool from_anim_edit; /* playback was invoked from animation editor */ } ScreenAnimData; /* for animplayer */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index beba4a7199b..27b7511c8a2 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -157,6 +157,8 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_GPENCIL_EDIT (1 << 13) #define P_CURSOR_EDIT (1 << 14) #define P_CLNOR_INVALIDATE (1 << 15) +/* For properties performed when confirming the transformation. */ +#define P_POST_TRANSFORM (1 << 16) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 774cf8c509f..8b7b0430765 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -250,6 +250,8 @@ enum { UI_BUT_TEXT_RIGHT = 1 << 3, /** Prevent the button to show any tooltip. */ UI_BUT_NO_TOOLTIP = 1 << 4, + /** Do not add the usual horizontal padding for text drawing. */ + UI_BUT_NO_TEXT_PADDING = 1 << 5, /* Button align flag, for drawing groups together. * Used in 'uiBlock.flag', take care! */ @@ -500,15 +502,24 @@ typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origs typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2); typedef void (*uiButHandleHoldFunc)(struct bContext *C, struct ARegion *butregion, uiBut *but); typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); -typedef struct ARegion *(*uiButSearchCreateFunc)(struct bContext *C, - struct ARegion *butregion, - uiBut *but); -typedef void (*uiButSearchFunc)(const struct bContext *C, - void *arg, - const char *str, - uiSearchItems *items); -typedef void (*uiButSearchArgFreeFunc)(void *arg); +/* Search types. */ +typedef struct ARegion *(*uiButSearchCreateFn)(struct bContext *C, + struct ARegion *butregion, + uiBut *but); +typedef void (*uiButSearchUpdateFn)(const struct bContext *C, + void *arg, + const char *str, + uiSearchItems *items); +typedef void (*uiButSearchArgFreeFn)(void *arg); +typedef bool (*uiButSearchContextMenuFn)(struct bContext *C, + void *arg, + void *active, + const struct wmEvent *event); +typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C, + struct ARegion *region, + void *arg, + void *active); /* Must return allocated string. */ typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip); @@ -619,8 +630,7 @@ void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, void (*arg_free)(void *arg), - const char *opname, - int opcontext); + bool can_refresh); void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, @@ -1570,21 +1580,25 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, /* use inside searchfunc to add items */ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int state); -/* bfunc gets search item *poin as arg2, or if NULL the old string */ void UI_but_func_search_set(uiBut *but, - uiButSearchCreateFunc cfunc, - uiButSearchFunc sfunc, + uiButSearchCreateFn search_create_fn, + uiButSearchUpdateFn search_update_fn, void *arg, - uiButSearchArgFreeFunc search_arg_free_func, - uiButHandleFunc bfunc, - const char *search_sep_string, + uiButSearchArgFreeFn search_arg_free_fn, + uiButHandleFunc search_exec_fn, void *active); +void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn); +void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn); +void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string); + /* height in pixels, it's using hardcoded values still */ int UI_searchbox_size_y(void); int UI_searchbox_size_x(void); /* check if a string is in an existing search box */ int UI_search_items_find_index(uiSearchItems *items, const char *name); +void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]); + void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg); void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg); void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2); @@ -1668,6 +1682,7 @@ void UI_panel_end(const struct ScrArea *area, void UI_panels_scale(struct ARegion *region, float new_width); void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y); int UI_panel_size_y(const struct Panel *panel); +bool UI_panel_is_dragging(const struct Panel *panel); bool UI_panel_category_is_visible(const struct ARegion *region); void UI_panel_category_add(struct ARegion *region, const char *name); @@ -1772,6 +1787,10 @@ enum { UI_ITEM_O_DEPRESS = 1 << 10, UI_ITEM_R_COMPACT = 1 << 11, UI_ITEM_R_CHECKBOX_INVERT = 1 << 12, + /** Don't add a real decorator item, just blank space. */ + UI_ITEM_R_FORCE_BLANK_DECORATE = 1 << 13, + /* Even create the property split layout if there's no name to show there. */ + UI_ITEM_R_SPLIT_EMPTY_NAME = 1 << 14, }; #define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X) @@ -1782,6 +1801,9 @@ enum { UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1, UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2, UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3, + /* Disable property split for the default layout (custom ui callbacks still have full control + * over the layout and can enable it). */ + UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT = 1 << 4, }; /* used for transp checkers */ @@ -1869,7 +1891,9 @@ bool uiLayoutGetPropDecorate(uiLayout *layout); /* layout specifiers */ uiLayout *uiLayoutRow(uiLayout *layout, bool align); +uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading); uiLayout *uiLayoutColumn(uiLayout *layout, bool align); +uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading); uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align); uiLayout *uiLayoutGridFlow(uiLayout *layout, bool row_major, @@ -2044,11 +2068,11 @@ void uiTemplateOperatorSearch(uiLayout *layout); void UI_but_func_menu_search(uiBut *but); void uiTemplateMenuSearch(uiLayout *layout); -eAutoPropButsReturn uiTemplateOperatorPropertyButs(const struct bContext *C, - uiLayout *layout, - struct wmOperator *op, - const eButLabelAlign label_align, - const short flag); +void uiTemplateOperatorPropertyButs(const struct bContext *C, + uiLayout *layout, + struct wmOperator *op, + eButLabelAlign label_align, + short flag); void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); @@ -2088,6 +2112,7 @@ void uiTemplateList(uiLayout *layout, bool sort_reverse, bool sort_lock); void uiTemplateNodeLink(uiLayout *layout, + struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); @@ -2297,6 +2322,14 @@ void uiItemsFullEnumO_items(uiLayout *layout, const EnumPropertyItem *item_array, int totitem); +typedef struct uiPropertySplitWrapper { + uiLayout *label_column; + uiLayout *property_row; + uiLayout *decorate_column; +} uiPropertySplitWrapper; + +uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout); + void uiItemL(uiLayout *layout, const char *name, int icon); /* label */ void uiItemL_ex( uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert); @@ -2308,6 +2341,9 @@ void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int ic void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon); /* menu contents */ void uiItemMContents(uiLayout *layout, const char *menuname); +/* Decorators */ +void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index); +void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index); /* value */ void uiItemV(uiLayout *layout, const char *name, int icon, int argval); /* separator */ @@ -2375,6 +2411,7 @@ bool UI_context_copy_to_selected_list(struct bContext *C, /* Helpers for Operators */ uiBut *UI_context_active_but_get(const struct bContext *C); +uiBut *UI_context_active_but_get_respect_menu(const struct bContext *C); uiBut *UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index b0995250979..c5c4ca79f14 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -26,10 +26,6 @@ #include "BLI_sys_types.h" -#ifdef __cplusplus -extern "C" { -#endif - /* Define icon enum. */ #define DEF_ICON(name) ICON_##name, #define DEF_ICON_VECTOR(name) ICON_##name, @@ -47,6 +43,10 @@ typedef enum { /* use to denote intentionally unset theme color */ #define TH_UNDEFINED -1 +#ifdef __cplusplus +extern "C" { +#endif + typedef enum ThemeColorID { TH_REDALERT, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index d4db1b14074..ffc06e94a90 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -137,9 +137,9 @@ void UI_view2d_view_orthoSpecial(struct ARegion *region, struct View2D *v2d, con void UI_view2d_view_restore(const struct bContext *C); /* grid drawing */ -void UI_view2d_constant_grid_draw(struct View2D *v2d, float step); +void UI_view2d_constant_grid_draw(const struct View2D *v2d, float step); void UI_view2d_multi_grid_draw( - struct View2D *v2d, int colorid, float step, int level_size, int totlevels); + const struct View2D *v2d, int colorid, float step, int level_size, int totlevels); void UI_view2d_draw_lines_y__values(const struct View2D *v2d); void UI_view2d_draw_lines_x__values(const struct View2D *v2d); @@ -209,14 +209,17 @@ bool UI_view2d_view_to_region_clip( const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL(); void UI_view2d_view_to_region( - struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL(); -void UI_view2d_view_to_region_fl( - struct View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) ATTR_NONNULL(); -void UI_view2d_view_to_region_m4(struct View2D *v2d, float matrix[4][4]) ATTR_NONNULL(); -void UI_view2d_view_to_region_rcti(struct View2D *v2d, + const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL(); +void UI_view2d_view_to_region_fl(const struct View2D *v2d, + float x, + float y, + float *r_region_x, + float *r_region_y) ATTR_NONNULL(); +void UI_view2d_view_to_region_m4(const struct View2D *v2d, float matrix[4][4]) ATTR_NONNULL(); +void UI_view2d_view_to_region_rcti(const struct View2D *v2d, const struct rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL(); -bool UI_view2d_view_to_region_rcti_clip(struct View2D *v2d, +bool UI_view2d_view_to_region_rcti_clip(const struct View2D *v2d, const struct rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL(); @@ -228,9 +231,9 @@ void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_ void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y); float UI_view2d_scale_get_x(const struct View2D *v2d); float UI_view2d_scale_get_y(const struct View2D *v2d); -void UI_view2d_scale_get_inverse(struct View2D *v2d, float *r_x, float *r_y); +void UI_view2d_scale_get_inverse(const struct View2D *v2d, float *r_x, float *r_y); -void UI_view2d_center_get(struct View2D *v2d, float *r_x, float *r_y); +void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y); void UI_view2d_center_set(struct View2D *v2d, float x, float y); void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac); diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index d33023c69a1..c2c27af9770 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -69,6 +69,9 @@ set(SRC interface_regions.c interface_style.c interface_templates.c + interface_template_search_menu.c + interface_template_search_operator.c + interface_undo.c interface_utils.c interface_widgets.c resources.c diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 9ec660a9714..04c259ab092 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -641,6 +641,26 @@ static int ui_but_calc_float_precision(uiBut *but, double value) /* ************** BLOCK ENDING FUNCTION ************* */ +bool ui_but_rna_equals(const uiBut *a, const uiBut *b) +{ + return ui_but_rna_equals_ex(a, &b->rnapoin, b->rnaprop, b->rnaindex); +} + +bool ui_but_rna_equals_ex(const uiBut *but, + const PointerRNA *ptr, + const PropertyRNA *prop, + int index) +{ + if (but->rnapoin.data != ptr->data) { + return false; + } + if (but->rnaprop != prop || but->rnaindex != index) { + return false; + } + + return true; +} + /* NOTE: if but->poin is allocated memory for every defbut, things fail... */ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut) { @@ -649,10 +669,7 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut) if (but->retval != oldbut->retval) { return false; } - if (but->rnapoin.data != oldbut->rnapoin.data) { - return false; - } - if (but->rnaprop != oldbut->rnaprop || but->rnaindex != oldbut->rnaindex) { + if (!ui_but_rna_equals(but, oldbut)) { return false; } if (but->func != oldbut->func) { @@ -790,8 +807,7 @@ static bool ui_but_update_from_old_block(const bContext *C, SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons); - SWAP(uiButSearchArgFreeFunc, oldbut->search_arg_free_func, but->search_arg_free_func); - SWAP(void *, oldbut->search_arg, but->search_arg); + SWAP(struct uiButSearchData *, oldbut->search, but->search); /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position * when scrolling without moving mouse (see [#28432]) */ @@ -979,7 +995,9 @@ static void ui_menu_block_set_keyaccels(uiBlock *block) UI_BTYPE_BUT_MENU, UI_BTYPE_MENU, UI_BTYPE_BLOCK, - UI_BTYPE_PULLDOWN) || + UI_BTYPE_PULLDOWN, + /* For PIE-menus. */ + UI_BTYPE_ROW) || (but->flag & UI_HIDDEN)) { /* pass */ } @@ -3208,9 +3226,12 @@ static void ui_but_free(const bContext *C, uiBut *but) MEM_freeN(but->hold_argN); } - if (but->search_arg_free_func) { - but->search_arg_free_func(but->search_arg); - but->search_arg = NULL; + if (but->search != NULL) { + if (but->search->arg_free_fn) { + but->search->arg_free_fn(but->search->arg); + but->search->arg = NULL; + } + MEM_freeN(but->search); } if (but->active) { @@ -6330,40 +6351,51 @@ uiBut *uiDefSearchBut(uiBlock *block, } /** - * \param search_func, bfunc: both get it as \a arg. - * \param arg: user value, - * \param active: when set, button opens with this item visible and selected. - * \param separator_string: when not NULL, this string is used as a separator, - * showing the icon and highlighted text after the last instance of this string. + * \note The item-pointer (referred to below) is a per search item user pointer + * passed to #UI_search_item_add (stored in #uiSearchItems.pointers). + * + * \param search_create_fn: Function to create the menu. + * \param search_update_fn: Function to refresh search content after the search text has changed. + * \param arg: user value. + * \param search_arg_free_fn: When non-null, use this function to free \a arg. + * \param search_exec_fn: Function that executes the action, gets \a arg as the first argument. + * The second argument as the active item-pointer + * \param active: When non-null, this item-pointer item will be visible and selected, + * otherwise the first item will be selected. */ void UI_but_func_search_set(uiBut *but, - uiButSearchCreateFunc search_create_func, - uiButSearchFunc search_func, + uiButSearchCreateFn search_create_fn, + uiButSearchUpdateFn search_update_fn, void *arg, - uiButSearchArgFreeFunc search_arg_free_func, - uiButHandleFunc bfunc, - const char *search_sep_string, + uiButSearchArgFreeFn search_arg_free_fn, + uiButHandleFunc search_exec_fn, void *active) { /* needed since callers don't have access to internal functions * (as an alternative we could expose it) */ - if (search_create_func == NULL) { - search_create_func = ui_searchbox_create_generic; + if (search_create_fn == NULL) { + search_create_fn = ui_searchbox_create_generic; } - if (but->search_arg_free_func != NULL) { - but->search_arg_free_func(but->search_arg); - but->search_arg = NULL; + struct uiButSearchData *search = but->search; + if (search != NULL) { + if (search->arg_free_fn != NULL) { + search->arg_free_fn(but->search->arg); + search->arg = NULL; + } + } + else { + search = MEM_callocN(sizeof(*but->search), __func__); + but->search = search; } - but->search_create_func = search_create_func; - but->search_func = search_func; + search->create_fn = search_create_fn; + search->update_fn = search_update_fn; - but->search_arg = arg; - but->search_arg_free_func = search_arg_free_func; - but->search_sep_string = search_sep_string; + search->arg = arg; + search->arg_free_fn = search_arg_free_fn; - if (bfunc) { + if (search_exec_fn) { #ifdef DEBUG if (but->func) { /* watch this, can be cause of much confusion, see: T47691 */ @@ -6371,7 +6403,7 @@ void UI_but_func_search_set(uiBut *but, __func__); } #endif - UI_but_func_set(but, bfunc, arg, active); + UI_but_func_set(but, search_exec_fn, search->arg, active); } /* search buttons show red-alert if item doesn't exist, not for menus */ @@ -6383,11 +6415,33 @@ void UI_but_func_search_set(uiBut *but, } } +void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn) +{ + struct uiButSearchData *search = but->search; + search->context_menu_fn = context_menu_fn; +} + +/** + * \param separator_string: when not NULL, this string is used as a separator, + * showing the icon and highlighted text after the last instance of this string. + */ +void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string) +{ + struct uiButSearchData *search = but->search; + search->sep_string = search_sep_string; +} + +void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn) +{ + struct uiButSearchData *search = but->search; + search->tooltip_fn = tooltip_fn; +} + /* Callbacks for operator search button. */ -static void operator_enum_search_cb(const struct bContext *C, - void *but, - const char *str, - uiSearchItems *items) +static void operator_enum_search_update_fn(const struct bContext *C, + void *but, + const char *str, + uiSearchItems *items) { wmOperatorType *ot = ((uiBut *)but)->optype; PropertyRNA *prop = ot->prop; @@ -6424,7 +6478,7 @@ static void operator_enum_search_cb(const struct bContext *C, } } -static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *arg2) +static void operator_enum_search_exec_fn(struct bContext *UNUSED(C), void *but, void *arg2) { wmOperatorType *ot = ((uiBut *)but)->optype; PointerRNA *opptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */ @@ -6467,11 +6521,10 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip); UI_but_func_search_set(but, ui_searchbox_create_generic, - operator_enum_search_cb, + operator_enum_search_update_fn, but, NULL, - operator_enum_call_cb, - NULL, + operator_enum_search_exec_fn, NULL); but->optype = ot; @@ -6486,6 +6539,13 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, return but; } +void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4]) +{ + but->flag |= UI_BUT_NODE_LINK; + but->custom_data = socket; + rgba_float_to_uchar(but->col, draw_color); +} + /** * push a new event onto event queue to activate the given button * (usually a text-field) upon entering a popup diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 15fc23bc539..8c9768f523d 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -28,12 +28,14 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_string_utf8.h" #include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_nla.h" @@ -114,10 +116,40 @@ void ui_but_anim_flag(uiBut *but, float cfra) } } +static uiBut *ui_but_anim_decorate_find_attached_button(uiBut *but_decorate) +{ + uiBut *but_iter = NULL; + + BLI_assert(UI_but_is_decorator(but_decorate)); + BLI_assert(but_decorate->rnasearchpoin.data && but_decorate->rnasearchprop); + + LISTBASE_CIRCULAR_BACKWARD_BEGIN (&but_decorate->block->buttons, but_iter, but_decorate->prev) { + if (but_iter != but_decorate && + ui_but_rna_equals_ex(but_iter, + &but_decorate->rnasearchpoin, + but_decorate->rnasearchprop, + POINTER_AS_INT(but_decorate->custom_data))) { + return but_iter; + } + } + LISTBASE_CIRCULAR_BACKWARD_END(&but_decorate->block->buttons, but_iter, but_decorate->prev); + + return NULL; +} + void ui_but_anim_decorate_update_from_flag(uiBut *but) { - BLI_assert(UI_but_is_decorator(but) && but->prev); - int flag = but->prev->flag; + const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but); + + if (!but_anim) { + printf("Could not find button with matching property to decorate (%s.%s)\n", + RNA_struct_identifier(but->rnasearchpoin.type), + RNA_property_identifier(but->rnasearchprop)); + return; + } + + int flag = but_anim->flag; + if (flag & UI_BUT_DRIVEN) { but->icon = ICON_DECORATE_DRIVER; } @@ -289,22 +321,26 @@ void ui_but_anim_paste_driver(bContext *C) void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)) { wmWindowManager *wm = CTX_wm_manager(C); - uiBut *but = arg_but; - but = but->prev; + uiBut *but_decorate = arg_but; + uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate); + + if (!but_anim) { + return; + } /* FIXME(campbell), swapping active pointer is weak. */ - SWAP(struct uiHandleButtonData *, but->active, but->next->active); + SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active); wm->op_undo_depth++; - if (but->flag & UI_BUT_DRIVEN) { + if (but_anim->flag & UI_BUT_DRIVEN) { /* pass */ /* TODO: report? */ } - else if (but->flag & UI_BUT_ANIMATED_KEY) { + else if (but_anim->flag & UI_BUT_ANIMATED_KEY) { PointerRNA props_ptr; wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); } @@ -312,11 +348,11 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy) PointerRNA props_ptr; wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); } - SWAP(struct uiHandleButtonData *, but->active, but->next->active); + SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active); wm->op_undo_depth--; } diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 5245b724da4..cc370113422 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -962,7 +962,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) const PropertyType prop_type = RNA_property_type(but->rnaprop); if (((prop_type == PROP_POINTER) || (prop_type == PROP_STRING && but->type == UI_BTYPE_SEARCH_MENU && - but->search_func == ui_rna_collection_search_cb)) && + but->search->update_fn == ui_rna_collection_search_update_fn)) && ui_jump_to_target_button_poll(C)) { uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Jump to Target"), diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9a7e189406c..ead36fdbd19 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -381,6 +381,9 @@ typedef struct uiHandleButtonData { uiSelectContextStore select_others; #endif + /* Text field undo. */ + struct uiUndoStack_Text *undo_stack_text; + /* post activate */ uiButtonActivateType posttype; uiBut *postbut; @@ -417,7 +420,7 @@ typedef struct uiAfterFunc { PropertyRNA *rnaprop; void *search_arg; - uiButSearchArgFreeFunc search_arg_free_func; + uiButSearchArgFreeFn search_arg_free_fn; bContextStore *context; @@ -753,10 +756,12 @@ static void ui_apply_but_func(bContext *C, uiBut *but) after->rnapoin = but->rnapoin; after->rnaprop = but->rnaprop; - after->search_arg_free_func = but->search_arg_free_func; - after->search_arg = but->search_arg; - but->search_arg_free_func = NULL; - but->search_arg = NULL; + if (but->search != NULL) { + after->search_arg_free_fn = but->search->arg_free_fn; + after->search_arg = but->search->arg; + but->search->arg_free_fn = NULL; + but->search->arg = NULL; + } if (but->context) { after->context = CTX_store_copy(but->context); @@ -924,8 +929,8 @@ static void ui_apply_but_funcs_after(bContext *C) MEM_freeN(after.rename_orig); } - if (after.search_arg_free_func) { - after.search_arg_free_func(after.search_arg); + if (after.search_arg_free_fn) { + after.search_arg_free_fn(after.search_arg); } ui_afterfunc_update_preferences_dirty(&after); @@ -2848,6 +2853,23 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data) return changed; } +static bool ui_textedit_set_cursor_pos_foreach_glyph(const char *UNUSED(str), + const size_t str_step_ofs, + const rcti *glyph_step_bounds, + const int UNUSED(glyph_advance_x), + const rctf *glyph_bounds, + const int UNUSED(glyph_bearing[2]), + void *user_data) +{ + int *cursor_data = user_data; + float center = glyph_step_bounds->xmin + (BLI_rctf_size_x(glyph_bounds) / 2.0f); + if (cursor_data[0] < center) { + cursor_data[1] = str_step_ofs; + return false; + } + return true; +} + /** * \param x: Screen space cursor location - #wmEvent.x * @@ -2883,8 +2905,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con startx += UI_DPI_ICON_SIZE / aspect; } } - /* But this extra .05 makes clicks in between characters feel nicer. */ - startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect; + startx += (UI_TEXT_MARGIN_X * U.widget_unit) / aspect; /* mouse dragged outside the widget to the left */ if (x < startx) { @@ -2907,48 +2928,24 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con but->pos = but->ofs; } /* mouse inside the widget, mouse coords mapped in widget space */ - else { /* (x >= startx) */ - int pos_i; - - /* keep track of previous distance from the cursor to the char */ - float cdist, cdist_prev = 0.0f; - short pos_prev; - - str_last = &str[strlen(str)]; - - but->pos = pos_prev = ((str_last - str) - but->ofs); - - while (true) { - cdist = startx + BLF_width(fstyle.uifont_id, str + but->ofs, (str_last - str) - but->ofs); - - /* check if position is found */ - if (cdist < x) { - /* check is previous location was in fact closer */ - if ((x - cdist) > (cdist_prev - x)) { - but->pos = pos_prev; - } - break; - } - cdist_prev = cdist; - pos_prev = but->pos; - /* done with tricky distance checks */ - - pos_i = but->pos; - if (but->pos <= 0) { - break; - } - if (BLI_str_cursor_step_prev_utf8(str + but->ofs, but->ofs, &pos_i)) { - but->pos = pos_i; - str_last = &str[but->pos + but->ofs]; - } - else { - break; /* unlikely but possible */ - } - } - but->pos += but->ofs; - if (but->pos < 0) { - but->pos = 0; - } + else { + str_last = &str[but->ofs]; + const int str_last_len = strlen(str_last); + int x_pos = (int)(x - startx); + int glyph_data[2] = { + x_pos, /* horizontal position to test. */ + -1, /* Write the character offset here. */ + }; + BLF_boundbox_foreach_glyph(fstyle.uifont_id, + str + but->ofs, + INT_MAX, + ui_textedit_set_cursor_pos_foreach_glyph, + glyph_data); + /* If value untouched then we are to the right. */ + if (glyph_data[1] == -1) { + glyph_data[1] = str_last_len; + } + but->pos = glyph_data[1] + but->ofs; } if (fstyle.kerning == 1) { @@ -3314,9 +3311,13 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) but->selsta = 0; but->selend = len; + /* Initialize undo history tracking. */ + data->undo_stack_text = ui_textedit_undo_stack_create(); + ui_textedit_undo_push(data->undo_stack_text, but->editstr, but->pos); + /* optional searchbox */ if (but->type == UI_BTYPE_SEARCH_MENU) { - data->searchbox = but->search_create_func(C, data->region, but); + data->searchbox = but->search->create_fn(C, data->region, but); ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */ } @@ -3369,6 +3370,10 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) WM_cursor_modal_restore(win); + /* Free text undo history text blocks. */ + ui_textedit_undo_stack_destroy(data->undo_stack_text); + data->undo_stack_text = NULL; + #ifdef WITH_INPUT_IME if (win->ime_data) { ui_textedit_ime_end(win, but); @@ -3448,7 +3453,7 @@ static void ui_do_but_textedit( bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { int retval = WM_UI_HANDLER_CONTINUE; - bool changed = false, inbox = false, update = false; + bool changed = false, inbox = false, update = false, skip_undo_push = false; #ifdef WITH_INPUT_IME wmWindow *win = CTX_wm_window(C); @@ -3468,7 +3473,7 @@ static void ui_do_but_textedit( /* pass */ } else { - ui_searchbox_event(C, data->searchbox, but, event); + ui_searchbox_event(C, data->searchbox, but, data->region, event); } #else ui_searchbox_event(C, data->searchbox, but, event); @@ -3479,6 +3484,16 @@ static void ui_do_but_textedit( case RIGHTMOUSE: case EVT_ESCKEY: if (event->val == KM_PRESS) { + /* Support search context menu. */ + if (event->type == RIGHTMOUSE) { + if (data->searchbox) { + if (ui_searchbox_event(C, data->searchbox, but, data->region, event)) { + /* Only break if the event was handled. */ + break; + } + } + } + #ifdef WITH_INPUT_IME /* skips button handling since it is not wanted */ if (is_ime_composing) { @@ -3587,7 +3602,7 @@ static void ui_do_but_textedit( #ifdef USE_KEYNAV_LIMIT ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event); #endif - ui_searchbox_event(C, data->searchbox, but, event); + ui_searchbox_event(C, data->searchbox, but, data->region, event); break; } if (event->type == WHEELDOWNMOUSE) { @@ -3604,7 +3619,7 @@ static void ui_do_but_textedit( #ifdef USE_KEYNAV_LIMIT ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event); #endif - ui_searchbox_event(C, data->searchbox, but, event); + ui_searchbox_event(C, data->searchbox, but, data->region, event); break; } if (event->type == WHEELUPMOUSE) { @@ -3670,6 +3685,32 @@ static void ui_do_but_textedit( } retval = WM_UI_HANDLER_BREAK; break; + case EVT_ZKEY: { + /* Ctrl-Z or Ctrl-Shift-Z: Undo/Redo (allowing for OS-Key on Apple). */ + + const bool is_redo = (event->shift != 0); + if ( +#if defined(__APPLE__) + (event->oskey && !IS_EVENT_MOD(event, alt, ctrl)) || +#endif + (event->ctrl && !IS_EVENT_MOD(event, alt, oskey))) { + int undo_pos; + const char *undo_str = ui_textedit_undo( + data->undo_stack_text, is_redo ? 1 : -1, &undo_pos); + if (undo_str != NULL) { + ui_textedit_string_set(but, data, undo_str); + + /* Set the cursor & clear selection. */ + but->pos = undo_pos; + but->selsta = but->pos; + but->selend = but->pos; + changed = true; + } + } + skip_undo_push = true; + retval = WM_UI_HANDLER_BREAK; + break; + } } if ((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE) @@ -3723,6 +3764,11 @@ static void ui_do_but_textedit( #endif if (changed) { + /* The undo stack may be NULL if an event exits editing. */ + if ((skip_undo_push == false) && (data->undo_stack_text != NULL)) { + ui_textedit_undo_push(data->undo_stack_text, data->str, but->pos); + } + /* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */ if (update && data->interactive) { ui_apply_but(C, block, but, data, true); @@ -8213,11 +8259,22 @@ static uiBut *ui_context_rna_button_active(const bContext *C) return ui_context_button_active(CTX_wm_region(C), ui_context_rna_button_active_test); } -uiBut *UI_context_active_but_get(const struct bContext *C) +uiBut *UI_context_active_but_get(const bContext *C) { return ui_context_button_active(CTX_wm_region(C), NULL); } +/* + * Version of #UI_context_active_get() that uses the result of #CTX_wm_menu() + * if set. Does not traverse into parent menus, which may be wanted in some + * cases. + */ +uiBut *UI_context_active_but_get_respect_menu(const bContext *C) +{ + ARegion *ar_menu = CTX_wm_menu(C); + return ui_context_button_active(ar_menu ? ar_menu : CTX_wm_region(C), NULL); +} + uiBut *UI_region_active_but_get(ARegion *region) { return ui_context_button_active(region, NULL); @@ -9339,6 +9396,11 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock if (event->val == KM_RELEASE) { /* pass, needed so we can exit active menu-items when click-dragging out of them */ } + else if (but->type == UI_BTYPE_SEARCH_MENU) { + /* Pass, needed so search popup can have RMB context menu. + * This may be useful for other interactions which happen in the search popup + * without being directly over the search button. */ + } else if (!ui_block_is_menu(but->block) || ui_block_is_pie_menu(but->block)) { /* pass, skip for dialogs */ } @@ -10772,9 +10834,6 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) if (temp.popup_func) { temp.popup_func(C, temp.popup_arg, temp.retvalue); } - if (temp.optype) { - WM_operator_name_call_ptr(C, temp.optype, temp.opcontext, NULL); - } } else if (temp.cancel_func) { temp.cancel_func(C, temp.popup_arg); @@ -10938,8 +10997,7 @@ void UI_screen_free_active_but(const bContext *C, bScreen *screen) { wmWindow *win = CTX_wm_window(C); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { uiBut *but = ui_region_find_active_but(region); if (but) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 9f9e04eea82..c94a95890c0 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -2320,6 +2320,9 @@ int UI_idcode_icon_get(const int idcode) return ICON_WORLD_DATA; case ID_WS: return ICON_WORKSPACE; + case ID_SIM: + /* TODO: Use correct icon. */ + return ICON_PHYSICS; default: return ICON_NONE; } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 3ded62dca7f..3748dbab519 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -41,6 +41,7 @@ struct bContextStore; struct uiHandleButtonData; struct uiLayout; struct uiStyle; +struct uiUndoStack_Text; struct uiWidgetColors; struct wmEvent; struct wmKeyConfig; @@ -147,6 +148,17 @@ enum { /* max amount of items a radial menu (pie menu) can contain */ #define PIE_MAX_ITEMS 8 +struct uiButSearchData { + uiButSearchCreateFn create_fn; + uiButSearchUpdateFn update_fn; + void *arg; + uiButSearchArgFreeFn arg_free_fn; + uiButSearchContextMenuFn context_menu_fn; + uiButSearchTooltipFn tooltip_fn; + + const char *sep_string; +}; + struct uiBut { struct uiBut *next, *prev; int flag, drawflag; @@ -203,11 +215,7 @@ struct uiBut { uiButCompleteFunc autocomplete_func; void *autofunc_arg; - uiButSearchCreateFunc search_create_func; - uiButSearchFunc search_func; - void *search_arg; - uiButSearchArgFreeFunc search_arg_free_func; - const char *search_sep_string; + struct uiButSearchData *search; uiButHandleRenameFunc rename_func; void *rename_arg1; @@ -601,10 +609,8 @@ struct uiPopupBlockHandle { /* for operator popups */ struct wmOperator *popup_op; - struct wmOperatorType *optype; struct ScrArea *ctx_area; struct ARegion *ctx_region; - int opcontext; /* return values */ int butretval; @@ -666,9 +672,10 @@ bool ui_searchbox_inside(struct ARegion *region, int x, int y); int ui_searchbox_find_index(struct ARegion *region, const char *name); void ui_searchbox_update(struct bContext *C, struct ARegion *region, uiBut *but, const bool reset); int ui_searchbox_autocomplete(struct bContext *C, struct ARegion *region, uiBut *but, char *str); -void ui_searchbox_event(struct bContext *C, +bool ui_searchbox_event(struct bContext *C, struct ARegion *region, uiBut *but, + struct ARegion *butregion, const struct wmEvent *event); bool ui_searchbox_apply(uiBut *but, struct ARegion *region); void ui_searchbox_free(struct bContext *C, struct ARegion *region); @@ -709,7 +716,7 @@ uiPopupBlockHandle *ui_popover_panel_create(struct bContext *C, void ui_pie_menu_level_create(uiBlock *block, struct wmOperatorType *ot, const char *propname, - IDProperty *properties, + struct IDProperty *properties, const EnumPropertyItem *items, int totitem, int context, @@ -774,6 +781,16 @@ void ui_draw_but_TRACKPREVIEW(struct ARegion *region, const struct uiWidgetColors *wcol, const rcti *rect); +/* interface_undo.c */ +struct uiUndoStack_Text *ui_textedit_undo_stack_create(void); +void ui_textedit_undo_stack_destroy(struct uiUndoStack_Text *undo_stack); +void ui_textedit_undo_push(struct uiUndoStack_Text *undo_stack, + const char *text, + int cursor_index); +const char *ui_textedit_undo(struct uiUndoStack_Text *undo_stack, + int direction, + int *r_cursor_index); + /* interface_handlers.c */ PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, @@ -800,6 +817,11 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]); void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip); void ui_but_clipboard_free(void); +bool ui_but_rna_equals(const uiBut *a, const uiBut *b); +bool ui_but_rna_equals_ex(const uiBut *but, + const PointerRNA *ptr, + const PropertyRNA *prop, + int index); uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new); uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new); @@ -869,7 +891,7 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle, int iconid, int state, bool use_sep, - int *r_name_width); + int *r_xmax); void ui_draw_preview_item( const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); @@ -1023,9 +1045,10 @@ void UI_OT_eyedropper_driver(struct wmOperatorType *ot); void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot); /* interface_util.c */ +bool ui_str_has_word_prefix(const char *haystack, const char *needle, size_t needle_len); /** - * For use with #ui_rna_collection_search_cb. + * For use with #ui_rna_collection_search_update_fn. */ typedef struct uiRNACollectionSearch { PointerRNA target_ptr; @@ -1040,10 +1063,10 @@ typedef struct uiRNACollectionSearch { /* Block has to be stored for freeing butstore (uiBut.block doesn't work with undo). */ uiBlock *butstore_block; } uiRNACollectionSearch; -void ui_rna_collection_search_cb(const struct bContext *C, - void *arg, - const char *str, - uiSearchItems *items); +void ui_rna_collection_search_update_fn(const struct bContext *C, + void *arg, + const char *str, + uiSearchItems *items); /* interface_ops.c */ bool ui_jump_to_target_button_poll(struct bContext *C); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index cbea32f179a..884e43b4026 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -75,7 +75,7 @@ } \ (void)0 -#define UI_ITEM_PROP_SEP_DIVIDE 0.5f +#define UI_ITEM_PROP_SEP_DIVIDE 0.4f /* uiLayoutRoot */ @@ -135,10 +135,11 @@ enum { UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */ UI_ITEM_PROP_SEP = 1 << 3, + UI_ITEM_INSIDE_PROP_SEP = 1 << 4, /* Show an icon button next to each property (to set keyframes, show status). * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */ - UI_ITEM_PROP_DECORATE = 1 << 4, - UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 5, + UI_ITEM_PROP_DECORATE = 1 << 5, + UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 6, }; typedef struct uiButtonItem { @@ -151,8 +152,11 @@ struct uiLayout { uiLayoutRoot *root; bContextStore *context; + uiLayout *parent; ListBase items; + char heading[UI_MAX_NAME_STR]; + /** Sub layout to add child items, if not the layout itself. */ uiLayout *child_items_layout; @@ -1780,6 +1784,7 @@ static void ui_item_rna_size(uiLayout *layout, PropertyType type; PropertySubType subtype; int len, w = 0, h; + bool is_checkbox_only = false; /* arbitrary extended width by type */ type = RNA_property_type(prop); @@ -1791,6 +1796,10 @@ static void ui_item_rna_size(uiLayout *layout, name = "non-empty text"; } else if (type == PROP_BOOLEAN) { + if (icon == ICON_NONE) { + /* Exception for checkboxes, they need a little less space to align nicely. */ + is_checkbox_only = true; + } icon = ICON_DOT; } else if (type == PROP_ENUM) { @@ -1850,6 +1859,9 @@ static void ui_item_rna_size(uiLayout *layout, if (type == PROP_BOOLEAN && name[0]) { w += UI_UNIT_X / 5; } + else if (is_checkbox_only) { + w -= UI_UNIT_X / 4; + } else if (type == PROP_ENUM && !icon_only) { w += UI_UNIT_X / 4; } @@ -1862,6 +1874,57 @@ static void ui_item_rna_size(uiLayout *layout, *r_h = h; } +static bool ui_item_rna_is_expand(PropertyRNA *prop, int index, int item_flag) +{ + const bool is_array = RNA_property_array_check(prop); + const int subtype = RNA_property_subtype(prop); + return is_array && (index == RNA_NO_INDEX) && + ((item_flag & UI_ITEM_R_EXPAND) || + !ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)); +} + +/** + * Find first layout ancestor (or self) with a heading set. + * + * \returns the layout to add the heading to as fallback (i.e. if it can't be placed in a split + * layout). Its #uiLayout.heading member can be cleared to mark the heading as added (so + * it's not added multiple times). Returns a pointer to the heading + */ +static uiLayout *ui_layout_heading_find(uiLayout *cur_layout) +{ + for (uiLayout *parent = cur_layout; parent; parent = parent->parent) { + if (parent->heading[0]) { + return parent; + } + } + + return NULL; +} + +static void ui_layout_heading_label_add(uiLayout *layout, + uiLayout *heading_layout, + bool right_align, + bool respect_prop_split) +{ + const int prev_alignment = layout->alignment; + + if (right_align) { + uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_RIGHT); + } + + if (respect_prop_split) { + uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE); + } + else { + uiItemL(layout, heading_layout->heading, ICON_NONE); + } + /* After adding the heading label, we have to mark it somehow as added, so it's not added again + * for other items in this layout. For now just clear it. */ + heading_layout->heading[0] = '\0'; + + layout->alignment = prev_alignment; +} + /** * Hack to add further items in a row into the second part of the split layout, so the label part * keeps a fixed size. @@ -1869,7 +1932,14 @@ static void ui_item_rna_size(uiLayout *layout, */ static uiLayout *ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split) { + /* Tag item as using property split layout, this is inherited to children so they can get special + * treatment if needed. */ + layout_parent->item.flag |= UI_ITEM_INSIDE_PROP_SEP; + if (layout_parent->item.type == ITEM_LAYOUT_ROW) { + /* Prevent further splits within the row. */ + uiLayoutSetPropSep(layout_parent, false); + layout_parent->child_items_layout = uiLayoutRow(layout_split, true); return layout_parent->child_items_layout; } @@ -1888,13 +1958,18 @@ void uiItemFullR(uiLayout *layout, uiBlock *block = layout->root->block; char namestr[UI_MAX_NAME_STR]; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); - - /* By default 'use_prop_sep' uses a separate column for labels. - * This is an exception for check-boxes otherwise only the small checkbox region is clickable. + const bool inside_prop_sep = ((layout->item.flag & UI_ITEM_INSIDE_PROP_SEP) != 0); + /* Columns can define a heading to insert. If the first item added to a split layout doesn't have + * 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 + * label in the second column, to not make that almost empty. * * Keep using 'use_prop_sep' instead of disabling it entirely because * we need the ability to have decorators still. */ bool use_prop_sep_split_label = use_prop_sep; + bool use_split_empty_name = (flag & UI_ITEM_R_SPLIT_EMPTY_NAME); #ifdef UI_PROP_DECORATE struct { @@ -2005,6 +2080,9 @@ void uiItemFullR(uiLayout *layout, if (use_prop_sep) { if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { use_prop_sep_split_label = false; + /* For check-boxes we make an exception: We allow showing them in a split row even without + * label. It typically relates to its neighbor items, so no need for an extra label. */ + use_split_empty_name = true; } } #endif @@ -2031,6 +2109,7 @@ void uiItemFullR(uiLayout *layout, /* Split the label / property. */ uiLayout *layout_parent = layout; + if (use_prop_sep) { uiLayout *layout_row = NULL; #ifdef UI_PROP_DECORATE @@ -2041,21 +2120,26 @@ void uiItemFullR(uiLayout *layout, } #endif /* UI_PROP_DECORATE */ - if ((name[0] == '\0') || (use_prop_sep_split_label == false)) { + if ((name[0] == '\0') && !use_split_empty_name) { /* Ensure we get a column when text is not set. */ layout = uiLayoutColumn(layout_row ? layout_row : layout, true); layout->space = 0; + if (heading_layout) { + ui_layout_heading_label_add(layout, heading_layout, false, false); + } } else { - const PropertySubType subtype = RNA_property_subtype(prop); uiLayout *layout_split = uiLayoutSplit( layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true); + bool label_added = false; layout_split->space = 0; uiLayout *layout_sub = uiLayoutColumn(layout_split, true); layout_sub->space = 0; - if ((index == RNA_NO_INDEX && is_array) && - ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0)) { + if (!use_prop_sep_split_label) { + /* Pass */ + } + else if (ui_item_rna_is_expand(prop, index, flag)) { char name_with_suffix[UI_MAX_DRAW_STR + 2]; char str[2] = {'\0'}; for (int a = 0; a < len; a++) { @@ -2084,6 +2168,8 @@ void uiItemFullR(uiLayout *layout, ""); but->drawflag |= UI_BUT_TEXT_RIGHT; but->drawflag &= ~UI_BUT_TEXT_LEFT; + + label_added = true; } } else { @@ -2092,13 +2178,17 @@ void uiItemFullR(uiLayout *layout, block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); but->drawflag |= UI_BUT_TEXT_RIGHT; but->drawflag &= ~UI_BUT_TEXT_LEFT; + + label_added = true; } } - if (layout_parent) { - layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split); + if (!label_added && heading_layout) { + ui_layout_heading_label_add(layout_sub, heading_layout, true, false); } + layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split); + /* Watch out! We can only write into the new layout now. */ if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) { /* Expanded enums each have their own name. */ @@ -2113,7 +2203,9 @@ void uiItemFullR(uiLayout *layout, } } else { - name = ""; + if (use_prop_sep_split_label) { + name = ""; + } layout = uiLayoutColumn(layout_split, true); } layout->space = 0; @@ -2132,9 +2224,20 @@ void uiItemFullR(uiLayout *layout, #endif /* UI_PROP_DECORATE */ } /* End split. */ + else if (heading_layout) { + /* Could not add heading to split layout, fallback to inserting it to the layout with the + * heading itself. */ + ui_layout_heading_label_add(heading_layout, heading_layout, false, false); + } /* array property */ if (index == RNA_NO_INDEX && is_array) { + if (inside_prop_sep) { + /* Within a split row, add array items to a column so they match the column layout of + * previous items (e.g. transform vector with lock icon for each item). */ + layout = uiLayoutColumn(layout, true); + } + ui_item_array(layout, block, name, @@ -2214,12 +2317,6 @@ void uiItemFullR(uiLayout *layout, if (layout->activate_init) { UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); } - - if (use_prop_sep && (use_prop_sep_split_label == false)) { - /* When the button uses it's own text right align it. */ - but->drawflag |= UI_BUT_TEXT_RIGHT; - but->drawflag &= ~UI_BUT_TEXT_LEFT; - } } /* The resulting button may have the icon set since boolean button drawing @@ -2242,50 +2339,21 @@ void uiItemFullR(uiLayout *layout, #ifdef UI_PROP_DECORATE if (ui_decorate.use_prop_decorate) { - const bool is_anim = RNA_property_animateable(ptr, prop); uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first; + const bool use_blank_decorator = (flag & UI_ITEM_R_FORCE_BLANK_DECORATE); uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false); layout_col->space = 0; layout_col->emboss = UI_EMBOSS_NONE; + int i; for (i = 0; i < ui_decorate.len && but_decorate; i++) { + PointerRNA *ptr_dec = use_blank_decorator ? NULL : &but_decorate->rnapoin; + PropertyRNA *prop_dec = use_blank_decorator ? NULL : but_decorate->rnaprop; + /* The icons are set in 'ui_but_anim_flag' */ - if (is_anim) { - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_DOT, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Animate property")); - UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL); - but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK; - } - else { - /* We may show other information here in future, for now use empty space. */ - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_BLANK1, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - ""); - but->flag |= UI_BUT_DISABLED; - } + uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex); + but = block->buttons.last; + /* Order the decorator after the button we decorate, this is used so we can always * do a quick lookup. */ BLI_remlink(&block->buttons, but); @@ -2577,7 +2645,7 @@ static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRN RNA_STRUCT_END; } -static void ui_rna_collection_search_free_cb(void *ptr) +static void ui_rna_collection_search_arg_free_fn(void *ptr) { uiRNACollectionSearch *coll_search = ptr; UI_butstore_free(coll_search->butstore_block, coll_search->butstore); @@ -2629,10 +2697,9 @@ void ui_but_add_search( UI_but_func_search_set(but, ui_searchbox_create_generic, - ui_rna_collection_search_cb, + ui_rna_collection_search_update_fn, coll_search, - ui_rna_collection_search_free_cb, - NULL, + ui_rna_collection_search_arg_free_fn, NULL, NULL); } @@ -2759,6 +2826,7 @@ static uiBut *ui_item_menu(uiLayout *layout, bool force_menu) { uiBlock *block = layout->root->block; + uiLayout *heading_layout = ui_layout_heading_find(layout); uiBut *but; int w, h; @@ -2788,6 +2856,10 @@ static uiBut *ui_item_menu(uiLayout *layout, } } + if (heading_layout) { + ui_layout_heading_label_add(layout, heading_layout, true, true); + } + if (name[0] && icon) { but = uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, tip); } @@ -2861,6 +2933,91 @@ void uiItemMContents(uiLayout *layout, const char *menuname) UI_menutype_draw(C, mt, layout); } +/** + * Insert a decorator item for a button with the same property as \a prop. + * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a prop. + */ +void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index) +{ + uiBlock *block = layout->root->block; + uiBut *but = NULL; + + uiLayout *col; + UI_block_layout_set_current(block, layout); + col = uiLayoutColumn(layout, false); + col->space = 0; + col->emboss = UI_EMBOSS_NONE; + + if (ELEM(NULL, ptr, prop) || !RNA_property_animateable(ptr, prop)) { + but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_BLANK1, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + ""); + but->flag |= UI_BUT_DISABLED; + return; + } + + const bool is_expand = ui_item_rna_is_expand(prop, index, 0); + const bool is_array = RNA_property_array_check(prop); + + /* Loop for the array-case, but only do in case of an expanded array. */ + for (int i = 0; i < (is_expand ? RNA_property_array_length(ptr, prop) : 1); i++) { + but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_DOT, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + TIP_("Animate property")); + UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL); + but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK; + /* Reusing RNA search members, setting actual RNA data has many side-effects. */ + but->rnasearchpoin = *ptr; + but->rnasearchprop = prop; + /* ui_def_but_rna() sets non-array buttons to have a RNA index of 0. */ + but->custom_data = POINTER_FROM_INT((!is_array || is_expand) ? i : index); + } +} + +/** + * Insert a decorator item for a button with the same property as \a prop. + * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a propname. + */ +void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index) +{ + PropertyRNA *prop = NULL; + + if (ptr && propname) { + /* validate arguments */ + prop = RNA_struct_find_property(ptr, propname); + if (!prop) { + ui_item_disabled(layout, propname); + RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + return; + } + } + + /* ptr and prop are allowed to be NULL here. */ + uiItemDecoratorR_prop(layout, ptr, prop, index); +} + /* popover */ void uiItemPopoverPanel_ptr( uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon) @@ -3004,33 +3161,40 @@ void uiItemL(uiLayout *layout, const char *name, int icon) } /** - * Helper to add a label, which handles logic for split property layout if needed. - * - * Normally, we handle the split layout in #uiItemFullR(), but there are other cases where we may - * want to use the logic. For those this helper was added, although it will likely have to be - * extended to support more cases. - * Ideally, #uiItemFullR() could just call this, but it currently has too many special needs. - * - * \return A layout placed in the row after the split layout. Used to place decorator items. + * Normally, we handle the split layout in #uiItemFullR(), but there are other cases where the + * logic is needed. Ideally, #uiItemFullR() could just call this, but it currently has too many + * special needs. + */ +uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout) +{ + uiPropertySplitWrapper split_wrapper = {NULL}; + + uiLayout *layout_row = uiLayoutRow(parent_layout, true); + uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true); + + layout_split->space = 0; + split_wrapper.label_column = uiLayoutColumn(layout_split, true); + split_wrapper.label_column->alignment = UI_LAYOUT_ALIGN_RIGHT; + split_wrapper.property_row = ui_item_prop_split_layout_hack(parent_layout, layout_split); + split_wrapper.decorate_column = uiLayoutColumn(layout_row, true); + + return split_wrapper; +} + +/* + * Helper to add a label and creates a property split layout if needed. */ uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon) { if (layout->item.flag & UI_ITEM_PROP_SEP) { uiBlock *block = uiLayoutGetBlock(layout); - uiLayout *layout_row = uiLayoutRow(layout, true); - uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true); - uiLayout *layout_sub = uiLayoutColumn(layout_split, true); - - layout_split->space = layout_sub->space = layout_row->space = 0; - layout_sub->alignment = UI_LAYOUT_ALIGN_RIGHT; + uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(layout); + /* Further items added to 'layout' will automatically be added to split_wrapper.property_row */ - uiItemL_(layout_sub, text, icon); + uiItemL_(split_wrapper.label_column, text, icon); + UI_block_layout_set_current(block, split_wrapper.property_row); - layout_split = ui_item_prop_split_layout_hack(layout, layout_split); - UI_block_layout_set_current(block, layout_split); - - /* Give caller a new sub-row to place items in. */ - return layout_row; + return split_wrapper.decorate_column; } else { char namestr[UI_MAX_NAME_STR]; @@ -4471,13 +4635,24 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali litem->redalert = layout->redalert; litem->w = layout->w; litem->emboss = layout->emboss; - litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE)); + litem->item.flag = (layout->item.flag & + (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE | UI_ITEM_INSIDE_PROP_SEP)); if (layout->child_items_layout) { BLI_addtail(&layout->child_items_layout->items, litem); + litem->parent = layout->child_items_layout; } else { BLI_addtail(&layout->items, litem); + litem->parent = layout; + } +} + +static void ui_layout_heading_set(uiLayout *layout, const char *heading) +{ + BLI_assert(layout->heading[0] == '\0'); + if (heading) { + STRNCPY(layout->heading, heading); } } @@ -4497,6 +4672,16 @@ uiLayout *uiLayoutRow(uiLayout *layout, bool align) return litem; } +/** + * See #uiLayoutColumnWithHeading(). + */ +uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading) +{ + uiLayout *litem = uiLayoutRow(layout, align); + ui_layout_heading_set(litem, heading); + return litem; +} + uiLayout *uiLayoutColumn(uiLayout *layout, bool align) { uiLayout *litem; @@ -4512,6 +4697,19 @@ uiLayout *uiLayoutColumn(uiLayout *layout, bool align) return litem; } +/** + * Variant of #uiLayoutColumn() that sets a heading label for the layout if the first item is + * added through #uiItemFullR(). If split layout is used and the item has no string to add to the + * first split-column, the heading is added there instead. Otherwise the heading inserted with a + * new row. + */ +uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading) +{ + uiLayout *litem = uiLayoutColumn(layout, align); + ui_layout_heading_set(litem, heading); + return litem; +} + uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align) { uiLayoutItemFlow *flow; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 53ea51c9e97..909da434554 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1135,8 +1135,9 @@ static bool jump_to_target_button(bContext *C, bool poll) else if (type == PROP_STRING) { const uiBut *but = UI_context_active_but_get(C); - if (but->type == UI_BTYPE_SEARCH_MENU && but->search_func == ui_rna_collection_search_cb) { - uiRNACollectionSearch *coll_search = but->search_arg; + if (but->type == UI_BTYPE_SEARCH_MENU && but->search && + but->search->update_fn == ui_rna_collection_search_update_fn) { + uiRNACollectionSearch *coll_search = but->search->arg; char str_buf[MAXBONENAME]; char *str_ptr = RNA_property_string_get_alloc(&ptr, prop, str_buf, sizeof(str_buf), NULL); @@ -1678,7 +1679,7 @@ static void UI_OT_button_execute(wmOperatorType *ot) static int button_string_clear_exec(bContext *C, wmOperator *UNUSED(op)) { - uiBut *but = UI_context_active_but_get(C); + uiBut *but = UI_context_active_but_get_respect_menu(C); if (but) { ui_but_active_string_clear_and_exit(C, but); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 2ad1c25305c..04179721305 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -102,6 +102,7 @@ typedef struct uiHandlePanelData { double starttime; /* dragging */ + bool is_drag_drop; int startx, starty; int startofsx, startofsy; int startsizex, startsizey; @@ -743,7 +744,7 @@ void ui_draw_aligned_panel(uiStyle *style, /* an open panel */ else { /* in some occasions, draw a border */ - if (panel->flag & PNL_SELECT) { + if (panel->flag & PNL_SELECT && !is_subpanel) { if (panel->control & UI_PNL_SOLID) { UI_draw_roundbox_corner_set(UI_CNR_ALL); } @@ -876,6 +877,16 @@ static int get_panel_real_ofsx(Panel *panel) } } +bool UI_panel_is_dragging(const struct Panel *panel) +{ + uiHandlePanelData *data = panel->activedata; + if (!data) { + return false; + } + + return data->is_drag_drop; +} + typedef struct PanelSort { Panel *panel, *orig; } PanelSort; @@ -2458,6 +2469,24 @@ static void ui_handler_remove_panel(bContext *C, void *userdata) panel_activate_state(C, panel, PANEL_STATE_EXIT); } +/** + * Set selection state for a panel and its subpanels. The subpanels need to know they are selected + * too so they can be drawn above their parent when it is dragged. + */ +static void set_panel_selection(Panel *panel, bool value) +{ + if (value) { + panel->flag |= PNL_SELECT; + } + else { + panel->flag &= ~PNL_SELECT; + } + + LISTBASE_FOREACH (Panel *, child, &panel->children) { + set_panel_selection(child, value); + } +} + static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state) { uiHandlePanelData *data = panel->activedata; @@ -2468,6 +2497,8 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS return; } + bool was_drag_drop = (data && data->state == PANEL_STATE_DRAG); + if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) { if (data && data->state != PANEL_STATE_ANIMATION) { /* XXX: @@ -2480,10 +2511,10 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS check_panel_overlap(region, NULL); /* clears */ } - panel->flag &= ~PNL_SELECT; + set_panel_selection(panel, false); } else { - panel->flag |= PNL_SELECT; + set_panel_selection(panel, true); } if (data && data->animtimer) { @@ -2519,6 +2550,12 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS data->startsizex = panel->sizex; data->startsizey = panel->sizey; data->starttime = PIL_check_seconds_timer(); + + /* Remember drag drop state even when animating to the aligned position after dragging. */ + data->is_drag_drop = was_drag_drop; + if (state == PANEL_STATE_DRAG) { + data->is_drag_drop = true; + } } ED_region_tag_redraw(region); diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index 31ef7261eb3..3e34b7f3f8a 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -581,21 +581,18 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) /** \name Popup Block API * \{ */ -void UI_popup_block_invoke_ex(bContext *C, - uiBlockCreateFunc func, - void *arg, - void (*arg_free)(void *arg), - const char *opname, - int opcontext) +void UI_popup_block_invoke_ex( + bContext *C, uiBlockCreateFunc func, void *arg, void (*arg_free)(void *arg), bool can_refresh) { wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free); handle->popup = true; - handle->can_refresh = true; - handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL; - handle->opcontext = opcontext; + + /* It can be useful to disable refresh (even though it will work) + * as this exists text fields which can be disruptive if refresh isn't needed. */ + handle->can_refresh = can_refresh; UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first); @@ -607,7 +604,7 @@ void UI_popup_block_invoke(bContext *C, void *arg, void (*arg_free)(void *arg)) { - UI_popup_block_invoke_ex(C, func, arg, arg_free, NULL, WM_OP_INVOKE_DEFAULT); + UI_popup_block_invoke_ex(C, func, arg, arg_free, true); } void UI_popup_block_ex(bContext *C, diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index e2c87891169..0007f6ab9a2 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -35,6 +35,7 @@ #include "BLI_math.h" +#include "BLI_listbase.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -153,7 +154,8 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int /* Limit flags that can be set so flags such as 'UI_SELECT' aren't accidentally set * which will cause problems, add others as needed. */ - BLI_assert((state & ~(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT)) == 0); + BLI_assert( + (state & ~(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)) == 0); if (items->states) { items->states[items->totitem] = state; } @@ -295,10 +297,31 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region) } } -void ui_searchbox_event(bContext *C, ARegion *region, uiBut *but, const wmEvent *event) +static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C, + struct ARegion *region, + int *UNUSED(r_pass), + double *UNUSED(pass_delay), + bool *r_exit_on_event) +{ + *r_exit_on_event = true; + + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->search && but->search->tooltip_fn) { + return but->search->tooltip_fn(C, region, but->search->arg, but->func_arg2); + } + } + } + return NULL; +} + +bool ui_searchbox_event( + bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *event) { uiSearchboxData *data = region->regiondata; int type = event->type, val = event->val; + bool handled = false; + bool tooltip_timer_started = false; if (type == MOUSEPAN) { ui_pan_to_scroll(event, &type, &val); @@ -308,12 +331,36 @@ void ui_searchbox_event(bContext *C, ARegion *region, uiBut *but, const wmEvent case WHEELUPMOUSE: case EVT_UPARROWKEY: ui_searchbox_select(C, region, but, -1); + handled = true; break; case WHEELDOWNMOUSE: case EVT_DOWNARROWKEY: ui_searchbox_select(C, region, but, 1); + handled = true; break; - case MOUSEMOVE: + case RIGHTMOUSE: + if (val) { + if (but->search->context_menu_fn) { + if (data->active != -1) { + /* Check the cursor is over the active element + * (a little confusing if this isn't the case, although it does work). */ + rcti rect; + ui_searchbox_butrect(&rect, data, data->active); + if (BLI_rcti_isect_pt( + &rect, event->x - region->winrct.xmin, event->y - region->winrct.ymin)) { + + void *active = data->items.pointers[data->active]; + if (but->search->context_menu_fn(C, but->search->arg, active, event)) { + handled = true; + } + } + } + } + } + break; + case MOUSEMOVE: { + bool is_inside = false; + if (BLI_rcti_isect_pt(®ion->winrct, event->x, event->y)) { rcti rect; int a; @@ -322,16 +369,46 @@ void ui_searchbox_event(bContext *C, ARegion *region, uiBut *but, const wmEvent ui_searchbox_butrect(&rect, data, a); if (BLI_rcti_isect_pt( &rect, event->x - region->winrct.xmin, event->y - region->winrct.ymin)) { + is_inside = true; if (data->active != a) { data->active = a; ui_searchbox_select(C, region, but, 0); + handled = true; break; } } } } + + if (U.flag & USER_TOOLTIPS) { + if (is_inside) { + if (data->active != -1) { + ScrArea *area = CTX_wm_area(C); + but->func_arg2 = data->items.pointers[data->active]; + WM_tooltip_timer_init(C, CTX_wm_window(C), area, butregion, wm_searchbox_tooltip_init); + tooltip_timer_started = true; + } + } + } + break; + } } + + if (handled && (tooltip_timer_started == false)) { + wmWindow *win = CTX_wm_window(C); + WM_tooltip_clear(C, win); + } + + return handled; +} + +/** Wrap #uiButSearchUpdateFn callback. */ +static void ui_searchbox_update_fn(bContext *C, uiBut *but, const char *str, uiSearchItems *items) +{ + wmWindow *win = CTX_wm_window(C); + WM_tooltip_clear(C, win); + but->search->update_fn(C, but->search->arg, str, items); } /* region is the search box itself */ @@ -350,9 +427,9 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re data->active = -1; /* handle active */ - if (but->search_func && but->func_arg2) { + if (but->search->update_fn && but->func_arg2) { data->items.active = but->func_arg2; - but->search_func(C, but->search_arg, but->editstr, &data->items); + ui_searchbox_update_fn(C, but, but->editstr, &data->items); data->items.active = NULL; /* found active item, calculate real offset by centering it */ @@ -381,8 +458,8 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re } /* callback */ - if (but->search_func) { - but->search_func(C, but->search_arg, but->editstr, &data->items); + if (but->search->update_fn) { + ui_searchbox_update_fn(C, but, but->editstr, &data->items); } /* handle case where editstr is equal to one of items */ @@ -416,7 +493,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *st if (str[0]) { data->items.autocpl = UI_autocomplete_begin(str, ui_but_string_get_max_length(but)); - but->search_func(C, but->search_arg, but->editstr, &data->items); + ui_searchbox_update_fn(C, but, but->editstr, &data->items); match = UI_autocomplete_end(data->items.autocpl, str); data->items.autocpl = NULL; @@ -603,7 +680,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) { data->use_sep = true; } - data->sep_string = but->search_sep_string; + data->sep_string = but->search->sep_string; /* compute position */ if (but->block->flag & UI_BLOCK_SEARCH_MENU) { @@ -881,7 +958,7 @@ void ui_but_search_refresh(uiBut *but) items->names[x1] = MEM_callocN(but->hardmax + 1, "search names"); } - but->search_func(but->block->evil_C, but->search_arg, but->drawstr, items); + ui_searchbox_update_fn(but->block->evil_C, but, but->drawstr, items); /* only redalert when we are sure of it, this can miss cases when >10 matches */ if (items->totitem == 0) { diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c new file mode 100644 index 00000000000..0a06f765c0e --- /dev/null +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -0,0 +1,1098 @@ +/* + * 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 + * + * Search available menu items via the user interface & key-maps. + * Accessed via the #WM_OT_search_menu operator. + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_action_types.h" +#include "DNA_gpencil_modifier_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_shader_fx_types.h" +#include "DNA_texture_types.h" + +#include "BLI_alloca.h" +#include "BLI_dynstr.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_listbase.h" +#include "BLI_math_matrix.h" +#include "BLI_memarena.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_screen.h" + +#include "ED_screen.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "interface_intern.h" + +/* For key-map item access. */ +#include "wm_event_system.h" + +/* -------------------------------------------------------------------- */ +/** \name Menu Search Template Implementation + * \{ */ + +/* Unicode arrow. */ +#define MENU_SEP "\xe2\x96\xb6" + +/** + * Use when #menu_items_from_ui_create is called with `include_all_areas`. + * so we can run the menu item in the area it was extracted from. + */ +struct MenuSearch_Context { + /** + * Index into `Area.ui_type` #EnumPropertyItem or the top-bar when -1. + * Needed to get the display-name to use as a prefix for each menu item. + */ + int space_type_ui_index; + + ScrArea *area; + ARegion *region; +}; + +struct MenuSearch_Parent { + struct MenuSearch_Parent *parent; + MenuType *parent_mt; + const char *drawstr; + + /** Set while writing menu items only. */ + struct MenuSearch_Parent *temp_child; +}; + +struct MenuSearch_Item { + struct MenuSearch_Item *next, *prev; + const char *drawstr; + const char *drawwstr_full; + /** Support a single level sub-menu nesting (for operator buttons that expand). */ + const char *drawstr_submenu; + int icon; + int state; + + struct MenuSearch_Parent *menu_parent; + MenuType *mt; + + enum { + MENU_SEARCH_TYPE_OP = 1, + MENU_SEARCH_TYPE_RNA = 2, + } type; + + union { + /** Operator menu item. */ + struct { + wmOperatorType *type; + PointerRNA *opptr; + short opcontext; + bContextStore *context; + } op; + + /** Property (only for check-box/boolean). */ + struct { + PointerRNA ptr; + PropertyRNA *prop; + int index; + /** Only for enum buttons. */ + int enum_value; + } rna; + }; + + /** Set when we need each menu item to be able to set it's own context. may be NULL. */ + struct MenuSearch_Context *wm_context; +}; + +struct MenuSearch_Data { + /** MenuSearch_Item */ + ListBase items; + /** Use for all small allocations. */ + MemArena *memarena; + + /** Use for context menu, to fake a button to create a context menu. */ + struct { + uiBut but; + uiBlock block; + } context_menu_data; +}; + +static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v) +{ + const struct MenuSearch_Item *menu_item_a = menu_item_a_v; + const struct MenuSearch_Item *menu_item_b = menu_item_b_v; + return strcmp(menu_item_a->drawwstr_full, menu_item_b->drawwstr_full); +} + +static const char *strdup_memarena(MemArena *memarena, const char *str) +{ + const uint str_size = strlen(str) + 1; + char *str_dst = BLI_memarena_alloc(memarena, str_size); + memcpy(str_dst, str, str_size); + return str_dst; +} + +static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str) +{ + const uint str_size = BLI_dynstr_get_len(dyn_str) + 1; + char *str_dst = BLI_memarena_alloc(memarena, str_size); + BLI_dynstr_get_cstring_ex(dyn_str, str_dst); + return str_dst; +} + +static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *data, + MemArena *memarena, + struct MenuType *mt, + const char *drawstr_submenu, + uiBut *but, + struct MenuSearch_Context *wm_context) +{ + struct MenuSearch_Item *item = NULL; + if (but->optype != NULL) { + item = BLI_memarena_calloc(memarena, sizeof(*item)); + item->type = MENU_SEARCH_TYPE_OP; + + item->op.type = but->optype; + item->op.opcontext = but->opcontext; + item->op.context = but->context; + item->op.opptr = but->opptr; + but->opptr = NULL; + } + else if (but->rnaprop != NULL) { + const int prop_type = RNA_property_type(but->rnaprop); + if (!ELEM(prop_type, PROP_BOOLEAN, PROP_ENUM)) { + /* Note that these buttons are not prevented, + * but aren't typically used in menus. */ + printf("Button '%s' in menu '%s' is a menu item with unsupported RNA type %d\n", + but->drawstr, + mt->idname, + prop_type); + } + else { + item = BLI_memarena_calloc(memarena, sizeof(*item)); + item->type = MENU_SEARCH_TYPE_RNA; + + item->rna.ptr = but->rnapoin; + item->rna.prop = but->rnaprop; + item->rna.index = but->rnaindex; + + if (prop_type == PROP_ENUM) { + item->rna.enum_value = (int)but->hardmax; + } + } + } + + if (item != NULL) { + /* Handle shared settings. */ + item->drawstr = strdup_memarena(memarena, but->drawstr); + item->icon = ui_but_icon(but); + item->state = (but->flag & + (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)); + item->mt = mt; + item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL; + + item->wm_context = wm_context; + + BLI_addtail(&data->items, item); + return true; + } + + return false; +} + +/** + * Populate a fake button from a menu item (use for context menu). + */ +static bool menu_items_to_ui_button(struct MenuSearch_Item *item, uiBut *but) +{ + bool changed = false; + switch (item->type) { + case MENU_SEARCH_TYPE_OP: { + but->optype = item->op.type; + but->opcontext = item->op.opcontext; + but->context = item->op.context; + but->opptr = item->op.opptr; + changed = true; + break; + } + case MENU_SEARCH_TYPE_RNA: { + const int prop_type = RNA_property_type(item->rna.prop); + + but->rnapoin = item->rna.ptr; + but->rnaprop = item->rna.prop; + but->rnaindex = item->rna.index; + + if (prop_type == PROP_ENUM) { + but->hardmax = item->rna.enum_value; + } + changed = true; + break; + } + } + + if (changed) { + STRNCPY(but->drawstr, item->drawstr); + char *drawstr_sep = (item->state & UI_BUT_HAS_SEP_CHAR) ? strrchr(but->drawstr, UI_SEP_CHAR) : + NULL; + if (drawstr_sep) { + *drawstr_sep = '\0'; + } + + but->icon = item->icon; + but->str = but->strdata; + } + + return changed; +} + +/** + * Populate \a menu_stack with menus from inspecting active key-maps for this context. + */ +static void menu_types_add_from_keymap_items(bContext *C, + wmWindow *win, + ScrArea *area, + ARegion *region, + LinkNode **menuid_stack_p, + GHash *menu_to_kmi, + GSet *menu_tagged) +{ + wmWindowManager *wm = CTX_wm_manager(C); + ListBase *handlers[] = { + region ? ®ion->handlers : NULL, + area ? &area->handlers : NULL, + &win->handlers, + }; + + for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) { + if (handlers[handler_index] == NULL) { + continue; + } + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers[handler_index]) { + /* During this loop, UI handlers for nested menus can tag multiple handlers free. */ + if (handler_base->flag & WM_HANDLER_DO_FREE) { + continue; + } + if (handler_base->type != WM_HANDLER_TYPE_KEYMAP) { + continue; + } + + else if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); + if (keymap && WM_keymap_poll(C, keymap)) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { + if (kmi->flag & KMI_INACTIVE) { + continue; + } + if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) { + char menu_idname[MAX_NAME]; + RNA_string_get(kmi->ptr, "name", menu_idname); + MenuType *mt = WM_menutype_find(menu_idname, false); + + if (mt && BLI_gset_add(menu_tagged, mt)) { + /* Unlikely, but possible this will be included twice. */ + BLI_linklist_prepend(menuid_stack_p, mt); + + void **kmi_p; + if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) { + *kmi_p = kmi; + } + } + } + } + } + } + } + } +} + +/** + * Display all operators (last). Developer-only convenience feature. + */ +static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *data) +{ + /* Add to temporary list so we can sort them separately. */ + ListBase operator_items = {NULL, NULL}; + + MemArena *memarena = data->memarena; + GHashIterator iter; + for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); + BLI_ghashIterator_step(&iter)) { + wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + + if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) { + continue; + } + + if (WM_operator_poll((bContext *)C, ot)) { + const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); + + struct MenuSearch_Item *item = NULL; + item = BLI_memarena_calloc(memarena, sizeof(*item)); + item->type = MENU_SEARCH_TYPE_OP; + + item->op.type = ot; + item->op.opcontext = WM_OP_INVOKE_DEFAULT; + item->op.context = NULL; + + char idname_as_py[OP_MAX_TYPENAME]; + char uiname[256]; + WM_operator_py_idname(idname_as_py, ot->idname); + + SNPRINTF(uiname, "%s " MENU_SEP "%s", idname_as_py, ot_ui_name); + + item->drawwstr_full = strdup_memarena(memarena, uiname); + item->drawstr = ot_ui_name; + + item->wm_context = NULL; + + BLI_addtail(&operator_items, item); + } + } + + BLI_listbase_sort(&operator_items, menu_item_sort_by_drawstr_full); + + BLI_movelisttolist(&data->items, &operator_items); +} + +/** + * Create #MenuSearch_Data by inspecting the current context, this uses two methods: + * + * - Look-up pre-defined editor-menus. + * - Look-up key-map items which call menus. + */ +static struct MenuSearch_Data *menu_items_from_ui_create( + bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas) +{ + MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + /** Map (#MenuType to #MenuSearch_Parent) */ + GHash *menu_parent_map = BLI_ghash_ptr_new(__func__); + GHash *menu_display_name_map = BLI_ghash_ptr_new(__func__); + const uiStyle *style = UI_style_get_dpi(); + + /* Convert into non-ui structure. */ + struct MenuSearch_Data *data = MEM_callocN(sizeof(*data), __func__); + + DynStr *dyn_str = BLI_dynstr_new_memarena(); + + /* Use a stack of menus to handle and discover new menus in passes. */ + LinkNode *menu_stack = NULL; + + /* Tag menu types not to add, either because they have already been added + * or they have been blacklisted. + * Set of #MenuType. */ + GSet *menu_tagged = BLI_gset_ptr_new(__func__); + /** Map (#MenuType -> #wmKeyMapItem). */ + GHash *menu_to_kmi = BLI_ghash_ptr_new(__func__); + + /* Blacklist menus we don't want to show. */ + { + const char *idname_array[] = { + /* While we could include this, it's just showing filenames to load. */ + "TOPBAR_MT_file_open_recent", + }; + for (int i = 0; i < ARRAY_SIZE(idname_array); i++) { + MenuType *mt = WM_menutype_find(idname_array[i], false); + if (mt != NULL) { + BLI_gset_add(menu_tagged, mt); + } + } + } + + /* Collect contexts, one for each 'ui_type'. */ + struct MenuSearch_Context *wm_contexts = NULL; + + const EnumPropertyItem *space_type_ui_items = NULL; + int space_type_ui_items_len = 0; + bool space_type_ui_items_free = false; + + /* Text used as prefix for top-bar menu items. */ + const char *global_menu_prefix = NULL; + + if (include_all_areas) { + /* First create arrays for ui_type. */ + PropertyRNA *prop_ui_type = NULL; + { + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_Area, NULL, &ptr); + prop_ui_type = RNA_struct_find_property(&ptr, "ui_type"); + RNA_property_enum_items(C, + &ptr, + prop_ui_type, + &space_type_ui_items, + &space_type_ui_items_len, + &space_type_ui_items_free); + + wm_contexts = BLI_memarena_calloc(memarena, sizeof(*wm_contexts) * space_type_ui_items_len); + for (int i = 0; i < space_type_ui_items_len; i++) { + wm_contexts[i].space_type_ui_index = -1; + } + } + + bScreen *screen = WM_window_get_active_screen(win); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); + if (region != NULL) { + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_Area, area, &ptr); + const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type); + + int space_type_ui_index = RNA_enum_from_value(space_type_ui_items, space_type_ui); + if (space_type_ui_index == -1) { + continue; + } + + if (wm_contexts[space_type_ui_index].space_type_ui_index != -1) { + ScrArea *area_best = wm_contexts[space_type_ui_index].area; + const uint value_best = (uint)area_best->winx * (uint)area_best->winy; + const uint value_test = (uint)area->winx * (uint)area->winy; + if (value_best > value_test) { + continue; + } + } + + wm_contexts[space_type_ui_index].space_type_ui_index = space_type_ui_index; + wm_contexts[space_type_ui_index].area = area; + wm_contexts[space_type_ui_index].region = region; + } + } + + global_menu_prefix = CTX_IFACE_(RNA_property_translation_context(prop_ui_type), "Top Bar"); + } + + GHashIterator iter; + + for (int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len; + space_type_ui_index += 1) { + + ScrArea *area = NULL; + ARegion *region = NULL; + struct MenuSearch_Context *wm_context = NULL; + + if (include_all_areas) { + if (space_type_ui_index == -1) { + /* First run without any context, to populate the top-bar without. */ + wm_context = NULL; + area = NULL; + region = NULL; + } + else { + wm_context = &wm_contexts[space_type_ui_index]; + if (wm_context->space_type_ui_index == -1) { + continue; + } + + area = wm_context->area; + region = wm_context->region; + + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + } + } + else { + area = area_init; + region = region_init; + } + + /* Populate menus from the editors, + * note that we could create a fake header, draw the header and extract the menus + * from the buttons, however this is quite involved and can be avoided as by convention + * each space-type has a single root-menu that headers use. */ + { + const char *idname_array[2] = {NULL}; + int idname_array_len = 0; + + /* Use negative for global (no area) context, populate the top-bar. */ + if (space_type_ui_index == -1) { + idname_array[idname_array_len++] = "TOPBAR_MT_editor_menus"; + } + +#define SPACE_MENU_MAP(space_type, menu_id) \ + case space_type: \ + idname_array[idname_array_len++] = menu_id; \ + break +#define SPACE_MENU_NOP(space_type) \ + case space_type: \ + break + + if (area != NULL) { + SpaceLink *sl = area->spacedata.first; + switch ((eSpace_Type)area->spacetype) { + SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus"); + SPACE_MENU_NOP(SPACE_PROPERTIES); + SPACE_MENU_MAP(SPACE_FILE, "FILEBROWSER_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_ACTION, + (((const SpaceAction *)sl)->mode == SACTCONT_TIMELINE) ? + "TIME_MT_editor_menus" : + "DOPESHEET_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_CLIP, + (((const SpaceClip *)sl)->mode == SC_MODE_TRACKING) ? + "CLIP_MT_tracking_editor_menus" : + "CLIP_MT_masking_editor_menus"); + SPACE_MENU_NOP(SPACE_EMPTY); + SPACE_MENU_NOP(SPACE_SCRIPT); + SPACE_MENU_NOP(SPACE_STATUSBAR); + SPACE_MENU_NOP(SPACE_TOPBAR); + } + } + for (int i = 0; i < idname_array_len; i++) { + MenuType *mt = WM_menutype_find(idname_array[i], false); + if (mt != NULL) { + /* Check if this exists because of 'include_all_areas'. */ + if (BLI_gset_add(menu_tagged, mt)) { + BLI_linklist_prepend(&menu_stack, mt); + } + } + } + } +#undef SPACE_MENU_MAP +#undef SPACE_MENU_NOP + + bool has_keymap_menu_items = false; + + while (menu_stack != NULL) { + MenuType *mt = BLI_linklist_pop(&menu_stack); + if (!WM_menutype_poll(C, mt)) { + continue; + } + + uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); + uiLayout *layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + + UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); + + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); + UI_menutype_draw(C, mt, layout); + + UI_block_end(C, block); + + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + MenuType *mt_from_but = NULL; + /* Support menu titles with dynamic from initial labels + * (used by edit-mesh context menu). */ + if (but->type == UI_BTYPE_LABEL) { + + /* Check if the label is the title. */ + uiBut *but_test = but->prev; + while (but_test && but_test->type == UI_BTYPE_SEPR) { + but_test = but_test->prev; + } + + if (but_test == NULL) { + BLI_ghash_insert( + menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr)); + } + } + else if (menu_items_from_ui_create_item_from_button( + data, memarena, mt, NULL, but, wm_context)) { + /* pass */ + } + else if ((mt_from_but = UI_but_menutype_get(but))) { + + if (BLI_gset_add(menu_tagged, mt_from_but)) { + BLI_linklist_prepend(&menu_stack, mt_from_but); + } + + if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) { + struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena, + sizeof(*menu_parent)); + /* Use brackets for menu key shortcuts, + * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)". + * This is needed so we don't right align sub-menu contents + * we only want to do that for the last menu item, not the path that leads to it. + */ + const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ? + strrchr(but->drawstr, UI_SEP_CHAR) : + NULL; + bool drawstr_is_empty = false; + if (drawstr_sep != NULL) { + BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); + /* Detect empty string, fallback to menu name. */ + const char *drawstr = but->drawstr; + int drawstr_len = drawstr_sep - but->drawstr; + if (UNLIKELY(drawstr_len == 0)) { + drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); + drawstr_len = strlen(drawstr); + if (drawstr[0] == '\0') { + drawstr_is_empty = true; + } + } + BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len); + BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1); + menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str); + BLI_dynstr_clear(dyn_str); + } + else { + const char *drawstr = but->drawstr; + if (UNLIKELY(drawstr[0] == '\0')) { + drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); + if (drawstr[0] == '\0') { + drawstr_is_empty = true; + } + } + menu_parent->drawstr = strdup_memarena(memarena, drawstr); + } + menu_parent->parent_mt = mt; + BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent); + + if (drawstr_is_empty) { + printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname); + } + } + } + else if (but->menu_create_func != NULL) { + /* A non 'MenuType' menu button. */ + + /* Only expand one level deep, this is mainly for expanding operator menus. */ + const char *drawstr_submenu = but->drawstr; + + /* +1 to avoid overlap with the current 'block'. */ + uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS); + uiLayout *sub_layout = UI_block_layout( + sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + + UI_block_flag_enable(sub_block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); + + uiLayoutSetOperatorContext(sub_layout, WM_OP_INVOKE_REGION_WIN); + + but->menu_create_func(C, sub_layout, but->poin); + + UI_block_end(C, sub_block); + + LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) { + menu_items_from_ui_create_item_from_button( + data, memarena, mt, drawstr_submenu, sub_but, wm_context); + } + + if (region) { + BLI_remlink(®ion->uiblocks, sub_block); + } + UI_block_free(NULL, sub_block); + } + } + if (region) { + BLI_remlink(®ion->uiblocks, block); + } + UI_block_free(NULL, block); + + /* Add key-map items as a second pass, + * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */ + if ((menu_stack == NULL) && (has_keymap_menu_items == false)) { + has_keymap_menu_items = true; + menu_types_add_from_keymap_items( + C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged); + } + } + } + + LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { + item->menu_parent = BLI_ghash_lookup(menu_parent_map, item->mt); + } + + GHASH_ITER (iter, menu_parent_map) { + struct MenuSearch_Parent *menu_parent = BLI_ghashIterator_getValue(&iter); + menu_parent->parent = BLI_ghash_lookup(menu_parent_map, menu_parent->parent_mt); + } + + /* NOTE: currently this builds the full path for each menu item, + * that could be moved into the parent menu. */ + + /* Set names as full paths. */ + LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { + BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); + + if (include_all_areas) { + BLI_dynstr_appendf(dyn_str, + "%s: ", + (item->wm_context != NULL) ? + space_type_ui_items[item->wm_context->space_type_ui_index].name : + global_menu_prefix); + } + + if (item->menu_parent != NULL) { + struct MenuSearch_Parent *menu_parent = item->menu_parent; + menu_parent->temp_child = NULL; + while (menu_parent && menu_parent->parent) { + menu_parent->parent->temp_child = menu_parent; + menu_parent = menu_parent->parent; + } + while (menu_parent) { + BLI_dynstr_append(dyn_str, menu_parent->drawstr); + BLI_dynstr_append(dyn_str, " " MENU_SEP " "); + menu_parent = menu_parent->temp_child; + } + } + else { + const char *drawstr = BLI_ghash_lookup(menu_display_name_map, item->mt); + if (drawstr == NULL) { + drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label); + } + BLI_dynstr_append(dyn_str, drawstr); + + wmKeyMapItem *kmi = BLI_ghash_lookup(menu_to_kmi, item->mt); + if (kmi != NULL) { + char kmi_str[128]; + WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); + BLI_dynstr_appendf(dyn_str, " (%s)", kmi_str); + } + + BLI_dynstr_append(dyn_str, " " MENU_SEP " "); + } + + /* Optional nested menu. */ + if (item->drawstr_submenu != NULL) { + BLI_dynstr_append(dyn_str, item->drawstr_submenu); + BLI_dynstr_append(dyn_str, " " MENU_SEP " "); + } + + BLI_dynstr_append(dyn_str, item->drawstr); + + item->drawwstr_full = strdup_memarena_from_dynstr(memarena, dyn_str); + BLI_dynstr_clear(dyn_str); + } + BLI_dynstr_free(dyn_str); + + /* Finally sort menu items. + * + * 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); + BLI_ghash_free(menu_display_name_map, NULL, NULL); + + BLI_ghash_free(menu_to_kmi, NULL, NULL); + + BLI_gset_free(menu_tagged, NULL); + + data->memarena = memarena; + + if (include_all_areas) { + CTX_wm_area_set(C, area_init); + CTX_wm_region_set(C, region_init); + + if (space_type_ui_items_free) { + MEM_freeN((void *)space_type_ui_items); + } + } + + /* Include all operators for developers, + * since it can be handy to have a quick way to access any operator, + * including operators being developed which haven't yet been added into the interface. + * + * These are added after all menu items so developers still get normal behavior by default, + * unless searching for something that isn't already in a menu (or scroll down). + * + * Keep this behind a developer only check: + * - Many operators need options to be set to give useful results, see: T74157. + * - User who really prefer to list all operators can use #WM_OT_search_operator. + */ + if (U.flag & USER_DEVELOPER_UI) { + menu_items_from_all_operators(C, data); + } + + return data; +} + +static void menu_search_arg_free_fn(void *data_v) +{ + struct MenuSearch_Data *data = data_v; + LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { + switch (item->type) { + case MENU_SEARCH_TYPE_OP: { + if (item->op.opptr != NULL) { + WM_operator_properties_free(item->op.opptr); + MEM_freeN(item->op.opptr); + } + } + case MENU_SEARCH_TYPE_RNA: { + break; + } + } + } + + BLI_memarena_free(data->memarena); + + MEM_freeN(data); +} + +static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2) +{ + struct MenuSearch_Item *item = arg2; + if (item == NULL) { + return; + } + if (item->state & UI_BUT_DISABLED) { + return; + } + + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + + switch (item->type) { + case MENU_SEARCH_TYPE_OP: { + CTX_store_set(C, item->op.context); + WM_operator_name_call_ptr(C, item->op.type, item->op.opcontext, item->op.opptr); + CTX_store_set(C, NULL); + break; + } + case MENU_SEARCH_TYPE_RNA: { + PointerRNA *ptr = &item->rna.ptr; + PropertyRNA *prop = item->rna.prop; + int index = item->rna.index; + const int prop_type = RNA_property_type(prop); + bool changed = false; + + if (prop_type == PROP_BOOLEAN) { + const bool is_array = RNA_property_array_check(prop); + if (is_array) { + const bool value = RNA_property_boolean_get_index(ptr, prop, index); + RNA_property_boolean_set_index(ptr, prop, index, !value); + } + else { + const bool value = RNA_property_boolean_get(ptr, prop); + RNA_property_boolean_set(ptr, prop, !value); + } + changed = true; + } + else if (prop_type == PROP_ENUM) { + RNA_property_enum_set(ptr, prop, item->rna.enum_value); + changed = true; + } + + if (changed) { + RNA_property_update(C, ptr, prop); + } + break; + } + } + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } +} + +static void menu_search_update_fn(const bContext *UNUSED(C), + void *arg, + const char *str, + uiSearchItems *items) +{ + struct MenuSearch_Data *data = arg; + const size_t str_len = strlen(str); + const int words_max = (str_len / 2) + 1; + int(*words)[2] = BLI_array_alloca(words, words_max); + + const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); + + for (struct MenuSearch_Item *item = data->items.first; item; item = item->next) { + int index; + + /* match name against all search words */ + for (index = 0; index < words_len; index++) { + if (!ui_str_has_word_prefix(item->drawwstr_full, str + words[index][0], words[index][1])) { + break; + } + } + + if (index == words_len) { + if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state)) { + break; + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Context Menu + * + * This uses a fake button to create a context menu, + * if this ever causes hard to solve bugs we may need to create + * a separate context menu just for the search, however this is fairly involved. + * \{ */ + +static bool ui_search_menu_create_context_menu(struct bContext *C, + void *arg, + void *active, + const struct wmEvent *UNUSED(event)) +{ + struct MenuSearch_Data *data = arg; + struct MenuSearch_Item *item = active; + bool has_menu = false; + + memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data)); + uiBut *but = &data->context_menu_data.but; + uiBlock *block = &data->context_menu_data.block; + + but->block = block; + + if (menu_items_to_ui_button(item, but)) { + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + + if (ui_popup_context_menu_for_button(C, but)) { + has_menu = true; + } + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } + } + + return has_menu; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tooltip + * \{ */ + +static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C, + struct ARegion *region, + void *arg, + void *active) +{ + struct MenuSearch_Data *data = arg; + struct MenuSearch_Item *item = active; + + memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data)); + uiBut *but = &data->context_menu_data.but; + uiBlock *block = &data->context_menu_data.block; + unit_m4(block->winmat); + block->aspect = 1; + + but->block = block; + + /* Place the fake button at the cursor so the tool-tip is places properly. */ + float tip_init[2]; + const wmEvent *event = CTX_wm_window(C)->eventstate; + tip_init[0] = event->x; + tip_init[1] = event->y - (UI_UNIT_Y / 2); + ui_window_to_block_fl(region, block, &tip_init[0], &tip_init[1]); + + but->rect.xmin = tip_init[0]; + but->rect.xmax = tip_init[0]; + but->rect.ymin = tip_init[1]; + but->rect.ymax = tip_init[1]; + + if (menu_items_to_ui_button(item, but)) { + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + + ARegion *region_tip = UI_tooltip_create_from_button(C, region, but, false); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } + return region_tip; + } + + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Menu Search Template Public API + * \{ */ + +void UI_but_func_menu_search(uiBut *but) +{ + bContext *C = but->block->evil_C; + wmWindow *win = CTX_wm_window(C); + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + /* When run from top-bar scan all areas in the current window. */ + bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR)); + struct MenuSearch_Data *data = menu_items_from_ui_create( + C, win, area, region, include_all_areas); + UI_but_func_search_set(but, + /* Generic callback. */ + ui_searchbox_create_menu, + menu_search_update_fn, + data, + menu_search_arg_free_fn, + menu_search_exec_fn, + NULL); + + UI_but_func_search_set_context_menu(but, ui_search_menu_create_context_menu); + UI_but_func_search_set_tooltip(but, ui_search_menu_create_tooltip); + UI_but_func_search_set_sep_string(but, MENU_SEP); +} + +void uiTemplateMenuSearch(uiLayout *layout) +{ + uiBlock *block; + uiBut *but; + static char search[256] = ""; + + block = uiLayoutGetBlock(layout); + UI_block_layout_set_current(block, layout); + + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); + UI_but_func_menu_search(but); +} + +#undef MENU_SEP + +/** \} */ diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c new file mode 100644 index 00000000000..cdf87103587 --- /dev/null +++ b/source/blender/editors/interface/interface_template_search_operator.c @@ -0,0 +1,151 @@ +/* + * 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 + * + * Search available operators by scanning all and checking their poll function. + * accessed via the #WM_OT_search_operator operator. + */ + +#include <string.h> + +#include "DNA_gpencil_modifier_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_shader_fx_types.h" +#include "DNA_texture_types.h" + +#include "BLI_alloca.h" +#include "BLI_ghash.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_context.h" +#include "BKE_global.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "interface_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Operator Search Template Implementation + * \{ */ + +static void operator_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2) +{ + wmOperatorType *ot = arg2; + + if (ot) { + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL); + } +} + +static void operator_search_update_fn(const bContext *C, + void *UNUSED(arg), + const char *str, + uiSearchItems *items) +{ + GHashIterator iter; + const size_t str_len = strlen(str); + const int words_max = (str_len / 2) + 1; + int(*words)[2] = BLI_array_alloca(words, words_max); + + const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); + + for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); + BLI_ghashIterator_step(&iter)) { + wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); + int index; + + if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) { + continue; + } + + /* match name against all search words */ + for (index = 0; index < words_len; index++) { + if (!ui_str_has_word_prefix(ot_ui_name, str + words[index][0], words[index][1])) { + break; + } + } + + if (index == words_len) { + if (WM_operator_poll((bContext *)C, ot)) { + char name[256]; + int len = strlen(ot_ui_name); + + /* display name for menu, can hold hotkey */ + BLI_strncpy(name, ot_ui_name, sizeof(name)); + + /* check for hotkey */ + if (len < sizeof(name) - 6) { + if (WM_key_event_operator_string(C, + ot->idname, + WM_OP_EXEC_DEFAULT, + NULL, + true, + &name[len + 1], + sizeof(name) - len - 1)) { + name[len] = UI_SEP_CHAR; + } + } + + if (!UI_search_item_add(items, name, ot, ICON_NONE, 0)) { + break; + } + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operator Search Template API + * \{ */ + +void UI_but_func_operator_search(uiBut *but) +{ + UI_but_func_search_set(but, + ui_searchbox_create_operator, + operator_search_update_fn, + NULL, + false, + operator_search_exec_fn, + NULL); +} + +void uiTemplateOperatorSearch(uiLayout *layout) +{ + uiBlock *block; + uiBut *but; + static char search[256] = ""; + + block = uiLayoutGetBlock(layout); + UI_block_layout_set_current(block, layout); + + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); + UI_but_func_operator_search(but); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index ca9f12a4219..0e67f943ee6 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -37,18 +37,12 @@ #include "DNA_shader_fx_types.h" #include "DNA_texture_types.h" -#include "BLI_alloca.h" -#include "BLI_dynstr.h" #include "BLI_fnmatch.h" -#include "BLI_ghash.h" -#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_memarena.h" #include "BLI_path_util.h" #include "BLI_rect.h" #include "BLI_string.h" -#include "BLI_string_utils.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" @@ -73,7 +67,6 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_packedFile.h" -#include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -103,9 +96,6 @@ #include "PIL_time.h" -/* For key-map item access. */ -#include "wm_event_system.h" - // #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. /* defines for templateID/TemplateSearch */ @@ -213,9 +203,9 @@ static void template_add_button_search_menu(const bContext *C, static uiBlock *template_common_search_menu(const bContext *C, ARegion *region, - uiButSearchFunc search_func, + uiButSearchUpdateFn search_update_fn, void *search_arg, - uiButHandleFunc handle_func, + uiButHandleFunc search_exec_fn, void *active_item, const int preview_rows, const int preview_cols, @@ -289,11 +279,10 @@ static uiBlock *template_common_search_menu(const bContext *C, } UI_but_func_search_set(but, ui_searchbox_create_generic, - search_func, + search_update_fn, search_arg, NULL, - handle_func, - NULL, + search_exec_fn, active_item); UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); @@ -326,7 +315,7 @@ typedef struct TemplateID { } TemplateID; /* Search browse menu, assign */ -static void template_ID_set_property_cb(bContext *C, void *arg_template, void *item) +static void template_ID_set_property_exec_fn(bContext *C, void *arg_template, void *item) { TemplateID *template_ui = (TemplateID *)arg_template; @@ -461,7 +450,8 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) { static TemplateID template_ui; PointerRNA active_item_ptr; - void (*id_search_cb_p)(const bContext *, void *, const char *, uiSearchItems *) = id_search_cb; + void (*id_search_update_fn)( + const bContext *, void *, const char *, uiSearchItems *) = id_search_cb; /* arg_litem is malloced, can be freed by parent button */ template_ui = *((TemplateID *)arg_litem); @@ -471,16 +461,16 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) /* Currently only used for objects. */ if (template_ui.idcode == ID_OB) { if (template_ui.filter == UI_TEMPLATE_ID_FILTER_AVAILABLE) { - id_search_cb_p = id_search_cb_objects_from_scene; + id_search_update_fn = id_search_cb_objects_from_scene; } } } return template_common_search_menu(C, region, - id_search_cb_p, + id_search_update_fn, &template_ui, - template_ID_set_property_cb, + template_ID_set_property_exec_fn, active_item_ptr.data, template_ui.prv_rows, template_ui.prv_cols, @@ -688,6 +678,8 @@ static const char *template_id_browse_tip(const StructRNA *type) return N_("Browse Point Cloud Data to be linked"); case ID_VO: return N_("Browse Volume Data to be linked"); + case ID_SIM: + return N_("Browse Simulation to be linked"); } } return N_("Browse ID data to be linked"); @@ -705,6 +697,8 @@ static const char *template_id_context(StructRNA *type) } return BLT_I18NCONTEXT_DEFAULT; } +#else +# define template_id_context(type) 0 #endif static uiBut *template_id_def_new_but(uiBlock *block, @@ -753,7 +747,8 @@ static uiBut *template_id_def_new_but(uiBlock *block, BLT_I18NCONTEXT_ID_LIGHTPROBE, BLT_I18NCONTEXT_ID_HAIR, BLT_I18NCONTEXT_ID_POINTCLOUD, - BLT_I18NCONTEXT_ID_VOLUME, ); + BLT_I18NCONTEXT_ID_VOLUME, + BLT_I18NCONTEXT_ID_SIMULATION, ); /* 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. */ @@ -1187,7 +1182,7 @@ static void template_ID_tabs(bContext *C, 0.0f, 0.0f, ""); - UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id); + UI_but_funcN_set(&tab->but, template_ID_set_property_exec_fn, MEM_dupallocN(template), id); tab->but.custom_data = (void *)id; tab->but.dragpoin = id; tab->menu = mt; @@ -1533,7 +1528,7 @@ typedef struct TemplateSearch { int preview_rows, preview_cols; } TemplateSearch; -static void template_search_handle_cb(bContext *C, void *arg_template, void *item) +static void template_search_exec_fn(bContext *C, void *arg_template, void *item) { TemplateSearch *template_search = arg_template; uiRNACollectionSearch *coll_search = &template_search->search_data; @@ -1557,9 +1552,9 @@ static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_tem return template_common_search_menu(C, region, - ui_rna_collection_search_cb, + ui_rna_collection_search_update_fn, &template_search, - template_search_handle_cb, + template_search_exec_fn, active_ptr.data, template_search.preview_rows, template_search.preview_cols, @@ -1823,14 +1818,14 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) { Object *ob = ob_v; ModifierData *md = md_v; - ModifierData *nmd = modifier_new(md->type); + ModifierData *nmd = BKE_modifier_new(md->type); - modifier_copyData(md, nmd); + BKE_modifier_copydata(md, nmd); nmd->mode &= ~eModifierMode_Virtual; BLI_addhead(&ob->modifiers, nmd); - modifier_unique_name(&ob->modifiers, nmd); + BKE_modifier_unique_name(&ob->modifiers, nmd); ob->partype = PAROBJECT; @@ -1840,20 +1835,26 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) ED_undo_push(C, "Modifier convert to real"); } -static int modifier_can_delete(ModifierData *md) +static bool modifier_can_delete(ModifierData *md) { /* fluid particle modifier can't be deleted here */ if (md->type == eModifierType_ParticleSystem) { short particle_type = ((ParticleSystemModifierData *)md)->psys->part->type; - if (particle_type == PART_FLUID || particle_type == PART_FLUID_FLIP || - particle_type == PART_FLUID_FOAM || particle_type == PART_FLUID_SPRAY || - particle_type == PART_FLUID_BUBBLE || particle_type == PART_FLUID_TRACER || - particle_type == PART_FLUID_SPRAYFOAM || particle_type == PART_FLUID_SPRAYBUBBLE || - particle_type == PART_FLUID_FOAMBUBBLE || particle_type == PART_FLUID_SPRAYFOAMBUBBLE) { - return 0; + if (ELEM(particle_type, + PART_FLUID, + PART_FLUID_FLIP, + PART_FLUID_FOAM, + PART_FLUID_SPRAY, + PART_FLUID_BUBBLE, + PART_FLUID_TRACER, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { + return false; } } - return 1; + return true; } /* Check whether Modifier is a simulation or not, @@ -1888,7 +1889,7 @@ static uiLayout *draw_modifier(uiLayout *layout, int cageIndex, int lastCageIndex) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); PointerRNA ptr; uiBut *but; uiBlock *block; @@ -1982,9 +1983,9 @@ static uiLayout *draw_modifier(uiLayout *layout, } if (ob->type == OB_MESH) { - if (modifier_supportsCage(scene, md) && (index <= lastCageIndex)) { + if (BKE_modifier_supports_cage(scene, md) && (index <= lastCageIndex)) { sub = uiLayoutRow(row, true); - if (index < cageIndex || !modifier_couldBeCage(scene, md)) { + if (index < cageIndex || !BKE_modifier_couldbe_cage(scene, md)) { uiLayoutSetActive(sub, false); } uiItemR(sub, &ptr, "show_on_cage", 0, "", ICON_NONE); @@ -2080,7 +2081,7 @@ static uiLayout *draw_modifier(uiLayout *layout, "apply_as", MODIFIER_APPLY_DATA); - if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) { + if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) { uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"), @@ -2147,10 +2148,10 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE); /* find modifier and draw it */ - cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0); + cageIndex = BKE_modifiers_get_cage_index(scene, ob, &lastCageIndex, 0); /* XXX virtual modifiers are not accessible for python */ - vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); + vmd = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); for (i = 0; vmd; i++, vmd = vmd->next) { if (md == vmd) { @@ -2172,7 +2173,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) static uiLayout *gpencil_draw_modifier(uiLayout *layout, Object *ob, GpencilModifierData *md) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); PointerRNA ptr; uiBlock *block; uiLayout *box, *column, *row, *sub; @@ -2315,7 +2316,7 @@ uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), Point static uiLayout *gpencil_draw_shaderfx(uiLayout *layout, Object *ob, ShaderFxData *md) { - const ShaderFxTypeInfo *mti = BKE_shaderfxType_getInfo(md->type); + const ShaderFxTypeInfo *mti = BKE_shaderfx_get_info(md->type); PointerRNA ptr; uiBlock *block; uiLayout *box, *column, *row, *sub; @@ -2432,21 +2433,196 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA * /** \} */ /* -------------------------------------------------------------------- */ -/** \name Operator Redo Buttons Template +/** \name Operator Property Buttons Template * \{ */ -static void template_operator_redo_property_buts_draw( - const bContext *C, wmOperator *op, uiLayout *layout, int layout_flags, bool *r_has_advanced) +typedef struct uiTemplateOperatorPropertyPollParam { + const bContext *C; + wmOperator *op; + short flag; +} uiTemplateOperatorPropertyPollParam; + +#ifdef USE_OP_RESET_BUT +static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), + void *op_pt, + void *UNUSED(arg_dummy2)) +{ + WM_operator_properties_reset((wmOperator *)op_pt); +} +#endif + +static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *prop, + void *user_data) +{ + uiTemplateOperatorPropertyPollParam *params = user_data; + + if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) && + (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) { + return false; + } + return params->op->type->poll_property(params->C, params->op, prop); +} + +static eAutoPropButsReturn template_operator_property_buts_draw_single( + const bContext *C, + wmOperator *op, + uiLayout *layout, + const eButLabelAlign label_align, + int layout_flags) +{ + uiBlock *block = uiLayoutGetBlock(layout); + eAutoPropButsReturn return_info = 0; + + if (!op->properties) { + IDPropertyTemplate val = {0}; + op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + } + + /* poll() on this operator may still fail, + * at the moment there is no nice feedback when this happens just fails silently. */ + if (!WM_operator_repeat_check(C, op)) { + UI_block_lock_set(block, true, "Operator can't' redo"); + return return_info; + } + else { + /* useful for macros where only one of the steps can't be re-done */ + UI_block_lock_clear(block); + } + + if (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) { + uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE); + } + + /* menu */ + if (op->type->flag & OPTYPE_PRESET) { + /* XXX, no simple way to get WM_MT_operator_presets.bl_label + * from python! Label remains the same always! */ + PointerRNA op_ptr; + uiLayout *row; + + block->ui_operator = op; + + row = uiLayoutRow(layout, true); + uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE); + + wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); + uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_string_set(&op_ptr, "operator", op->type->idname); + + uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_string_set(&op_ptr, "operator", op->type->idname); + RNA_boolean_set(&op_ptr, "remove_active", true); + } + + if (op->type->ui) { + op->layout = layout; + 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. */ + } + else { + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags}; + const bool use_prop_split = (layout_flags & UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT) == 0; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + uiLayoutSetPropSep(layout, use_prop_split); + uiLayoutSetPropDecorate(layout, false); + + /* main draw call */ + return_info = uiDefAutoButsRNA( + layout, + &ptr, + op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL, + op->type->poll_property ? &user_data : NULL, + op->type->prop, + label_align, + (layout_flags & UI_TEMPLATE_OP_PROPS_COMPACT)); + + if ((return_info & UI_PROP_BUTS_NONE_ADDED) && + (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { + uiItemL(layout, IFACE_("No Properties"), ICON_NONE); + } + } + +#ifdef USE_OP_RESET_BUT + /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled + * but this is not so important if this button is drawn in those cases + * (which isn't all that likely anyway) - campbell */ + if (op->properties->len) { + uiBut *but; + uiLayout *col; /* needed to avoid alignment errors with previous buttons */ + + col = uiLayoutColumn(layout, false); + block = uiLayoutGetBlock(col); + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_FILE_REFRESH, + IFACE_("Reset"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + TIP_("Reset operator defaults")); + UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); + } +#endif + + /* set various special settings for buttons */ + + /* Only do this if we're not refreshing an existing UI. */ + if (block->oldblock == NULL) { + const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; + uiBut *but; + + for (but = block->buttons.first; but; but = but->next) { + /* no undo for buttons for operator redo panels */ + UI_but_flag_disable(but, UI_BUT_UNDO); + + /* only for popups, see [#36109] */ + + /* if button is operator's default property, and a text-field, enable focus for it + * - this is used for allowing operators with popups to rename stuff with fewer clicks + */ + if (is_popup) { + if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { + UI_but_focus_on_enter_event(CTX_wm_window(C), but); + } + } + } + } + + return return_info; +} + +static void template_operator_property_buts_draw_recursive(const bContext *C, + wmOperator *op, + uiLayout *layout, + const eButLabelAlign label_align, + int layout_flags, + bool *r_has_advanced) { if (op->type->flag & OPTYPE_MACRO) { LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) { - template_operator_redo_property_buts_draw(C, macro_op, layout, layout_flags, r_has_advanced); + template_operator_property_buts_draw_recursive( + C, macro_op, layout, label_align, layout_flags, r_has_advanced); } } else { /* Might want to make label_align adjustable somehow. */ - eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_NONE, layout_flags); + eAutoPropButsReturn return_info = template_operator_property_buts_draw_single( + C, op, layout, label_align, layout_flags); if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) { if (r_has_advanced) { *r_has_advanced = true; @@ -2455,6 +2631,61 @@ static void template_operator_redo_property_buts_draw( } } +static bool ui_layout_operator_properties_only_booleans(const bContext *C, + wmWindowManager *wm, + wmOperator *op, + int layout_flags) +{ + if (op->type->flag & OPTYPE_MACRO) { + LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) { + if (!ui_layout_operator_properties_only_booleans(C, wm, macro_op, layout_flags)) { + return false; + } + } + } + else { + uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags}; + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + RNA_STRUCT_BEGIN (&ptr, prop) { + if (RNA_property_flag(prop) & PROP_HIDDEN) { + continue; + } + if (op->type->poll_property && + !ui_layout_operator_buts_poll_property(&ptr, prop, &user_data)) { + continue; + } + if (RNA_property_type(prop) != PROP_BOOLEAN) { + return false; + } + } + RNA_STRUCT_END; + } + + return true; +} + +/** + * Draw Operator property buttons for redoing execution with different settings. + * This function does not initialize the layout, + * functions can be called on the layout before and after. + */ +void uiTemplateOperatorPropertyButs( + const bContext *C, uiLayout *layout, wmOperator *op, eButLabelAlign label_align, short flag) +{ + 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. */ + if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) { + flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT; + } + + template_operator_property_buts_draw_recursive(C, op, layout, label_align, flag, NULL); +} + void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) { wmOperator *op = WM_operator_last_redo(C); @@ -2487,8 +2718,8 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) #endif UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op); - template_operator_redo_property_buts_draw( - C, op, layout, layout_flags, NULL /* &has_advanced */); + template_operator_property_buts_draw_recursive( + C, op, layout, UI_BUT_LABEL_ALIGN_NONE, layout_flags, NULL /* &has_advanced */); /* Warning! this leaves the handle function for any other users of this block. */ #if 0 @@ -6583,952 +6814,6 @@ void uiTemplateList(uiLayout *layout, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Operator Search Template - * \{ */ - -static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2) -{ - wmOperatorType *ot = arg2; - - if (ot) { - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL); - } -} - -static bool has_word_prefix(const char *haystack, const char *needle, size_t needle_len) -{ - const char *match = BLI_strncasestr(haystack, needle, needle_len); - if (match) { - if ((match == haystack) || (*(match - 1) == ' ') || ispunct(*(match - 1))) { - return true; - } - else { - return has_word_prefix(match + 1, needle, needle_len); - } - } - else { - return false; - } -} - -static void operator_search_cb(const bContext *C, - void *UNUSED(arg), - const char *str, - uiSearchItems *items) -{ - GHashIterator iter; - const size_t str_len = strlen(str); - const int words_max = (str_len / 2) + 1; - int(*words)[2] = BLI_array_alloca(words, words_max); - - const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); - - for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); - BLI_ghashIterator_step(&iter)) { - wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); - const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); - int index; - - if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) { - continue; - } - - /* match name against all search words */ - for (index = 0; index < words_len; index++) { - if (!has_word_prefix(ot_ui_name, str + words[index][0], words[index][1])) { - break; - } - } - - if (index == words_len) { - if (WM_operator_poll((bContext *)C, ot)) { - char name[256]; - int len = strlen(ot_ui_name); - - /* display name for menu, can hold hotkey */ - BLI_strncpy(name, ot_ui_name, sizeof(name)); - - /* check for hotkey */ - if (len < sizeof(name) - 6) { - if (WM_key_event_operator_string(C, - ot->idname, - WM_OP_EXEC_DEFAULT, - NULL, - true, - &name[len + 1], - sizeof(name) - len - 1)) { - name[len] = UI_SEP_CHAR; - } - } - - if (!UI_search_item_add(items, name, ot, ICON_NONE, 0)) { - break; - } - } - } - } -} - -void UI_but_func_operator_search(uiBut *but) -{ - UI_but_func_search_set(but, - ui_searchbox_create_operator, - operator_search_cb, - NULL, - false, - operator_call_cb, - NULL, - NULL); -} - -void uiTemplateOperatorSearch(uiLayout *layout) -{ - uiBlock *block; - uiBut *but; - static char search[256] = ""; - - block = uiLayoutGetBlock(layout); - UI_block_layout_set_current(block, layout); - - but = uiDefSearchBut( - block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); - UI_but_func_operator_search(but); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Menu Search Template - * \{ */ - -/* Unicode arrow. */ -#define MENU_SEP "\xe2\x96\xb6" - -struct MenuSearch_Parent { - struct MenuSearch_Parent *parent; - MenuType *parent_mt; - /* Set while writing menu items only. */ - struct MenuSearch_Parent *temp_child; - const char *drawstr; -}; - -struct MenuSearch_Item { - struct MenuSearch_Item *next, *prev; - const char *drawstr; - const char *drawwstr_full; - /** Support a single level sub-menu nesting (for operator buttons that expand). */ - const char *drawstr_submenu; - int icon; - int state; - - struct MenuSearch_Parent *menu_parent; - MenuType *mt; - - enum { - MENU_SEARCH_TYPE_OP = 1, - MENU_SEARCH_TYPE_RNA = 2, - } type; - - union { - /* Operator menu item. */ - struct { - wmOperatorType *type; - PointerRNA *opptr; - short opcontext; - bContextStore *context; - } op; - - /* Property (only for check-boxe/boolean). */ - struct { - PointerRNA ptr; - PropertyRNA *prop; - int index; - /** Only for enum buttons. */ - int enum_value; - } rna; - }; -}; - -struct MenuSearch_Data { - /** MenuSearch_Item */ - ListBase items; - /** Use for all small allocations. */ - MemArena *memarena; -}; - -static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v) -{ - const struct MenuSearch_Item *menu_item_a = menu_item_a_v; - const struct MenuSearch_Item *menu_item_b = menu_item_b_v; - return strcmp(menu_item_a->drawwstr_full, menu_item_b->drawwstr_full); -} - -static const char *strdup_memarena(MemArena *memarena, const char *str) -{ - const uint str_size = strlen(str) + 1; - char *str_dst = BLI_memarena_alloc(memarena, str_size); - memcpy(str_dst, str, str_size); - return str_dst; -} - -static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str) -{ - const uint str_size = BLI_dynstr_get_len(dyn_str) + 1; - char *str_dst = BLI_memarena_alloc(memarena, str_size); - BLI_dynstr_get_cstring_ex(dyn_str, str_dst); - return str_dst; -} - -static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *data, - MemArena *memarena, - struct MenuType *mt, - const char *drawstr_submenu, - uiBut *but) -{ - struct MenuSearch_Item *item = NULL; - if (but->optype != NULL) { - item = BLI_memarena_calloc(memarena, sizeof(*item)); - item->type = MENU_SEARCH_TYPE_OP; - - item->op.type = but->optype; - item->op.opcontext = but->opcontext; - item->op.context = but->context; - item->op.opptr = but->opptr; - but->opptr = NULL; - } - else if (but->rnaprop != NULL) { - const int prop_type = RNA_property_type(but->rnaprop); - if (!ELEM(prop_type, PROP_BOOLEAN, PROP_ENUM)) { - /* Note that these buttons are not prevented, - * but aren't typically used in menus. */ - printf("Button '%s' in menu '%s' is a menu item with unsupported RNA type %d\n", - but->drawstr, - mt->idname, - prop_type); - } - else { - item = BLI_memarena_calloc(memarena, sizeof(*item)); - item->type = MENU_SEARCH_TYPE_RNA; - - item->rna.ptr = but->rnapoin; - item->rna.prop = but->rnaprop; - item->rna.index = but->rnaindex; - - if (prop_type == PROP_ENUM) { - item->rna.enum_value = (int)but->hardmax; - } - } - } - - if (item != NULL) { - /* Handle shared settings. */ - item->drawstr = strdup_memarena(memarena, but->drawstr); - item->icon = ui_but_icon(but); - item->state = (but->flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT)); - item->mt = mt; - item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL; - BLI_addtail(&data->items, item); - return true; - } - - return false; -} - -/** - * Populate \a menu_stack with menus from inspecting active key-maps for this context. - */ -static void menu_types_add_from_keymap_items(bContext *C, - wmWindow *win, - ScrArea *area, - ARegion *region, - LinkNode **menuid_stack_p, - GHash *menu_to_kmi, - GSet *menu_tagged) -{ - wmWindowManager *wm = CTX_wm_manager(C); - ListBase *handlers[] = { - region ? ®ion->handlers : NULL, - area ? &area->handlers : NULL, - &win->handlers, - }; - - for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) { - if (handlers[handler_index] == NULL) { - continue; - } - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers[handler_index]) { - /* During this loop, ui handlers for nested menus can tag multiple handlers free. */ - if (handler_base->flag & WM_HANDLER_DO_FREE) { - continue; - } - if (handler_base->type != WM_HANDLER_TYPE_KEYMAP) { - continue; - } - - else if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - if (keymap && WM_keymap_poll(C, keymap)) { - LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { - if (kmi->flag & KMI_INACTIVE) { - continue; - } - if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) { - char menu_idname[MAX_NAME]; - RNA_string_get(kmi->ptr, "name", menu_idname); - MenuType *mt = WM_menutype_find(menu_idname, false); - - if (mt && BLI_gset_add(menu_tagged, mt)) { - /* Unlikely, but possible this will be included twice. */ - BLI_linklist_prepend(menuid_stack_p, mt); - - void **kmi_p; - if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) { - *kmi_p = kmi; - } - } - } - } - } - } - } - } -} - -/** - * Create #MenuSearch_Data by inspecting the current context, this uses two methods: - * - * - Look-up pre-defined editor-menus. - * - Look-up key-map items which call menus. - */ -static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, - wmWindow *win, - ScrArea *area, - ARegion *region) -{ - MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - /** Map (#MenuType to #MenuSearch_Parent) */ - GHash *menu_parent_map = BLI_ghash_ptr_new(__func__); - GHash *menu_display_name_map = BLI_ghash_ptr_new(__func__); - const uiStyle *style = UI_style_get_dpi(); - - /* Convert into non-ui structure. */ - struct MenuSearch_Data *data = MEM_callocN(sizeof(*data), __func__); - - DynStr *dyn_str = BLI_dynstr_new_memarena(); - - /* Use a stack of menus to handle and discover new menus in passes. */ - LinkNode *menu_stack = NULL; - - /* Tag menu types not to add, either because they have already been added - * or they have been blacklisted. - * Set of #MenuType. */ - GSet *menu_tagged = BLI_gset_ptr_new(__func__); - /** Map (#MenuType -> #wmKeyMapItem). */ - GHash *menu_to_kmi = BLI_ghash_ptr_new(__func__); - - /* Blacklist menus we don't want to show. */ - { - const char *idname_array[] = { - /* While we could include this, it's just showing filenames to load. */ - "TOPBAR_MT_file_open_recent", - }; - for (int i = 0; i < ARRAY_SIZE(idname_array); i++) { - MenuType *mt = WM_menutype_find(idname_array[i], false); - if (mt != NULL) { - BLI_gset_add(menu_tagged, mt); - } - } - } - - /* Populate menus from the editors, - * note that we could create a fake header, draw the header and extract the menus - * from the buttons, however this is quite involved and can be avoided as by convention - * each space-type has a single root-menu that headers use. */ - { - const char *idname_array[] = { - "TOPBAR_MT_editor_menus", - /* Optional second menu for the space-type. */ - NULL, - }; - int idname_array_len = 1; - -#define SPACE_MENU_MAP(space_type, menu_id) \ - case space_type: \ - idname_array[idname_array_len++] = menu_id; \ - break -#define SPACE_MENU_NOP(space_type) \ - case space_type: \ - break - - if (area != NULL) { - switch (area->spacetype) { - SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus"); - SPACE_MENU_NOP(SPACE_PROPERTIES); - SPACE_MENU_MAP(SPACE_FILE, "FILE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_ACTION, "DOPESHEET_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_CLIP, - (((const SpaceClip *)area->spacedata.first)->mode == SC_MODE_TRACKING) ? - "CLIP_MT_tracking_editor_menus" : - "CLIP_MT_masking_editor_menus"); - SPACE_MENU_NOP(SPACE_TOPBAR); - SPACE_MENU_NOP(SPACE_STATUSBAR); - default: - printf("Unknown space type '%d'\n", area->spacetype); - } - } - for (int i = 0; i < idname_array_len; i++) { - MenuType *mt = WM_menutype_find(idname_array[i], false); - if (mt != NULL) { - BLI_linklist_prepend(&menu_stack, mt); - BLI_gset_add(menu_tagged, mt); - } - } - } -#undef SPACE_MENU_MAP -#undef SPACE_MENU_NOP - - bool has_keymap_menu_items = false; - - GHashIterator iter; - - while (menu_stack != NULL) { - MenuType *mt = BLI_linklist_pop(&menu_stack); - if (!WM_menutype_poll(C, mt)) { - continue; - } - - uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); - uiLayout *layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - - UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); - - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); - UI_menutype_draw(C, mt, layout); - - UI_block_end(C, block); - - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - MenuType *mt_from_but = NULL; - /* Support menu titles with dynamic from initial labels - * (used by edit-mesh context menu). */ - if (but->type == UI_BTYPE_LABEL) { - - /* Check if the label is the title. */ - uiBut *but_test = but->prev; - while (but_test && but_test->type == UI_BTYPE_SEPR) { - but_test = but_test->prev; - } - - if (but_test == NULL) { - BLI_ghash_insert( - menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr)); - } - } - else if (menu_items_from_ui_create_item_from_button(data, memarena, mt, NULL, but)) { - /* pass */ - } - else if ((mt_from_but = UI_but_menutype_get(but))) { - - if (BLI_gset_add(menu_tagged, mt_from_but)) { - BLI_linklist_prepend(&menu_stack, mt_from_but); - } - - if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) { - struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena, - sizeof(*menu_parent)); - /* Use brackets for menu key shortcuts, - * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)". - * This is needed so we don't right align sub-menu contents - * we only want to do that for the last menu item, not the path that leads to it. - */ - const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ? - strrchr(but->drawstr, UI_SEP_CHAR) : - NULL; - bool drawstr_is_empty = false; - if (drawstr_sep != NULL) { - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); - /* Detect empty string, fallback to menu name. */ - const char *drawstr = but->drawstr; - int drawstr_len = drawstr_sep - but->drawstr; - if (UNLIKELY(drawstr_len == 0)) { - drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); - drawstr_len = strlen(drawstr); - if (drawstr[0] == '\0') { - drawstr_is_empty = true; - } - } - BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len); - BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1); - menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str); - BLI_dynstr_clear(dyn_str); - } - else { - const char *drawstr = but->drawstr; - if (UNLIKELY(drawstr[0] == '\0')) { - drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); - if (drawstr[0] == '\0') { - drawstr_is_empty = true; - } - } - menu_parent->drawstr = strdup_memarena(memarena, drawstr); - } - menu_parent->parent_mt = mt; - BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent); - - if (drawstr_is_empty) { - printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname); - } - } - } - else if (but->menu_create_func != NULL) { - /* A non 'MenuType' menu button. */ - - /* Only expand one level deep, this is mainly for expanding operator menus. */ - const char *drawstr_submenu = but->drawstr; - - /* +1 to avoid overlap with the current 'block'. */ - uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS); - uiLayout *sub_layout = UI_block_layout( - sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - - UI_block_flag_enable(sub_block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); - - uiLayoutSetOperatorContext(sub_layout, WM_OP_INVOKE_REGION_WIN); - - but->menu_create_func(C, sub_layout, but->poin); - - UI_block_end(C, sub_block); - - LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) { - menu_items_from_ui_create_item_from_button(data, memarena, mt, drawstr_submenu, sub_but); - } - - if (region) { - BLI_remlink(®ion->uiblocks, sub_block); - } - UI_block_free(NULL, sub_block); - } - } - if (region) { - BLI_remlink(®ion->uiblocks, block); - } - UI_block_free(NULL, block); - - /* Add key-map items as a second pass, - * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */ - if ((menu_stack == NULL) && (has_keymap_menu_items == false)) { - has_keymap_menu_items = true; - menu_types_add_from_keymap_items( - C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged); - } - } - - LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { - item->menu_parent = BLI_ghash_lookup(menu_parent_map, item->mt); - } - - GHASH_ITER (iter, menu_parent_map) { - struct MenuSearch_Parent *menu_parent = BLI_ghashIterator_getValue(&iter); - menu_parent->parent = BLI_ghash_lookup(menu_parent_map, menu_parent->parent_mt); - } - - /* NOTE: currently this builds the full path for each menu item, - * that could be moved into the parent menu. */ - - /* Set names as full paths. */ - LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { - if (item->menu_parent != NULL) { - struct MenuSearch_Parent *menu_parent = item->menu_parent; - menu_parent->temp_child = NULL; - while (menu_parent && menu_parent->parent) { - menu_parent->parent->temp_child = menu_parent; - menu_parent = menu_parent->parent; - } - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); - while (menu_parent) { - BLI_dynstr_append(dyn_str, menu_parent->drawstr); - BLI_dynstr_append(dyn_str, " " MENU_SEP " "); - menu_parent = menu_parent->temp_child; - } - } - else { - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); - const char *drawstr = BLI_ghash_lookup(menu_display_name_map, item->mt); - if (drawstr == NULL) { - drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label); - } - BLI_dynstr_append(dyn_str, drawstr); - - wmKeyMapItem *kmi = BLI_ghash_lookup(menu_to_kmi, item->mt); - if (kmi != NULL) { - char kmi_str[128]; - WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); - BLI_dynstr_appendf(dyn_str, " (%s)", kmi_str); - } - - BLI_dynstr_append(dyn_str, " " MENU_SEP " "); - } - - /* Optional nested menu. */ - if (item->drawstr_submenu != NULL) { - BLI_dynstr_append(dyn_str, item->drawstr_submenu); - BLI_dynstr_append(dyn_str, " " MENU_SEP " "); - } - - BLI_dynstr_append(dyn_str, item->drawstr); - - item->drawwstr_full = strdup_memarena_from_dynstr(memarena, dyn_str); - BLI_dynstr_clear(dyn_str); - } - BLI_dynstr_free(dyn_str); - - /* Finally sort menu items. - * - * 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); - BLI_ghash_free(menu_display_name_map, NULL, NULL); - - BLI_ghash_free(menu_to_kmi, NULL, NULL); - - BLI_gset_free(menu_tagged, NULL); - - data->memarena = memarena; - - return data; -} - -static void menu_items_from_ui_destroy(void *data_v) -{ - struct MenuSearch_Data *data = data_v; - LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { - switch (item->type) { - case MENU_SEARCH_TYPE_OP: { - if (item->op.opptr != NULL) { - WM_operator_properties_free(item->op.opptr); - MEM_freeN(item->op.opptr); - } - } - case MENU_SEARCH_TYPE_RNA: { - break; - } - } - } - - BLI_memarena_free(data->memarena); - - MEM_freeN(data); -} - -static void menu_call_fn(bContext *C, void *UNUSED(arg1), void *arg2) -{ - struct MenuSearch_Item *item = arg2; - if (item == NULL) { - return; - } - if (item->state & UI_BUT_DISABLED) { - return; - } - - switch (item->type) { - case MENU_SEARCH_TYPE_OP: { - CTX_store_set(C, item->op.context); - WM_operator_name_call_ptr(C, item->op.type, item->op.opcontext, item->op.opptr); - CTX_store_set(C, NULL); - break; - } - case MENU_SEARCH_TYPE_RNA: { - PointerRNA *ptr = &item->rna.ptr; - PropertyRNA *prop = item->rna.prop; - int index = item->rna.index; - const int prop_type = RNA_property_type(prop); - bool changed = false; - - if (prop_type == PROP_BOOLEAN) { - const bool is_array = RNA_property_array_check(prop); - if (is_array) { - const bool value = RNA_property_boolean_get_index(ptr, prop, index); - RNA_property_boolean_set_index(ptr, prop, index, !value); - } - else { - const bool value = RNA_property_boolean_get(ptr, prop); - RNA_property_boolean_set(ptr, prop, !value); - } - changed = true; - } - else if (prop_type == PROP_ENUM) { - RNA_property_enum_set(ptr, prop, item->rna.enum_value); - changed = true; - } - - if (changed) { - RNA_property_update(C, ptr, prop); - } - break; - } - } -} - -static void menu_search_cb(const bContext *UNUSED(C), - void *arg, - const char *str, - uiSearchItems *items) -{ - struct MenuSearch_Data *data = arg; - const size_t str_len = strlen(str); - const int words_max = (str_len / 2) + 1; - int(*words)[2] = BLI_array_alloca(words, words_max); - - const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); - - for (struct MenuSearch_Item *item = data->items.first; item; item = item->next) { - int index; - - /* match name against all search words */ - for (index = 0; index < words_len; index++) { - if (!has_word_prefix(item->drawwstr_full, str + words[index][0], words[index][1])) { - break; - } - } - - if (index == words_len) { - if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state)) { - break; - } - } - } -} - -void UI_but_func_menu_search(uiBut *but) -{ - bContext *C = but->block->evil_C; - wmWindow *win = CTX_wm_window(C); - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - struct MenuSearch_Data *data = menu_items_from_ui_create(C, win, area, region); - UI_but_func_search_set(but, - ui_searchbox_create_menu, - menu_search_cb, - data, - menu_items_from_ui_destroy, - menu_call_fn, - MENU_SEP, - NULL); -} - -void uiTemplateMenuSearch(uiLayout *layout) -{ - uiBlock *block; - uiBut *but; - static char search[256] = ""; - - block = uiLayoutGetBlock(layout); - UI_block_layout_set_current(block, layout); - - but = uiDefSearchBut( - block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); - UI_but_func_menu_search(but); -} - -#undef MENU_SEP - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Operator Redo Properties Template - * \{ */ - -#ifdef USE_OP_RESET_BUT -static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), - void *op_pt, - void *UNUSED(arg_dummy2)) -{ - WM_operator_properties_reset((wmOperator *)op_pt); -} -#endif - -struct uiTemplateOperatorPropertyPollParam { - const bContext *C; - wmOperator *op; - short flag; -}; - -static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr), - struct PropertyRNA *prop, - void *user_data) -{ - struct uiTemplateOperatorPropertyPollParam *params = user_data; - if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) && - (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) { - return false; - } - return params->op->type->poll_property(params->C, params->op, prop); -} - -/** - * Draw Operator property buttons for redoing execution with different settings. - * This function does not initialize the layout, - * functions can be called on the layout before and after. - */ -eAutoPropButsReturn uiTemplateOperatorPropertyButs(const bContext *C, - uiLayout *layout, - wmOperator *op, - const eButLabelAlign label_align, - const short flag) -{ - uiBlock *block = uiLayoutGetBlock(layout); - eAutoPropButsReturn return_info = 0; - - if (!op->properties) { - IDPropertyTemplate val = {0}; - op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - } - - /* poll() on this operator may still fail, - * at the moment there is no nice feedback when this happens just fails silently. */ - if (!WM_operator_repeat_check(C, op)) { - UI_block_lock_set(block, true, "Operator can't' redo"); - return return_info; - } - else { - /* useful for macros where only one of the steps can't be re-done */ - UI_block_lock_clear(block); - } - - if (flag & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) { - uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE); - } - - /* menu */ - if (op->type->flag & OPTYPE_PRESET) { - /* XXX, no simple way to get WM_MT_operator_presets.bl_label - * from python! Label remains the same always! */ - PointerRNA op_ptr; - uiLayout *row; - - block->ui_operator = op; - - row = uiLayoutRow(layout, true); - uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE); - - wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); - uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_string_set(&op_ptr, "operator", op->type->idname); - - uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_string_set(&op_ptr, "operator", op->type->idname); - RNA_boolean_set(&op_ptr, "remove_active", true); - } - - if (op->type->ui) { - op->layout = layout; - op->type->ui((bContext *)C, op); - op->layout = NULL; - - /* UI_LAYOUT_OP_SHOW_EMPTY ignored. return_info is ignored too. We could - * allow ot.ui callback to return this, but not needed right now. */ - } - else { - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - struct uiTemplateOperatorPropertyPollParam user_data = { - .C = C, - .op = op, - .flag = flag, - }; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - - /* main draw call */ - return_info = uiDefAutoButsRNA( - layout, - &ptr, - op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL, - op->type->poll_property ? &user_data : NULL, - op->type->prop, - label_align, - (flag & UI_TEMPLATE_OP_PROPS_COMPACT)); - - if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { - uiItemL(layout, IFACE_("No Properties"), ICON_NONE); - } - } - -#ifdef USE_OP_RESET_BUT - /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled - * but this is not so important if this button is drawn in those cases - * (which isn't all that likely anyway) - campbell */ - if (op->properties->len) { - uiBut *but; - uiLayout *col; /* needed to avoid alignment errors with previous buttons */ - - col = uiLayoutColumn(layout, false); - block = uiLayoutGetBlock(col); - but = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_FILE_REFRESH, - IFACE_("Reset"), - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Reset operator defaults")); - UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); - } -#endif - - /* set various special settings for buttons */ - - /* Only do this if we're not refreshing an existing UI. */ - if (block->oldblock == NULL) { - const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; - uiBut *but; - - for (but = block->buttons.first; but; but = but->next) { - /* no undo for buttons for operator redo panels */ - UI_but_flag_disable(but, UI_BUT_UNDO); - - /* only for popups, see [#36109] */ - - /* if button is operator's default property, and a text-field, enable focus for it - * - this is used for allowing operators with popups to rename stuff with fewer clicks - */ - if (is_popup) { - if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { - UI_but_focus_on_enter_event(CTX_wm_window(C), but); - } - } - } - } - - return return_info; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Running Jobs Template * \{ */ diff --git a/source/blender/editors/interface/interface_undo.c b/source/blender/editors/interface/interface_undo.c new file mode 100644 index 00000000000..016bc4159db --- /dev/null +++ b/source/blender/editors/interface/interface_undo.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. + * + * Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edinterface + * + * Undo stack to use for UI widgets that manage their own editing state. + */ + +#include <string.h> + +#include "BLI_listbase.h" + +#include "DNA_listBase.h" + +#include "MEM_guardedalloc.h" + +#include "interface_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Text Field Undo Stack + * \{ */ + +typedef struct uiUndoStack_Text_State { + struct uiUndoStack_Text_State *next, *prev; + int cursor_index; + char text[0]; +} uiUndoStack_Text_State; + +typedef struct uiUndoStack_Text { + ListBase states; + uiUndoStack_Text_State *current; +} uiUndoStack_Text; + +static const char *ui_textedit_undo_impl(uiUndoStack_Text *stack, int *r_cursor_index) +{ + /* Don't undo if no data has been pushed yet. */ + if (stack->current == NULL) { + return NULL; + } + + /* Travel backwards in the stack and copy information to the caller. */ + if (stack->current->prev != NULL) { + stack->current = stack->current->prev; + + *r_cursor_index = stack->current->cursor_index; + return stack->current->text; + } + return NULL; +} + +static const char *ui_textedit_redo_impl(uiUndoStack_Text *stack, int *r_cursor_index) +{ + /* Don't redo if no data has been pushed yet. */ + if (stack->current == NULL) { + return NULL; + } + + /* Only redo if new data has not been entered since the last undo. */ + if (stack->current->next) { + stack->current = stack->current->next; + + *r_cursor_index = stack->current->cursor_index; + return stack->current->text; + } + return NULL; +} + +const char *ui_textedit_undo(uiUndoStack_Text *stack, int direction, int *r_cursor_index) +{ + BLI_assert(ELEM(direction, -1, 1)); + if (direction < 0) { + return ui_textedit_undo_impl(stack, r_cursor_index); + } + else { + return ui_textedit_redo_impl(stack, r_cursor_index); + } +} + +/** + * Push the information in the arguments to a new state in the undo stack. + * + * \note Currently the total length of the undo stack is not limited. + */ +void ui_textedit_undo_push(uiUndoStack_Text *stack, const char *text, int cursor_index) +{ + /* Clear all redo actions from the current state. */ + if (stack->current != NULL) { + while (stack->current->next) { + uiUndoStack_Text_State *state = stack->current->next; + BLI_remlink(&stack->states, state); + MEM_freeN(state); + } + } + + /* Create the new state */ + const int text_size = strlen(text) + 1; + stack->current = MEM_mallocN(sizeof(uiUndoStack_Text_State) + text_size, __func__); + stack->current->cursor_index = cursor_index; + memcpy(stack->current->text, text, text_size); + BLI_addtail(&stack->states, stack->current); +} +/** + * Start the undo stack. + * + * \note The current state should be pushed immediately after calling this. + */ +uiUndoStack_Text *ui_textedit_undo_stack_create(void) +{ + uiUndoStack_Text *stack = MEM_mallocN(sizeof(uiUndoStack_Text), __func__); + stack->current = NULL; + BLI_listbase_clear(&stack->states); + + return stack; +} + +void ui_textedit_undo_stack_destroy(uiUndoStack_Text *stack) +{ + BLI_freelistN(&stack->states); + MEM_freeN(stack); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 781c8f73b0a..4013e962ce5 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -22,6 +22,7 @@ */ #include <assert.h> +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -51,6 +52,22 @@ #include "interface_intern.h" +bool ui_str_has_word_prefix(const char *haystack, const char *needle, size_t needle_len) +{ + const char *match = BLI_strncasestr(haystack, needle, needle_len); + if (match) { + if ((match == haystack) || (*(match - 1) == ' ') || ispunct(*(match - 1))) { + return true; + } + else { + return ui_str_has_word_prefix(match + 1, needle, needle_len); + } + } + else { + return false; + } +} + /*************************** RNA Utilities ******************************/ uiBut *uiDefAutoButR(uiBlock *block, @@ -294,7 +311,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, const bool compact) { eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED; - uiLayout *split, *col; + uiLayout *col; const char *name; RNA_STRUCT_BEGIN (ptr, prop) { @@ -325,19 +342,11 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, } else { BLI_assert(label_align == UI_BUT_LABEL_ALIGN_SPLIT_COLUMN); - split = uiLayoutSplit(layout, 0.5f, false); - - col = uiLayoutColumn(split, false); - uiItemL(col, (is_boolean) ? "" : name, ICON_NONE); - col = uiLayoutColumn(split, false); + col = uiLayoutColumn(layout, true); + /* Let uiItemFullR() create the split layout. */ + uiLayoutSetPropSep(col, true); } - /* May need to add more cases here. - * don't override enum flag names */ - - /* name is shown above, empty name for button below */ - name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : ""; - break; } case UI_BUT_LABEL_ALIGN_NONE: @@ -390,10 +399,10 @@ static int sort_search_items_list(const void *a, const void *b) } } -void ui_rna_collection_search_cb(const struct bContext *C, - void *arg, - const char *str, - uiSearchItems *items) +void ui_rna_collection_search_update_fn(const struct bContext *C, + void *arg, + const char *str, + uiSearchItems *items) { uiRNACollectionSearch *data = arg; int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ed0f50f4113..4706be205e1 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -41,6 +41,8 @@ #include "BLF_api.h" +#include "ED_node.h" + #include "UI_interface.h" #include "UI_interface_icons.h" @@ -2092,15 +2094,18 @@ static void widget_draw_text_ime_underline(const uiFontStyle *fstyle, #endif /* WITH_INPUT_IME */ static bool widget_draw_text_underline_calc_center_x(const char *UNUSED(str), - const size_t str_ofs, - const rcti *glyph_bounds, - const int glyph_advance_x, + const size_t str_step_ofs, + const rcti *glyph_step_bounds, + const int UNUSED(glyph_advance_x), + const rctf *glyph_bounds, + const int glyph_bearing[2], void *user_data) { /* The index of the character to get, set to the x-position. */ int *ul_data = user_data; - if (ul_data[0] == (int)str_ofs) { - ul_data[1] = glyph_bounds->xmin + (glyph_advance_x / 2); + if (ul_data[0] == (int)str_step_ofs) { + ul_data[1] = glyph_step_bounds->xmin + glyph_bearing[0] + + (BLI_rctf_size_x(glyph_bounds) / 2.0f); /* Early exit. */ return false; } @@ -2418,6 +2423,30 @@ static void widget_draw_extra_icons(const uiWidgetColors *wcol, } } +static void widget_draw_node_link_socket(const uiWidgetColors *wcol, + const rcti *rect, + uiBut *but, + float alpha) +{ + /* Node socket pointer can be passed as custom_data, see UI_but_node_link_set(). */ + if (but->custom_data) { + const float scale = 0.9f / but->block->aspect; + + float col[4]; + rgba_uchar_to_float(col, but->col); + col[3] *= alpha; + + GPU_blend(true); + UI_widgetbase_draw_cache_flush(); + GPU_blend(false); + + ED_node_socket_draw(but->custom_data, rect, col, scale); + } + else { + widget_draw_icon(but, ICON_LAYER_USED, alpha, rect, wcol->text); + } +} + /* draws text and icons for buttons */ static void widget_draw_text_icon(const uiFontStyle *fstyle, const uiWidgetColors *wcol, @@ -2427,15 +2456,27 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, const bool show_menu_icon = ui_but_draw_menu_icon(but); float alpha = (float)wcol->text[3] / 255.0f; char password_str[UI_MAX_DRAW_STR]; + bool no_text_padding = but->drawflag & UI_BUT_NO_TEXT_PADDING; ui_but_text_password_hide(password_str, but, false); /* check for button text label */ if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && (but->flag & UI_BUT_NODE_LINK)) { rcti temp = *rect; - temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1; - widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, wcol->text); - rect->xmax = temp.xmin; + const int size = BLI_rcti_size_y(rect) + 1; /* Not the icon size! */ + + if (but->drawflag & UI_BUT_ICON_LEFT) { + temp.xmax = rect->xmin + size; + rect->xmin = temp.xmax; + /* Further padding looks off. */ + no_text_padding = true; + } + else { + temp.xmin = rect->xmax - size; + rect->xmax = temp.xmin; + } + + widget_draw_node_link_socket(wcol, &temp, but, alpha); } /* If there's an icon too (made with uiDefIconTextBut) then draw the icon @@ -2520,28 +2561,30 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, rect->xmin += icon_size + icon_padding; } - int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; - if (but->editstr) { - rect->xmin += text_padding; - } - else if (but->flag & UI_BUT_DRAG_MULTI) { - bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL; - if (text_is_edited) { + if (!no_text_padding) { + int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; + if (but->editstr) { rect->xmin += text_padding; } - } - else if (but->drawflag & UI_BUT_TEXT_LEFT) { - - /* Reduce the left padding for labels without an icon. */ - if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && - !ui_block_is_menu(but->block)) { - text_padding /= 2; + else if (but->flag & UI_BUT_DRAG_MULTI) { + bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL; + if (text_is_edited) { + rect->xmin += text_padding; + } } + else if (but->drawflag & UI_BUT_TEXT_LEFT) { - rect->xmin += text_padding; - } - else if (but->drawflag & UI_BUT_TEXT_RIGHT) { - rect->xmax -= text_padding; + /* Reduce the left padding for labels without an icon. */ + if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && + !ui_block_is_menu(but->block)) { + text_padding /= 2; + } + + rect->xmin += text_padding; + } + else if (but->drawflag & UI_BUT_TEXT_RIGHT) { + rect->xmax -= text_padding; + } } /* Menu contains sub-menu items with triangle icon on their right. Shortcut @@ -4145,10 +4188,10 @@ static void widget_optionbut(uiWidgetColors *wcol, /* smaller */ delta = 1 + BLI_rcti_size_y(&recttemp) / 8; - recttemp.xmin += delta; - recttemp.ymin += delta; - recttemp.xmax -= delta; - recttemp.ymax -= delta; + BLI_rcti_resize( + &recttemp, BLI_rcti_size_x(&recttemp) - delta * 2, BLI_rcti_size_y(&recttemp) - delta * 2); + /* Keep one edge in place. */ + BLI_rcti_translate(&recttemp, text_before_widget ? delta : -delta, 0); rad = wcol->roundness * BLI_rcti_size_y(&recttemp); round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad); @@ -4160,13 +4203,13 @@ static void widget_optionbut(uiWidgetColors *wcol, widgetbase_draw(&wtb, wcol); - /* text space */ - const float offset = BLI_rcti_size_y(rect) * 0.7 + delta; + /* Text space - factor is really just eyeballed. */ + const float offset = delta * 0.9; if (text_before_widget) { - rect->xmax -= offset; + rect->xmax = recttemp.xmin - offset; } else { - rect->xmin += offset; + rect->xmin = recttemp.xmax + offset; } } @@ -4723,9 +4766,14 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu case UI_BTYPE_CHECKBOX_N: if (!(but->flag & UI_HAS_ICON)) { wt = widget_type(UI_WTYPE_CHECKBOX); + if ((but->drawflag & (UI_BUT_TEXT_LEFT | UI_BUT_TEXT_RIGHT)) == 0) { but->drawflag |= UI_BUT_TEXT_LEFT; } + /* widget_optionbut() carefully sets the text rectangle for fine tuned paddings. If the + * text drawing were to add its own padding, DPI and zoom factor would be applied twice + * in the final padding, so it's difficult to control it. */ + but->drawflag |= UI_BUT_NO_TEXT_PADDING; } else { wt = widget_type(UI_WTYPE_TOGGLE); @@ -5279,15 +5327,23 @@ void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(bl wt->draw(&wt->wcol, rect, 0, 0); } -/* helper call to draw a menu item without button */ -/* state: UI_ACTIVE or 0 */ +/** + * Helper call to draw a menu item without a button. + * + * \param state: The state of the button, + * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE. + * \param use_sep: When true, characters after the last #UI_SEP_CHAR are right aligned, + * use for displaying key shortcuts. + * \param r_xmax: The right hand position of the text, this takes into the icon, + * padding and text clipping when there is not enough room to display the full text. + */ void ui_draw_menu_item(const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep, - int *r_name_width) + int *r_xmax) { uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); rcti _rect = *rect; @@ -5350,23 +5406,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, &xofs, &yofs, &info); - if (r_name_width != NULL) { - *r_name_width = xofs + info.width; - } - } - - /* part text right aligned */ - if (use_sep) { - if (cpoin) { - rect->xmax = _rect.xmax - 5; - UI_fontstyle_draw(fstyle, - rect, - cpoin + 1, - wt->wcol.text, - &(struct uiFontStyleDraw_Params){ - .align = UI_STYLE_TEXT_RIGHT, - }); - *cpoin = UI_SEP_CHAR; + if (r_xmax != NULL) { + *r_xmax = xofs + info.width; } } @@ -5386,6 +5427,24 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false); GPU_blend(false); } + + /* part text right aligned */ + if (use_sep) { + if (cpoin) { + /* Set inactive state for grayed out text. */ + wt->state(wt, state | UI_BUT_INACTIVE, 0); + + rect->xmax = _rect.xmax - 5; + UI_fontstyle_draw(fstyle, + rect, + cpoin + 1, + wt->wcol.text, + &(struct uiFontStyleDraw_Params){ + .align = UI_STYLE_TEXT_RIGHT, + }); + *cpoin = UI_SEP_CHAR; + } + } } void ui_draw_preview_item( diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index c07166b9ad2..f8419ba3eba 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -60,7 +60,7 @@ #include "interface_intern.h" -static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers); +static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize); /* -------------------------------------------------------------------- */ /** \name Internal Utilities @@ -134,7 +134,7 @@ void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask) * * \param mask_scroll: Optionally clamp scrollbars by this region. */ -static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scroll) +static void view2d_masks(View2D *v2d, const rcti *mask_scroll) { int scroll; @@ -144,26 +144,24 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr mask_scroll = &v2d->mask; } - if (check_scrollers) { - /* check size if hiding flag is set: */ - if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) { - if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) { - v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR; - } - else { - v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR; - } + /* check size if hiding flag is set: */ + if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) { + if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) { + if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) { + v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR; + } + else { + v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR; } } - if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) { - if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) { - v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR; - } - else { - v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR; - } + } + if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) { + if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) { + if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) { + v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR; + } + else { + v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR; } } } @@ -385,8 +383,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) v2d->winx = winx; v2d->winy = winy; - /* set masks (always do), but leave scroller scheck to totrect_set */ - view2d_masks(v2d, 0, NULL); + view2d_masks(v2d, NULL); if (do_init) { /* Visible by default. */ @@ -394,13 +391,12 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) } /* set 'tot' rect before setting cur? */ - /* XXX confusing stuff here still - - * I made this function not check scroller hide - that happens in totrect_set */ + /* XXX confusing stuff here still */ if (tot_changed) { UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init); } else { - ui_view2d_curRect_validate_resize(v2d, !do_init, 0); + ui_view2d_curRect_validate_resize(v2d, !do_init); } } @@ -409,7 +405,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) * 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot' */ // XXX pre2.5 -> this used to be called test_view2d() -static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers) +static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) { float totwidth, totheight, curwidth, curheight, width, height; float winx, winy; @@ -851,12 +847,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas } /* set masks */ - view2d_masks(v2d, mask_scrollers, NULL); + view2d_masks(v2d, NULL); } void UI_view2d_curRect_validate(View2D *v2d) { - ui_view2d_curRect_validate_resize(v2d, 0, 1); + ui_view2d_curRect_validate_resize(v2d, false); } /* ------------------ */ @@ -982,22 +978,10 @@ void UI_view2d_curRect_reset(View2D *v2d) /* Change the size of the maximum viewable area (i.e. 'tot' rect) */ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize) { - // int scroll = view2d_scroll_mapped(v2d->scroll); - /* don't do anything if either value is 0 */ width = abs(width); height = abs(height); - /* hrumf! */ - /* XXX: there are work arounds for this in the panel and file browse code. */ - /* round to int, because this is called with width + V2D_SCROLL_WIDTH */ - // if (scroll & V2D_SCROLL_HORIZONTAL) { - // width -= (int)V2D_SCROLL_WIDTH; - // } - // if (scroll & V2D_SCROLL_VERTICAL) { - // height -= (int)V2D_SCROLL_HEIGHT; - // } - if (ELEM(0, width, height)) { if (G.debug & G_DEBUG) { printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n", @@ -1047,20 +1031,12 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz } /* make sure that 'cur' rect is in a valid state as a result of these changes */ - ui_view2d_curRect_validate_resize(v2d, resize, 1); + ui_view2d_curRect_validate_resize(v2d, resize); } void UI_view2d_totRect_set(View2D *v2d, int width, int height) { - int scroll = view2d_scroll_mapped(v2d->scroll); - - UI_view2d_totRect_set_resize(v2d, width, height, 0); - - /* solve bad recursion... if scroller state changed, - * mask is different, so you get different rects */ - if (scroll != view2d_scroll_mapped(v2d->scroll)) { - UI_view2d_totRect_set_resize(v2d, width, height, 0); - } + UI_view2d_totRect_set_resize(v2d, width, height, false); } bool UI_view2d_tab_set(View2D *v2d, int tab) @@ -1258,7 +1234,7 @@ void UI_view2d_view_restore(const bContext *C) * \{ */ /* Draw a constant grid in given 2d-region */ -void UI_view2d_constant_grid_draw(View2D *v2d, float step) +void UI_view2d_constant_grid_draw(const View2D *v2d, float step) { float start_x, start_y; int count_x, count_y; @@ -1330,7 +1306,8 @@ void UI_view2d_constant_grid_draw(View2D *v2d, float step) } /* Draw a multi-level grid in given 2d-region */ -void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels) +void UI_view2d_multi_grid_draw( + const View2D *v2d, int colorid, float step, int level_size, int totlevels) { /* Exit if there is nothing to draw */ if (totlevels == 0) { @@ -1448,7 +1425,7 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom) scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers"); /* Always update before drawing (for dynamically sized scrollers). */ - view2d_masks(v2d, false, mask_custom); + view2d_masks(v2d, mask_custom); vert = v2d->vert; hor = v2d->hor; @@ -1801,7 +1778,8 @@ bool UI_view2d_view_to_region_clip( * \param x, y: Coordinates to convert. * \param r_region_x, r_region_y: Resultant coordinates. */ -void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) +void UI_view2d_view_to_region( + const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) { /* step 1: express given coordinates as proportional values */ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); @@ -1817,7 +1795,7 @@ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, in } void UI_view2d_view_to_region_fl( - View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) + const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) { /* express given coordinates as proportional values */ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); @@ -1828,7 +1806,7 @@ void UI_view2d_view_to_region_fl( *r_region_y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask)); } -void UI_view2d_view_to_region_rcti(View2D *v2d, const rctf *rect_src, rcti *rect_dst) +void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst) { const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)}; const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)}; @@ -1849,7 +1827,7 @@ void UI_view2d_view_to_region_rcti(View2D *v2d, const rctf *rect_src, rcti *rect clamp_rctf_to_rcti(rect_dst, &rect_tmp); } -void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4]) +void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4]) { rctf mask; unit_m4(matrix); @@ -1857,7 +1835,7 @@ void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4]) BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &mask, matrix); } -bool UI_view2d_view_to_region_rcti_clip(View2D *v2d, const rctf *rect_src, rcti *rect_dst) +bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst) { const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)}; const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)}; @@ -1983,7 +1961,7 @@ float UI_view2d_scale_get_y(const View2D *v2d) /** * Same as ``UI_view2d_scale_get() - 1.0f / x, y`` */ -void UI_view2d_scale_get_inverse(View2D *v2d, float *r_x, float *r_y) +void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y) { if (r_x) { *r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); @@ -1997,7 +1975,7 @@ void UI_view2d_scale_get_inverse(View2D *v2d, float *r_x, float *r_y) * Simple functions for consistent center offset access. * Used by node editor to shift view center for each individual node tree. */ -void UI_view2d_center_get(struct View2D *v2d, float *r_x, float *r_y) +void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y) { /* get center */ if (r_x) { diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index af17303466b..551f7989d53 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_alembic.h b/source/blender/editors/io/io_alembic.h index 881712fe630..ecd8c1818f8 100644 --- a/source/blender/editors/io/io_alembic.h +++ b/source/blender/editors/io/io_alembic.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index 6c5abf60272..045a293f71b 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_cache.h b/source/blender/editors/io/io_cache.h index 25548dcdbce..c6fc50a236e 100644 --- a/source/blender/editors/io/io_cache.h +++ b/source/blender/editors/io/io_cache.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c index bb527ee6a3f..262b15c63e5 100644 --- a/source/blender/editors/io/io_usd.c +++ b/source/blender/editors/io/io_usd.c @@ -10,7 +10,7 @@ * 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, + * 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) 2019 Blender Foundation. diff --git a/source/blender/editors/io/io_usd.h b/source/blender/editors/io/io_usd.h index 4738e1c348d..c794dc744df 100644 --- a/source/blender/editors/io/io_usd.h +++ b/source/blender/editors/io/io_usd.h @@ -10,7 +10,7 @@ * 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, + * 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) 2019 Blender Foundation. diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index a6dece91eb0..c8cddced99c 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -521,8 +521,8 @@ void MASK_OT_select_box(wmOperatorType *ot) * \{ */ static bool do_lasso_select_mask(bContext *C, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { ScrArea *area = CTX_wm_area(C); @@ -540,7 +540,7 @@ static bool do_lasso_select_mask(bContext *C, } /* get rectangle from operator */ - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { @@ -573,7 +573,7 @@ static bool do_lasso_select_mask(bContext *C, &screen_co[1]); if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) { + BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) { BKE_mask_point_select_set(point, select); BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select); changed = true; @@ -594,14 +594,14 @@ static bool do_lasso_select_mask(bContext *C, static int clip_lasso_select_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - do_lasso_select_mask(C, mcords, mcords_tot, sel_op); + do_lasso_select_mask(C, mcoords, mcoords_len, sel_op); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 23f622ac359..bf6c5a2f829 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -226,6 +226,7 @@ static bool edbm_extrude_ex(Object *obedit, char htype, const char hflag, const bool use_normal_flip, + const bool use_dissolve_ortho_edges, const bool use_mirror, const bool use_select_history) { @@ -241,6 +242,7 @@ static bool edbm_extrude_ex(Object *obedit, BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); BMO_slot_bool_set(extop.slots_in, "use_normal_flip", use_normal_flip); + BMO_slot_bool_set(extop.slots_in, "use_dissolve_ortho_edges", use_dissolve_ortho_edges); BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history); BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag); @@ -312,7 +314,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) mul_v3_m3v3(offset_local, tmat, offset); for (int a = 0; a < steps; a++) { - edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, true); + edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false, true); BMO_op_callf( em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT); } @@ -359,6 +361,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) { const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip"); + const bool use_dissolve_ortho_edges = RNA_boolean_get(op->ptr, "use_dissolve_ortho_edges"); const char htype = edbm_extrude_htype_from_em_select(em); enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr; bool changed = false; @@ -401,7 +404,14 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) case NONE: return false; case ELEM_FLAG: - changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true); + changed = edbm_extrude_ex(obedit, + em, + htype, + BM_ELEM_SELECT, + use_normal_flip, + use_dissolve_ortho_edges, + true, + true); break; case VERT_ONLY: changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT); @@ -465,6 +475,7 @@ void MESH_OT_extrude_region(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -519,6 +530,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -840,7 +852,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w } } - edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, true, true); + edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, false, true, true); EDBM_op_callf( vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat); EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, ofs); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 37bacb4af55..3861676c2cf 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -372,7 +372,8 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) if (is_interactive) { for (uint base_index = 0; base_index < bases_len; base_index++) { Object *ob_iter = bases[base_index]->object; - if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) { + if (BKE_modifiers_is_deformed_by_lattice(ob_iter) || + BKE_modifiers_is_deformed_by_armature(ob_iter)) { BKE_report( op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display"); break; diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 3a0a028468d..225776a452b 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -224,7 +224,7 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "add_solidify")) { ED_object_modifier_add( op->reports, bmain, scene, new_ob, "mask_extract_solidify", eModifierType_Solidify); - SolidifyModifierData *sfmd = (SolidifyModifierData *)modifiers_findByName( + SolidifyModifierData *sfmd = (SolidifyModifierData *)BKE_modifiers_findny_name( new_ob, "mask_extract_solidify"); if (sfmd) { sfmd->offset = -0.05f; diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index 5106108a16c..365c5b5d264 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -1059,7 +1059,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (type == SIMVERT_VGROUP) { /* We store the names of the vertex groups, so we can select - * vertex groups with the same name in different objects. */ + * vertex groups with the same name in different objects. */ const int dvert_tot = BLI_listbase_count(&ob->defbase); for (int i = 0; i < dvert_tot; i++) { if (dvert_selected & (1 << i)) { diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 48ec41027ff..e4ecfa9c680 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -397,9 +397,7 @@ struct UMArrayData { UndoMesh *um; const UndoMesh *um_ref; /* can be NULL */ }; -static void um_arraystore_compact_cb(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void um_arraystore_compact_cb(TaskPool *__restrict UNUSED(pool), void *taskdata) { struct UMArrayData *um_data = taskdata; um_arraystore_compact_with_info(um_data->um, um_data->um_ref); @@ -541,9 +539,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) # ifdef USE_ARRAY_STORE_THREAD if (um_arraystore.task_pool == NULL) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - um_arraystore.task_pool = BLI_task_pool_create_background( - scheduler, NULL, TASK_PRIORITY_LOW); + um_arraystore.task_pool = BLI_task_pool_create_background(NULL, TASK_PRIORITY_LOW); } struct UMArrayData *um_data = MEM_mallocN(sizeof(*um_data), __func__); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 66b2c66f2aa..c52a5956ac4 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -277,6 +277,18 @@ void ED_operatormacros_mesh(void) RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); RNA_boolean_set(otmacro->ptr, "mirror", false); + ot = WM_operatortype_append_macro( + "MESH_OT_extrude_region_dissolve_move_intersect", + "Extrude, Dissolve, Move and Intersect", + "Extrude, dissolves edges whose faces form a flat surface and intersect new edges", + OPTYPE_UNDO | OPTYPE_REGISTER); + otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region"); + RNA_boolean_set(otmacro->ptr, "use_dissolve_ortho_edges", true); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); + RNA_boolean_set(otmacro->ptr, "mirror", false); + RNA_boolean_set(otmacro->ptr, "use_automerge_and_split", true); + ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move", "Extrude Region and Move", "Extrude region together along the average normal", diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index c2c25e47908..fb273cf49a8 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -17,8 +17,8 @@ set(INC ../include - ../../blenkernel ../../blenfont + ../../blenkernel ../../blenlib ../../blentranslation ../../bmesh @@ -34,6 +34,7 @@ set(INC ../../shader_fx ../../render/extern/include ../../windowmanager + ../../../../intern/clog ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 64abd01983c..4a229ae741f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -64,7 +64,7 @@ #include "BKE_duplilist.h" #include "BKE_effect.h" #include "BKE_font.h" -#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_curve.h" #include "BKE_hair.h" #include "BKE_key.h" #include "BKE_lattice.h" @@ -1357,6 +1357,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) Object *ob = ED_object_add_type( C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits); ob->instance_collection = collection; + ob->empty_drawsize = U.collection_instance_empty_size; ob->transflag |= OB_DUPLICOLLECTION; id_us_plus(&collection->id); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 2cb0229126d..baa24ab2f4e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -156,7 +156,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op) ok = mmd->totlvl > 0; for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) { - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { ok = false; } } diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index debad321583..46923b593b1 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -895,7 +895,7 @@ static int bake(Render *re, /* for multires bake, use linear UV subdivision to match low res UVs */ if (pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT && !is_selected_to_active) { - mmd_low = (MultiresModifierData *)modifiers_findByType(ob_low, eModifierType_Multires); + mmd_low = (MultiresModifierData *)BKE_modifiers_findby_type(ob_low, eModifierType_Multires); if (mmd_low) { mmd_flags_low = mmd_low->flags; mmd_low->uv_smooth = SUBSURF_UV_SMOOTH_NONE; @@ -945,7 +945,7 @@ static int bake(Render *re, if (md->type == eModifierType_EdgeSplit) { BLI_remlink(&ob_low_eval->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); is_changed = true; } md = md_next; @@ -1096,7 +1096,7 @@ static int bake(Render *re, int mode; BKE_object_eval_reset(ob_low_eval); - md = modifiers_findByType(ob_low_eval, eModifierType_Multires); + md = BKE_modifiers_findby_type(ob_low_eval, eModifierType_Multires); if (md) { mode = md->mode; diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c index 7554c4efeda..b3155ab3ade 100644 --- a/source/blender/editors/object/object_collection.c +++ b/source/blender/editors/object/object_collection.c @@ -483,7 +483,7 @@ static int collection_link_exec(bContext *C, wmOperator *op) /* Adding object to collection which is used as dupli-collection for self is bad idea. * - * It is also bad idea to add object to collection which is in collection which + * It is also bad idea to add object to collection which is in collection which * contains our current object. */ if (BKE_collection_object_cyclic_check(bmain, ob, collection)) { diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 5506895613b..46837e4fdf3 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -100,6 +100,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "CLG_log.h" + /* for menu/popup icons etc etc*/ #include "UI_interface.h" @@ -112,21 +114,17 @@ #include "object_intern.h" // own include +static CLG_LogRef LOG = {"ed.object.edit"}; + /* prototypes */ typedef struct MoveToCollectionData MoveToCollectionData; static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu); static ListBase selected_objects_get(bContext *C); -/* ************* XXX **************** */ -static void error(const char *UNUSED(arg)) -{ -} - -/* port over here */ -static void error_libdata(void) -{ -} +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ Object *ED_object_context(bContext *C) { @@ -147,7 +145,11 @@ Object *ED_object_active_context(bContext *C) return ob; } -/* ********************** object hiding *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Operator + * \{ */ static bool object_hide_poll(bContext *C) { @@ -401,7 +403,11 @@ void OBJECT_OT_hide_collection(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } -/* ******************* toggle editmode operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Edit-Mode Operator + * \{ */ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me) { @@ -441,7 +447,11 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f } if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) { - error("Too many vertices"); + /* This used to be warned int the UI, we could warn again although it's quite rare. */ + CLOG_WARN(&LOG, + "Too many vertices for mesh '%s' (%d)", + me->id.name + 2, + me->edit_mesh->bm->totvert); return false; } @@ -600,7 +610,8 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag } if (BKE_object_obdata_is_libdata(ob)) { - error_libdata(); + /* Ideally the caller should check this. */ + CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2); return false; } @@ -777,7 +788,11 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Pose-Mode Operator + * \{ */ static int posemode_exec(bContext *C, wmOperator *op) { @@ -861,12 +876,16 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* force field toggle operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Force Field Toggle Operator + * \{ */ void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object) { PartDeflect *pd = object->pd; - ModifierData *md = modifiers_findByType(object, eModifierType_Surface); + ModifierData *md = BKE_modifiers_findby_type(object, eModifierType_Surface); /* add/remove modifier as needed */ if (!md) { @@ -924,8 +943,11 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************************** */ -/* Motion Paths */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Calculate Motion Paths Operator + * \{ */ static eAnimvizCalcRange object_path_convert_range(eObjectPathCalcRange range) { @@ -1019,7 +1041,7 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEv } /* show popup dialog to allow editing of range... */ - /* FIXME: hardcoded dimensions here are just arbitrary */ + /* FIXME: hard-coded dimensions here are just arbitrary. */ return WM_operator_props_dialog_popup(C, op, 200); } @@ -1088,7 +1110,11 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot) MAXFRAME / 2.0); } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update Motion Paths Operator + * \{ */ static bool object_update_paths_poll(bContext *C) { @@ -1132,7 +1158,11 @@ void OBJECT_OT_paths_update(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Motion Paths Operator + * \{ */ /* Helper for ED_objects_clear_paths() */ static void object_clear_mpath(Object *ob) @@ -1151,14 +1181,14 @@ static void object_clear_mpath(Object *ob) void ED_objects_clear_paths(bContext *C, bool only_selected) { if (only_selected) { - /* loop over all selected + sedtiable objects in scene */ + /* Loop over all selected + editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { object_clear_mpath(ob); } CTX_DATA_END; } else { - /* loop over all edtiable objects in scene */ + /* Loop over all editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) { object_clear_mpath(ob); } @@ -1210,13 +1240,17 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update Motion Paths Range from Scene Operator + * \{ */ static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - /* loop over all edtiable objects in scene */ + /* Loop over all editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) { /* use Preview Range or Full Frame Range - whichever is in use */ ob->avs.path_sf = PSFRA; @@ -1246,63 +1280,99 @@ void OBJECT_OT_paths_range_update(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** Smooth/Flat *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Shade Smooth/Flat Operator + * \{ */ static int shade_smooth_exec(bContext *C, wmOperator *op) { - ID *data; - Curve *cu; - Nurb *nu; - int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat")); - bool done = false, linked_data = false; + const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth"); + bool changed_multi = false; + bool has_linked_data = false; - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - data = ob->data; + ListBase ctx_objects = {NULL, NULL}; + CollectionPointerLink ctx_ob_single_active = {NULL}; + + /* For modes that only use an active object, don't handle the whole selection. */ + { + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) { + ctx_ob_single_active.ptr.data = obact; + BLI_addtail(&ctx_objects, &ctx_ob_single_active); + } + } + + if (ctx_objects.first != &ctx_ob_single_active) { + CTX_data_selected_editable_objects(C, &ctx_objects); + } + + for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) { + Object *ob = ctx_ob->ptr.data; + ID *data = ob->data; + if (data != NULL) { + data->tag |= LIB_TAG_DOIT; + } + } + + for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) { + /* Always un-tag all object data-blocks irrespective of our ability to operate on them. */ + Object *ob = ctx_ob->ptr.data; + ID *data = ob->data; + if ((data == NULL) || ((data->tag & LIB_TAG_DOIT) == 0)) { + continue; + } + data->tag &= ~LIB_TAG_DOIT; + /* Finished un-tagging, continue with regular logic. */ if (data && ID_IS_LINKED(data)) { - linked_data = true; + has_linked_data = true; continue; } + bool changed = false; if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(ob->data, !clear); - + BKE_mesh_smooth_flag_set(ob->data, use_smooth); BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - - done = true; + changed = true; } else if (ELEM(ob->type, OB_SURF, OB_CURVE)) { - cu = ob->data; + BKE_curve_smooth_flag_set(ob->data, use_smooth); + changed = true; + } - for (nu = cu->nurb.first; nu; nu = nu->next) { - if (!clear) { - nu->flag |= ME_SMOOTH; - } - else { - nu->flag &= ~ME_SMOOTH; - } - } + if (changed) { + changed_multi = true; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - - done = true; } } - CTX_DATA_END; - if (linked_data) { + if (ctx_objects.first != &ctx_ob_single_active) { + BLI_freelistN(&ctx_objects); + } + + if (has_linked_data) { BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data"); } - return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static bool shade_poll(bContext *C) { - return (CTX_data_edit_object(C) == NULL); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + if (obact != NULL) { + /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */ + if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) { + return false; + } + } + return true; } void OBJECT_OT_shade_flat(wmOperatorType *ot) @@ -1335,7 +1405,11 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Mode Set Operator + * \{ */ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(ptr), @@ -1355,7 +1429,8 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C, if (ob) { const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) || (ob->soft != NULL) || - (modifiers_findByType(ob, eModifierType_Cloth) != NULL); + (BKE_modifiers_findby_type(ob, eModifierType_Cloth) != + NULL); while (input->identifier) { if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) || (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) || @@ -1516,6 +1591,12 @@ void OBJECT_OT_mode_set_with_submode(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Link/Move to Collection Operator + * \{ */ + static ListBase selected_objects_get(bContext *C) { ListBase objects = {NULL}; @@ -1856,3 +1937,5 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); ot->prop = prop; } + +/** \} */ diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 5bf5c4bd95a..6d0f53cfa1e 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -65,7 +65,7 @@ GpencilModifierData *ED_object_gpencil_modifier_add( ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type) { GpencilModifierData *new_md = NULL; - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type); if (ob->type != OB_GPENCIL) { BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2); @@ -73,7 +73,7 @@ GpencilModifierData *ED_object_gpencil_modifier_add( } if (mti->flags & eGpencilModifierTypeFlag_Single) { - if (BKE_gpencil_modifiers_findByType(ob, type)) { + if (BKE_gpencil_modifiers_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return NULL; } @@ -214,7 +214,7 @@ int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), static int gpencil_modifier_apply_obdata( ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->isDisabled && mti->isDisabled(md, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); @@ -281,18 +281,18 @@ int ED_object_gpencil_modifier_apply(Main *bmain, int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md) { GpencilModifierData *nmd; - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); GpencilModifierType type = md->type; if (mti->flags & eGpencilModifierTypeFlag_Single) { - if (BKE_gpencil_modifiers_findByType(ob, type)) { + if (BKE_gpencil_modifiers_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return 0; } } nmd = BKE_gpencil_modifier_new(md->type); - BKE_gpencil_modifier_copyData(md, nmd); + BKE_gpencil_modifier_copydata(md, nmd); BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd); BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd); @@ -335,7 +335,7 @@ static const EnumPropertyItem *gpencil_modifier_add_itemf(bContext *C, for (a = 0; rna_enum_object_greasepencil_modifier_type_items[a].identifier; a++) { md_item = &rna_enum_object_greasepencil_modifier_type_items[a]; if (md_item->identifier[0]) { - mti = BKE_gpencil_modifierType_getInfo(md_item->value); + mti = BKE_gpencil_modifier_get_info(md_item->value); if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd) { continue; @@ -455,7 +455,7 @@ static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op, GpencilModifierData *md; RNA_string_get(op->ptr, "modifier", modifier_name); - md = BKE_gpencil_modifiers_findByName(ob, modifier_name); + md = BKE_gpencil_modifiers_findby_name(ob, modifier_name); if (md && type != 0 && md->type != type) { md = NULL; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 4414acff115..9d2e5e74352 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -552,14 +552,14 @@ static int add_hook_object(const bContext *C, } md = obedit->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } - hmd = (HookModifierData *)modifier_new(eModifierType_Hook); + hmd = (HookModifierData *)BKE_modifier_new(eModifierType_Hook); BLI_insertlinkbefore(&obedit->modifiers, md, hmd); BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name + 2); - modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd); + BKE_modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd); hmd->object = ob; hmd->indexar = indexar; @@ -725,7 +725,7 @@ static int object_hook_remove_exec(bContext *C, wmOperator *op) /* remove functionality */ BLI_remlink(&ob->modifiers, (ModifierData *)hmd); - modifier_free((ModifierData *)hmd); + BKE_modifier_free((ModifierData *)hmd); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index d8ba270073e..d7a7b4ca110 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -169,6 +169,8 @@ void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot); void OBJECT_OT_multires_reshape(struct wmOperatorType *ot); void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot); void OBJECT_OT_multires_base_apply(struct wmOperatorType *ot); +void OBJECT_OT_multires_unsubdivide(struct wmOperatorType *ot); +void OBJECT_OT_multires_rebuild_subdiv(struct wmOperatorType *ot); void OBJECT_OT_multires_external_save(struct wmOperatorType *ot); void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot); void OBJECT_OT_correctivesmooth_bind(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index a24f3ba2269..5cb4714dabf 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -135,23 +135,24 @@ static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph, Object *object, ModifierData *md) { - ModifierData *md_eval = (ModifierData *)modifier_get_evaluated(depsgraph, object, md); + ModifierData *md_eval = (ModifierData *)BKE_modifier_get_evaluated(depsgraph, object, md); const int mode = md_eval->mode; md_eval->mode |= eModifierMode_Realtime; object_force_modifier_update_for_bind(depsgraph, object); md_eval->mode = mode; } -/** Add a modifier to given object, including relevant extra processing needed by some physics - * types (particles, simulations...). +/** + * Add a modifier to given object, including relevant extra processing needed by some physics types + * (particles, simulations...). * - * \param scene is only used to set current frame in some cases, and may be NULL. + * \param scene: is only used to set current frame in some cases, and may be NULL. */ ModifierData *ED_object_modifier_add( ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type) { ModifierData *md = NULL, *new_md = NULL; - const ModifierTypeInfo *mti = modifierType_getInfo(type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(type); /* Check compatibility of modifier [T25291, T50373]. */ if (!BKE_object_support_modifier_type_check(ob, type)) { @@ -160,7 +161,7 @@ ModifierData *ED_object_modifier_add( } if (mti->flags & eModifierTypeFlag_Single) { - if (modifiers_findByType(ob, type)) { + if (BKE_modifiers_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return NULL; } @@ -174,12 +175,12 @@ ModifierData *ED_object_modifier_add( } else { /* get new modifier data to add */ - new_md = modifier_new(type); + new_md = BKE_modifier_new(type); if (mti->flags & eModifierTypeFlag_RequiresOriginalData) { md = ob->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } @@ -195,7 +196,7 @@ ModifierData *ED_object_modifier_add( /* make sure modifier data has unique name */ - modifier_unique_name(&ob->modifiers, new_md); + BKE_modifier_unique_name(&ob->modifiers, new_md); /* special cases */ if (type == eModifierType_Softbody) { @@ -382,7 +383,7 @@ static bool object_modifier_remove(Main *bmain, } BLI_remlink(&ob->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); BKE_object_free_derived_caches(ob); return 1; @@ -432,10 +433,10 @@ void ED_object_modifier_clear(Main *bmain, Object *ob) int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md) { if (md->prev) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->type != eModifierTypeType_OnlyDeform) { - const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type); + const ModifierTypeInfo *nmti = BKE_modifier_get_info(md->prev->type); if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) { BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data"); @@ -453,10 +454,10 @@ int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md) { if (md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->flags & eModifierTypeFlag_RequiresOriginalData) { - const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type); + const ModifierTypeInfo *nmti = BKE_modifier_get_info(md->next->type); if (nmti->type != eModifierTypeType_OnlyDeform) { BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier"); @@ -619,7 +620,7 @@ static int modifier_apply_shape(Main *bmain, Object *ob, ModifierData *md_eval) { - const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type); if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); @@ -643,7 +644,7 @@ static int modifier_apply_shape(Main *bmain, Key *key = me->key; KeyBlock *kb; - if (!modifier_isSameTopology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) { + if (!BKE_modifier_is_same_topology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) { BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); return 0; } @@ -679,7 +680,7 @@ static int modifier_apply_shape(Main *bmain, static int modifier_apply_obdata( ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md_eval) { - const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type); if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); @@ -790,7 +791,7 @@ bool ED_object_modifier_apply(Main *bmain, return false; } else if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) && - (modifier_isSameTopology(md) == false)) { + (BKE_modifier_is_same_topology(md) == false)) { BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); @@ -804,7 +805,7 @@ bool ED_object_modifier_apply(Main *bmain, /* Get evaluated modifier, so object links pointer to evaluated data, * but still use original object it is applied to the original mesh. */ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md; + ModifierData *md_eval = (ob_eval) ? BKE_modifiers_findny_name(ob_eval, md->name) : md; /* allow apply of a not-realtime modifier, by first re-enabling realtime. */ prev_mode = md_eval->mode; @@ -825,7 +826,7 @@ bool ED_object_modifier_apply(Main *bmain, md_eval->mode = prev_mode; BLI_remlink(&ob->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); BKE_object_free_derived_caches(ob); @@ -836,10 +837,10 @@ int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierDat { ModifierData *nmd; - nmd = modifier_new(md->type); - modifier_copyData(md, nmd); + nmd = BKE_modifier_new(md->type); + BKE_modifier_copydata(md, nmd); BLI_insertlinkafter(&ob->modifiers, md, nmd); - modifier_unique_name(&ob->modifiers, nmd); + BKE_modifier_unique_name(&ob->modifiers, nmd); return 1; } @@ -885,7 +886,7 @@ static const EnumPropertyItem *modifier_add_itemf(bContext *C, md_item = &rna_enum_object_modifier_type_items[a]; if (md_item->identifier[0]) { - mti = modifierType_getInfo(md_item->value); + mti = BKE_modifier_get_info(md_item->value); if (mti->flags & eModifierTypeFlag_NoUserAdd) { continue; @@ -1019,7 +1020,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type) ModifierData *md; RNA_string_get(op->ptr, "modifier", modifier_name); - md = modifiers_findByName(ob, modifier_name); + md = BKE_modifiers_findny_name(ob, modifier_name); if (md && type != 0 && md->type != type) { md = NULL; @@ -1199,7 +1200,7 @@ static bool modifier_apply_poll(bContext *C) } else if (md != NULL) { if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) && - (modifier_isSameTopology(md) == false)) { + (BKE_modifier_is_same_topology(md) == false)) { CTX_wm_operator_poll_msg_set( C, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); return false; @@ -1432,6 +1433,25 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot) /** \name Multires Subdivide Operator * \{ */ +static EnumPropertyItem prop_multires_subdivide_mode_type[] = { + {MULTIRES_SUBDIVIDE_CATMULL_CLARK, + "CATMULL_CLARK", + 0, + "Catmull-Clark", + "Create a new level using Catmull-Clark subdivisions"}, + {MULTIRES_SUBDIVIDE_SIMPLE, + "SIMPLE", + 0, + "Simple", + "Create a new level using simple subdivisions"}, + {MULTIRES_SUBDIVIDE_LINEAR, + "LINEAR", + 0, + "Linear", + "Create a new level using linear interpolation of the sculpted displacement"}, + {0, NULL, 0, NULL, NULL}, +}; + static int multires_subdivide_exec(bContext *C, wmOperator *op) { Object *object = ED_object_active_context(C); @@ -1442,7 +1462,9 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - multiresModifier_subdivide(object, mmd); + const eMultiresSubdivideModeType subdivide_mode = (eMultiresSubdivideModeType)( + RNA_enum_get(op->ptr, "mode")); + multiresModifier_subdivide(object, mmd, subdivide_mode); ED_object_iter_other( CTX_data_main(C), object, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl); @@ -1481,6 +1503,12 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); + RNA_def_enum(ot->srna, + "mode", + prop_multires_subdivide_mode_type, + MULTIRES_SUBDIVIDE_CATMULL_CLARK, + "Subdivision Mode", + "How the mesh is going to be subdivided to create a new level"); } /** \} */ @@ -1738,6 +1766,119 @@ void OBJECT_OT_multires_base_apply(wmOperatorType *ot) /** \} */ /* ------------------------------------------------------------------- */ +/** \name Multires Unsubdivide + * \{ */ + +static int multires_unsubdivide_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *object = ED_object_active_context(C); + MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get( + op, object, eModifierType_Multires); + + if (!mmd) { + return OPERATOR_CANCELLED; + } + + int new_levels = multiresModifier_rebuild_subdiv(depsgraph, object, mmd, 1, true); + if (new_levels == 0) { + BKE_report(op->reports, RPT_ERROR, "Not valid subdivisions found to rebuild a lower level"); + return OPERATOR_CANCELLED; + } + + DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object); + + return OPERATOR_FINISHED; +} + +static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (edit_modifier_invoke_properties(C, op)) { + return multires_unsubdivide_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_multires_unsubdivide(wmOperatorType *ot) +{ + ot->name = "Unsubdivide"; + ot->description = "Rebuild a lower subdivision level of the current base mesh"; + ot->idname = "OBJECT_OT_multires_unsubdivide"; + + ot->poll = multires_poll; + ot->invoke = multires_unsubdivide_invoke; + ot->exec = multires_unsubdivide_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); +} + +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Rebuild Subdivisions + * \{ */ + +static int multires_rebuild_subdiv_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *object = ED_object_active_context(C); + MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get( + op, object, eModifierType_Multires); + + if (!mmd) { + return OPERATOR_CANCELLED; + } + + int new_levels = multiresModifier_rebuild_subdiv(depsgraph, object, mmd, INT_MAX, false); + if (new_levels == 0) { + BKE_report(op->reports, RPT_ERROR, "Not valid subdivisions found to rebuild lower levels"); + return OPERATOR_CANCELLED; + } + + BKE_reportf(op->reports, RPT_INFO, "%d new levels rebuilt", new_levels); + + DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object); + + return OPERATOR_FINISHED; +} + +static int multires_rebuild_subdiv_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + if (edit_modifier_invoke_properties(C, op)) { + return multires_rebuild_subdiv_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_multires_rebuild_subdiv(wmOperatorType *ot) +{ + ot->name = "Rebuild Lower Subdivisions"; + ot->description = + "Rebuilds all possible subdivisions levels to generate a lower resolution base mesh"; + ot->idname = "OBJECT_OT_multires_rebuild_subdiv"; + + ot->poll = multires_poll; + ot->invoke = multires_rebuild_subdiv_invoke; + ot->exec = multires_rebuild_subdiv_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); +} + +/** \} */ + +/* ------------------------------------------------------------------- */ /** \name Skin Modifier * \{ */ @@ -2071,7 +2212,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) arm_ob = modifier_skin_armature_create(depsgraph, bmain, scene, ob); /* add a modifier to connect the new armature to the mesh */ - arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature); + arm_md = (ArmatureModifierData *)BKE_modifier_new(eModifierType_Armature); if (arm_md) { skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin); BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md); @@ -2135,7 +2276,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, &csmd->modifier, eModifierMode_Realtime)) { BKE_report(op->reports, RPT_ERROR, "Modifier is disabled"); return OPERATOR_CANCELLED; } @@ -2152,7 +2293,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) else { /* Signal to modifier to recalculate. */ CorrectiveSmoothModifierData *csmd_eval = (CorrectiveSmoothModifierData *) - modifier_get_evaluated(depsgraph, ob, &csmd->modifier); + BKE_modifier_get_evaluated(depsgraph, ob, &csmd->modifier); csmd_eval->bind_coords_num = (uint)-1; /* Force modifier to run, it will call binding routine @@ -2231,7 +2372,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) else { /* Force modifier to run, it will call binding routine * (this has to happen outside of depsgraph evaluation). */ - MeshDeformModifierData *mmd_eval = (MeshDeformModifierData *)modifier_get_evaluated( + MeshDeformModifierData *mmd_eval = (MeshDeformModifierData *)BKE_modifier_get_evaluated( depsgraph, ob, &mmd->modifier); mmd_eval->bindfunc = ED_mesh_deform_bind_callback; object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier); @@ -2436,7 +2577,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) } och = BKE_ocean_init_cache(omd->cachepath, - modifier_path_relbase(bmain, ob), + BKE_modifier_path_relbase(bmain, ob), omd->bakestart, omd->bakeend, omd->wave_scale, @@ -2455,7 +2596,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) * No drivers or other modifier parameters. */ /* TODO(sergey): This operates on an original data, so no flush is needed. However, baking * usually should happen on an evaluated objects, so this seems to be deeper issue here. */ - BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false); och->time[i] = omd->time; i++; @@ -2559,8 +2700,8 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) lmd->flag |= MOD_LAPLACIANDEFORM_BIND; } - LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *)modifier_get_evaluated( - depsgraph, ob, &lmd->modifier); + LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *) + BKE_modifier_get_evaluated(depsgraph, ob, &lmd->modifier); lmd_eval->flag = lmd->flag; /* Force modifier to run, it will call binding routine @@ -2638,7 +2779,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) smd->flags |= MOD_SDEF_BIND; } - SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)modifier_get_evaluated( + SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)BKE_modifier_get_evaluated( depsgraph, ob, &smd->modifier); smd_eval->flags = smd->flags; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index fef046169a7..819b6c18a44 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -137,6 +137,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_multires_reshape); WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete); WM_operatortype_append(OBJECT_OT_multires_base_apply); + WM_operatortype_append(OBJECT_OT_multires_unsubdivide); + WM_operatortype_append(OBJECT_OT_multires_rebuild_subdiv); WM_operatortype_append(OBJECT_OT_multires_external_save); WM_operatortype_append(OBJECT_OT_multires_external_pack); WM_operatortype_append(OBJECT_OT_skin_root_mark); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 759af18ed2b..bfceaef4644 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -557,7 +557,7 @@ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par) /* free modifier if match */ if (free) { BLI_remlink(&ob->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); } } } @@ -803,7 +803,7 @@ bool ED_object_parent_set(ReportList *reports, switch (partype) { case PAR_CURVE: /* curve deform */ - if (modifiers_isDeformedByCurve(ob) != par) { + if (BKE_modifiers_is_deformed_by_curve(ob) != par) { md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve); if (md) { ((CurveModifierData *)md)->object = par; @@ -814,7 +814,7 @@ bool ED_object_parent_set(ReportList *reports, } break; case PAR_LATTICE: /* lattice deform */ - if (modifiers_isDeformedByLattice(ob) != par) { + if (BKE_modifiers_is_deformed_by_lattice(ob) != par) { md = ED_object_modifier_add( reports, bmain, scene, ob, NULL, eModifierType_Lattice); if (md) { @@ -823,7 +823,7 @@ bool ED_object_parent_set(ReportList *reports, } break; default: /* armature deform */ - if (modifiers_isDeformedByArmature(ob) != par) { + if (BKE_modifiers_is_deformed_by_armature(ob) != par) { md = ED_object_modifier_add( reports, bmain, scene, ob, NULL, eModifierType_Armature); if (md) { diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 9f9179440a8..22869748b22 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -114,7 +114,7 @@ static bool object_remesh_poll(bContext *C) return false; } - if (modifiers_usesMultires(ob)) { + if (BKE_modifiers_uses_multires(ob)) { CTX_wm_operator_poll_msg_set( C, "The remesher cannot run with a Multires modifier in the modifier stack"); return false; diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index cd71ab674ba..30fcdfc88bc 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -66,7 +66,7 @@ ShaderFxData *ED_object_shaderfx_add( ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type) { ShaderFxData *new_fx = NULL; - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(type); if (ob->type != OB_GPENCIL) { BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2); @@ -74,7 +74,7 @@ ShaderFxData *ED_object_shaderfx_add( } if (fxi->flags & eShaderFxTypeFlag_Single) { - if (BKE_shaderfx_findByType(ob, type)) { + if (BKE_shaderfx_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed"); return NULL; } @@ -236,7 +236,7 @@ static const EnumPropertyItem *shaderfx_add_itemf(bContext *C, for (a = 0; rna_enum_object_shaderfx_type_items[a].identifier; a++) { fx_item = &rna_enum_object_shaderfx_type_items[a]; if (fx_item->identifier[0]) { - mti = BKE_shaderfxType_getInfo(fx_item->value); + mti = BKE_shaderfx_get_info(fx_item->value); if (mti->flags & eShaderFxTypeFlag_NoUserAdd) { continue; @@ -356,7 +356,7 @@ static ShaderFxData *edit_shaderfx_property_get(wmOperator *op, Object *ob, int ShaderFxData *fx; RNA_string_get(op->ptr, "shaderfx", shaderfx_name); - fx = BKE_shaderfx_findByName(ob, shaderfx_name); + fx = BKE_shaderfx_findby_name(ob, shaderfx_name); if (fx && type != 0 && fx->type != type) { fx = NULL; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 62a8b46e904..132b530455e 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1608,6 +1608,7 @@ struct XFormAxisItem { float rot_mat[3][3]; void *obtfm; float xform_dist; + bool is_z_flip; #ifdef USE_RELATIVE_ROTATION /* use when translating multiple */ @@ -1730,11 +1731,16 @@ static void object_apply_location(Object *ob, const float loc[3]) static bool object_orient_to_location(Object *ob, const float rot_orig[3][3], const float axis[3], - const float location[3]) + const float location[3], + const bool z_flip) { float delta[3]; sub_v3_v3v3(delta, ob->obmat[3], location); if (normalize_v3(delta) != 0.0f) { + if (z_flip) { + negate_v3(delta); + } + if (len_squared_v3v3(delta, axis) > FLT_EPSILON) { float delta_rot[3][3]; float final_rot[3][3]; @@ -1841,6 +1847,11 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons for (int i = 0; i < xfd->object_data_len; i++, item++) { item->obtfm = BKE_object_tfm_backup(item->ob); BKE_object_rot_to_mat3(item->ob, item->rot_mat, true); + + /* Detect negative scale matrix. */ + float full_mat3[3][3]; + BKE_object_to_mat3(item->ob, full_mat3); + item->is_z_flip = dot_v3v3(item->rot_mat[2], full_mat3[2]) < 0.0f; } } @@ -1975,7 +1986,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const } object_orient_to_location( - item->ob, item->rot_mat, item->rot_mat[2], location_world); + item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip); DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); @@ -1989,8 +2000,11 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const else { struct XFormAxisItem *item = xfd->object_data; for (int i = 0; i < xfd->object_data_len; i++, item++) { - if (object_orient_to_location( - item->ob, item->rot_mat, item->rot_mat[2], location_world)) { + if (object_orient_to_location(item->ob, + item->rot_mat, + item->rot_mat[2], + location_world, + item->is_z_flip)) { DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 3ec55d42849..fb79cfb910e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3945,7 +3945,7 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) { if (bonebase == NULL) { - Object *armobj = modifiers_isDeformedByArmature(ob); + Object *armobj = BKE_modifiers_is_deformed_by_armature(ob); if (armobj != NULL) { bArmature *armature = armobj->data; bonebase = &armature->bonebase; diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 37845e8d74e..6922a03b12f 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -72,7 +72,7 @@ static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) DynamicPaintSurface *surface; /* Make sure we're dealing with a canvas */ - pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint); + pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(cObject, eModifierType_DynamicPaint); if (!pmd || !pmd->canvas) { return OPERATOR_CANCELLED; } @@ -117,7 +117,7 @@ static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op)) int id = 0; /* Make sure we're dealing with a canvas */ - pmd = (DynamicPaintModifierData *)modifiers_findByType(obj_ctx, eModifierType_DynamicPaint); + pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(obj_ctx, eModifierType_DynamicPaint); if (!pmd || !pmd->canvas) { return OPERATOR_CANCELLED; } @@ -162,7 +162,7 @@ static int type_toggle_exec(bContext *C, wmOperator *op) Object *cObject = ED_object_context(C); Scene *scene = CTX_data_scene(C); - DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType( + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type( cObject, eModifierType_DynamicPaint); int type = RNA_enum_get(op->ptr, "type"); @@ -222,7 +222,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); DynamicPaintSurface *surface; - DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType( + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type( ob, eModifierType_DynamicPaint); int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */ @@ -483,7 +483,7 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op) /* * Get modifier data */ - DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType( + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type( object_eval, eModifierType_DynamicPaint); if (pmd == NULL) { BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found"); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 75ae0299318..6cafc51231c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -849,7 +849,6 @@ static void foreach_mouse_hit_key(PEData *data, ForHitKeyMatFunc func, int selec TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, foreach_mouse_hit_key_iter, &settings); } @@ -1229,7 +1228,6 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, deflect_emitter_iter, &settings); } @@ -1278,7 +1276,6 @@ static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit) TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, apply_lengths_iter, &settings); } @@ -1353,7 +1350,6 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, iterate_lengths_iter, &settings); } @@ -2256,7 +2252,7 @@ bool PE_circle_select(bContext *C, const int sel_op, const int mval[2], float ra /************************ lasso select operator ************************/ -int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const int sel_op) +int PE_lasso_select(bContext *C, const int mcoords[][2], const int mcoords_len, const int sel_op) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Scene *scene = CTX_data_scene(C); @@ -2300,7 +2296,8 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const const bool is_inside = ((ED_view3d_project_int_global(region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) && + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED) && key_test_depth(&data, co, screen_co)); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -2319,7 +2316,8 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const const bool is_inside = ((ED_view3d_project_int_global(region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) && + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED) && key_test_depth(&data, co, screen_co)); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -2833,8 +2831,8 @@ static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem if (pe_x_mirror(ob)) { /* mirror key tags */ ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *)modifier_get_evaluated( - depsgraph, ob, &psmd->modifier); + ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *) + BKE_modifier_get_evaluated(depsgraph, ob, &psmd->modifier); LOOP_POINTS { LOOP_TAGGED_KEYS { @@ -4084,7 +4082,6 @@ typedef struct BrushAddCountIterData { short size; float imat[4][4]; ParticleData *add_pars; - int num_added; } BrushAddCountIterData; typedef struct BrushAddCountIterTLSData { @@ -4113,7 +4110,7 @@ static void brush_add_count_iter(void *__restrict iter_data_v, dmy = size; if (tls->rng == NULL) { tls->rng = BLI_rng_new_srandom(psys->seed + data->mval[0] + data->mval[1] + - tls_v->thread_id); + BLI_task_parallel_thread_id(tls_v)); } /* rejection sampling to get points in circle */ while (dmx * dmx + dmy * dmy > size2) { @@ -4176,12 +4173,19 @@ static void brush_add_count_iter(void *__restrict iter_data_v, } } -static void brush_add_count_iter_finalize(void *__restrict userdata_v, - void *__restrict userdata_chunk_v) +static void brush_add_count_iter_reduce(const void *__restrict UNUSED(userdata), + void *__restrict join_v, + void *__restrict chunk_v) +{ + BrushAddCountIterTLSData *join = (BrushAddCountIterTLSData *)join_v; + BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v; + join->num_added += tls->num_added; +} + +static void brush_add_count_iter_free(const void *__restrict UNUSED(userdata_v), + void *__restrict chunk_v) { - BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v; - BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v; - iter_data->num_added += tls->num_added; + BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v; if (tls->rng != NULL) { BLI_rng_free(tls->rng); } @@ -4245,23 +4249,22 @@ static int brush_add(const bContext *C, PEData *data, short number) iter_data.number = number; iter_data.size = size; iter_data.add_pars = add_pars; - iter_data.num_added = 0; copy_m4_m4(iter_data.imat, imat); BrushAddCountIterTLSData tls = {NULL}; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; settings.userdata_chunk = &tls; settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData); - settings.func_finalize = brush_add_count_iter_finalize; + settings.func_reduce = brush_add_count_iter_reduce; + settings.func_free = brush_add_count_iter_free; BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings); /* Convert add_parse to a dense array, where all new particles are in the * beginning of the array. */ - n = iter_data.num_added; + n = tls.num_added; for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) { if (add_pars[current_iter].num == DMCACHE_NOTFOUND) { continue; @@ -5124,7 +5127,8 @@ void PE_create_particle_edit( int totpoint; if (psmd != NULL) { - psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name); + psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name(ob_eval, + psmd->modifier.name); } /* no psmd->dm happens in case particle system modifier is not enabled */ @@ -5251,8 +5255,8 @@ static bool particle_edit_toggle_poll(bContext *C) return 0; } - return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) || - modifiers_findByType(ob, eModifierType_Softbody)); + return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) || + BKE_modifiers_findby_type(ob, eModifierType_Softbody)); } static void free_all_psys_edit(Object *object) @@ -5297,7 +5301,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) * with possible changes applied when object was outside of the * edit mode. */ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); - edit->psmd_eval = (ParticleSystemModifierData *)modifiers_findByName( + edit->psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name( object_eval, edit->psmd->modifier.name); recalc_emitter_field(depsgraph, ob, edit->psys); } diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index f37a20bf43e..e75169a476b 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1064,7 +1064,7 @@ static void remove_particle_systems_from_object(Object *ob_to) eModifierType_DynamicPaint, eModifierType_Fluid)) { BLI_remlink(&ob_to->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); } } @@ -1138,13 +1138,13 @@ static bool copy_particle_systems_to_object(const bContext *C, psys_unique_name(ob_to, psys, psys->name); /* add a particle system modifier for each system */ - md = modifier_new(eModifierType_ParticleSystem); + md = BKE_modifier_new(eModifierType_ParticleSystem); psmd = (ParticleSystemModifierData *)md; /* push on top of the stack, no use trying to reproduce old stack order */ BLI_addtail(&ob_to->modifiers, md); BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i); - modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); + BKE_modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); psmd->psys = psys; diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index eb808398254..ceaac201da3 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -156,7 +156,7 @@ static bool fluid_initjob( FluidDomainSettings *mds; Object *ob = CTX_data_active_object(C); - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (!mmd) { BLI_strncpy(error_msg, N_("Bake failed: no Fluid modifier found"), error_size); return false; @@ -185,13 +185,13 @@ static bool fluid_validatepaths(FluidJob *job, ReportList *reports) temp_dir[0] = '\0'; bool is_relative = false; - const char *relbase = modifier_path_relbase(job->bmain, job->ob); + const char *relbase = BKE_modifier_path_relbase(job->bmain, job->ob); /* We do not accept empty paths, they can end in random places silently, see T51176. */ if (mds->cache_directory[0] == '\0') { char cache_name[64]; BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name); - modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); + BKE_modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); BKE_reportf(reports, RPT_WARNING, "Fluid: Empty cache path, reset to default '%s'", @@ -209,7 +209,7 @@ static bool fluid_validatepaths(FluidJob *job, ReportList *reports) if (!dir_exists) { char cache_name[64]; BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name); - modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); + BKE_modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); BKE_reportf(reports, RPT_ERROR, @@ -361,7 +361,7 @@ static void fluid_bake_endjob(void *customdata) RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start); } else { - if (mds->error != NULL && mds->error[0] != '\0') { + if (mds->error[0] != '\0') { WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error); } else { /* User canceled the bake */ @@ -376,7 +376,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, FluidDomainSettings *mds = job->mmd->domain; char temp_dir[FILE_MAX]; - const char *relbase = modifier_path_relbase_from_global(job->ob); + const char *relbase = BKE_modifier_path_relbase_from_global(job->ob); job->stop = stop; job->do_update = do_update; @@ -473,7 +473,7 @@ static void fluid_free_endjob(void *customdata) RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start); } else { - if (mds->error != NULL && mds->error[0] != '\0') { + if (mds->error[0] != '\0') { WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error); } else { /* User canceled the free job */ @@ -622,7 +622,7 @@ static int fluid_free_exec(struct bContext *C, struct wmOperator *op) /* * Get modifier data */ - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (!mmd) { BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found"); return OPERATOR_CANCELLED; @@ -684,7 +684,7 @@ static int fluid_pause_exec(struct bContext *C, struct wmOperator *op) /* * Get modifier data */ - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (!mmd) { BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index f35f92feaec..f2e8209b099 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -144,7 +144,6 @@ typedef struct OGLRender { wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/ void **movie_ctx_arr; - TaskScheduler *task_scheduler; TaskPool *task_pool; bool pool_ok; bool is_animation; @@ -630,6 +629,7 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data) case ID_HA: /* Hair */ case ID_PT: /* PointCloud */ case ID_VO: /* Volume */ + case ID_SIM: /* Simulation */ break; /* Blacklist: */ @@ -855,22 +855,16 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) gather_frames_to_render(C, oglrender); } - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - task_scheduler = BLI_task_scheduler_create(1); - oglrender->task_scheduler = task_scheduler; - oglrender->task_pool = BLI_task_pool_create_background( - task_scheduler, oglrender, TASK_PRIORITY_LOW); + oglrender->task_pool = BLI_task_pool_create_background_serial(oglrender, TASK_PRIORITY_LOW); } else { - oglrender->task_scheduler = NULL; - oglrender->task_pool = BLI_task_pool_create(task_scheduler, oglrender, TASK_PRIORITY_LOW); + oglrender->task_pool = BLI_task_pool_create(oglrender, TASK_PRIORITY_LOW); } oglrender->pool_ok = true; BLI_spin_init(&oglrender->reports_lock); } else { - oglrender->task_scheduler = NULL; oglrender->task_pool = NULL; } oglrender->num_scheduled_frames = 0; @@ -909,10 +903,6 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender) } BLI_task_pool_work_and_wait(oglrender->task_pool); BLI_task_pool_free(oglrender->task_pool); - /* Depending on various things we might or might not use global scheduler. */ - if (oglrender->task_scheduler != NULL) { - BLI_task_scheduler_free(oglrender->task_scheduler); - } BLI_spin_end(&oglrender->reports_lock); } BLI_mutex_end(&oglrender->task_mutex); @@ -1032,9 +1022,9 @@ typedef struct WriteTaskData { Scene tmp_scene; } WriteTaskData; -static void write_result_func(TaskPool *__restrict pool, void *task_data_v, int UNUSED(thread_id)) +static void write_result_func(TaskPool *__restrict pool, void *task_data_v) { - OGLRender *oglrender = (OGLRender *)BLI_task_pool_userdata(pool); + OGLRender *oglrender = (OGLRender *)BLI_task_pool_user_data(pool); WriteTaskData *task_data = (WriteTaskData *)task_data_v; Scene *scene = &task_data->tmp_scene; RenderResult *rr = task_data->rr; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 94937ce9db8..8fb96ca0b76 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2517,6 +2517,7 @@ void ED_region_panels_layout_ex(const bContext *C, int margin_x = 0; const bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE; const bool is_context_new = (contextnr != -1) ? UI_view2d_tab_set(v2d, contextnr) : false; + bool update_tot_size = true; /* before setting the view */ if (vertical) { @@ -2534,7 +2535,6 @@ void ED_region_panels_layout_ex(const bContext *C, v2d->scroll |= (V2D_SCROLL_BOTTOM); v2d->scroll &= ~(V2D_SCROLL_RIGHT); } - const int scroll = v2d->scroll; /* collect categories */ if (use_category_tabs) { @@ -2586,6 +2586,11 @@ void ED_region_panels_layout_ex(const bContext *C, } } + if (panel && UI_panel_is_dragging(panel)) { + /* Prevent View2d.tot rectangle size changes while dragging panels. */ + update_tot_size = false; + } + ed_panel_draw(C, area, region, ®ion->panels, pt, panel, w, em, vertical); } @@ -2641,17 +2646,9 @@ void ED_region_panels_layout_ex(const bContext *C, y = -y; } - /* this also changes the 'cur' */ - UI_view2d_totRect_set(v2d, x, y); - - if (scroll != v2d->scroll) { - /* Note: this code scales fine, but because of rounding differences, positions of elements - * flip +1 or -1 pixel compared to redoing the entire layout again. - * Leaving in commented code for future tests */ -#if 0 - UI_panels_scale(region, BLI_rctf_size_x(&v2d->cur)); - break; -#endif + if (update_tot_size) { + /* this also changes the 'cur' */ + UI_view2d_totRect_set(v2d, x, y); } if (use_category_tabs) { diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 83edb2c3aca..00afbf452dd 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -413,8 +413,7 @@ static void region_cursor_set(wmWindow *win, bool swin_changed) { bScreen *screen = WM_window_get_active_screen(win); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region == screen->active_region) { region_cursor_set_ex(win, area, region, swin_changed); @@ -467,8 +466,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) screen_geom_vertices_scale(win, screen); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { /* set spacetype and region callbacks, calls init() */ /* sets subwindows for regions, adds handlers */ ED_area_initialize(wm, win, area); @@ -691,8 +689,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) ARegion *region; ARegion *region_prev = screen->active_region; - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) { if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) { if (ED_area_azones_update(area_iter, xy) == NULL) { @@ -718,8 +715,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) /* Check for redraw headers. */ if (region_prev != screen->active_region) { - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { bool do_draw = false; for (region = area_iter->regionbase.first; region; region = region->next) { diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 31174f88629..5b808206935 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1741,8 +1741,7 @@ static void area_move_apply_do(const bContext *C, /* only redraw if we actually moved a screen vert, for AREAGRID */ if (doredraw) { bool redraw_all = false; - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { if (area->v1->editflag || area->v2->editflag || area->v3->editflag || area->v4->editflag) { if (ED_area_is_global(area)) { /* Snap to minimum or maximum for global areas. */ @@ -1761,8 +1760,7 @@ static void area_move_apply_do(const bContext *C, } } if (redraw_all) { - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { ED_area_tag_redraw(area); } } @@ -3870,7 +3868,6 @@ static int region_quadview_exec(bContext *C, wmOperator *op) rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT; rv3d->viewlock = 0; - rv3d->rflag &= ~RV3D_CLIPPING; /* FIXME: This fixes missing update to workbench TAA. (see T76216) * However, it would be nice if the tagging should be done in a more conventional way. */ @@ -4393,7 +4390,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv wmWindow *window; ScrArea *area; int sync; - float time; + double time; /* sync, don't sync, or follow scene setting */ if (sad->flag & ANIMPLAY_FLAG_SYNC) { @@ -4416,7 +4413,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } else if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false && isfinite(time = BKE_sound_sync_scene(scene_eval))) { - double newfra = (double)time * FPS; + double newfra = time * FPS; /* give some space here to avoid jumps */ if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra) { @@ -4440,10 +4437,29 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } else { if (sync) { - /* note: this is very simplistic, - * its has problem that it may skip too many frames. - * however at least this gives a less jittery playback */ - const int step = max_ii(1, floor((wt->duration - sad->last_duration) * FPS)); + /* Try to keep the playback in realtime by dropping frames. */ + + /* How much time (in frames) has passed since the last frame was drawn? */ + double delta_frames = wt->delta * FPS; + + /* Add the remaining fraction from the last time step. */ + delta_frames += sad->lagging_frame_count; + + if (delta_frames < 1.0) { + /* We can render faster than the scene frame rate. However skipping or delaying frames + * here seems to in practice lead to jittery playback so just step forward a minimum of + * one frame. (Even though this can lead to too fast playback, the jitteryness is more + * annoying) + */ + delta_frames = 1.0f; + sad->lagging_frame_count = 0; + } + else { + /* Extract the delta frame fractions that will be skipped when converting to int. */ + sad->lagging_frame_count = delta_frames - (int)delta_frames; + } + + const int step = delta_frames; /* skip frames */ if (sad->flag & ANIMPLAY_FLAG_REVERSE) { @@ -4464,8 +4480,6 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } } - sad->last_duration = wt->duration; - /* reset 'jumped' flag before checking if we need to jump... */ sad->flag &= ~ANIMPLAY_FLAG_JUMPED; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 536453ad085..191a064a95c 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -10,7 +10,7 @@ * 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, + * 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 by Nicholas Bishop @@ -171,6 +171,8 @@ static void load_tex_task_cb_ex(void *__restrict userdata, bool convert_to_linear = false; struct ColorSpace *colorspace = NULL; + const int thread_id = BLI_task_parallel_thread_id(tls); + if (mtex->tex && mtex->tex->type == TEX_IMAGE && mtex->tex->ima) { ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(mtex->tex->ima, &mtex->tex->iuser, pool); /* For consistency, sampling always returns color in linear space. */ @@ -214,8 +216,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata, if (col) { float rgba[4]; - paint_get_tex_pixel_col( - mtex, x, y, rgba, pool, tls->thread_id, convert_to_linear, colorspace); + paint_get_tex_pixel_col(mtex, x, y, rgba, pool, thread_id, convert_to_linear, colorspace); buffer[index * 4] = rgba[0] * 255; buffer[index * 4 + 1] = rgba[1] * 255; @@ -223,7 +224,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata, buffer[index * 4 + 3] = rgba[3] * 255; } else { - float avg = paint_get_tex_pixel(mtex, x, y, pool, tls->thread_id); + float avg = paint_get_tex_pixel(mtex, x, y, pool, thread_id); avg += br->texture_sample_bias; diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index 69ca86efa9d..e9dcc4a356a 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -10,7 +10,7 @@ * 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, + * 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) 2010 by Nicholas Bishop diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 6af9ec01fc3..3dc6305dcf2 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5168,9 +5168,7 @@ static void copy_original_alpha_channel(ProjPixel *pixel, bool is_floatbuf) } /* Run this for single and multi-threaded painting. */ -static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), - void *ph_v, - int UNUSED(threadid)) +static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v) { /* First unpack args from the struct */ ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps; @@ -5605,7 +5603,6 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po bool touch_any = false; ProjectHandle handles[BLENDER_MAX_THREADS]; - TaskScheduler *scheduler = NULL; TaskPool *task_pool = NULL; int a, i; @@ -5616,8 +5613,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po } if (ps->thread_tot > 1) { - scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create_suspended(scheduler, NULL, TASK_PRIORITY_HIGH); + task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH); } image_pool = BKE_image_pool_new(); @@ -5661,7 +5657,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po BLI_task_pool_free(task_pool); } else { - do_projectpaint_thread(NULL, &handles[0], 0); + do_projectpaint_thread(NULL, &handles[0]); } BKE_image_pool_free(image_pool); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index fb8cc3a639b..c32e496f4f5 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -10,7 +10,7 @@ * 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, + * 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) 2012 by Nicholas Bishop @@ -168,9 +168,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) .value = value, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings); if (multires) { multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED); @@ -343,9 +343,9 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti * .clip_planes_final = clip_planes_final, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings); if (nodes) { MEM_freeN(nodes); @@ -456,10 +456,10 @@ static void mask_gesture_lasso_task_cb(void *__restrict userdata, static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); float clip_planes[4][4], clip_planes_final[4][4]; BoundBox bb; @@ -485,7 +485,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) ob = vc.obact; ED_view3d_ob_project_mat_get(vc.rv3d, ob, data.projviewobjmat); - BLI_lasso_boundbox(&data.rect, mcords, mcords_tot); + BLI_lasso_boundbox(&data.rect, mcoords, mcoords_len); data.width = data.rect.xmax - data.rect.xmin; data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__); @@ -493,8 +493,8 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) data.rect.ymin, data.rect.xmax, data.rect.ymax, - mcords, - mcords_tot, + mcoords, + mcoords_len, mask_lasso_px_cb, &data); @@ -532,9 +532,9 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) data.task_data.mode = mode; data.task_data.value = value; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings); if (nodes) { MEM_freeN(nodes); @@ -551,7 +551,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) SCULPT_undo_push_end(); ED_region_tag_redraw(vc.region); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); MEM_freeN(data.px); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 7887aaaf658..458c24e5194 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -10,7 +10,7 @@ * 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, + * 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 by Nicholas Bishop diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 60b4a2f8e0c..c84a3b9cbfc 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -166,10 +166,11 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread) { - float intensity, rgba[4]; + float intensity; + float rgba_dummy[4]; float co[3] = {u, v, 0.0f}; - externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba_dummy); return intensity; } @@ -184,11 +185,10 @@ void paint_get_tex_pixel_col(const MTex *mtex, struct ColorSpace *colorspace) { float co[3] = {u, v, 0.0f}; - int hasrgb; float intensity; - hasrgb = externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + const bool hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); + if (!hasrgb) { rgba[0] = intensity; rgba[1] = intensity; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index d050a39ce68..66e72145835 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1398,7 +1398,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) */ { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); if (md != NULL) { /* Can be NULL. */ View3D *v3d = CTX_wm_view3d(C); @@ -2183,9 +2183,9 @@ static void calculate_average_weight(SculptThreadedTaskData *data, struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__); data->custom_data = accum; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (data->sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings); uint accum_len = 0; double accum_weight = 0.0; @@ -2231,22 +2231,22 @@ static void wpaint_paint_leaves(bContext *C, data.strength = BKE_brush_weight_get(scene, brush); /* NOTE: current mirroring code cannot be run in parallel */ - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, !(me->editflag & ME_EDIT_MIRROR_X), totnode); switch ((eBrushWeightPaintTool)brush->weightpaint_tool) { case WPAINT_TOOL_AVERAGE: calculate_average_weight(&data, nodes, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); break; case WPAINT_TOOL_SMEAR: - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings); break; case WPAINT_TOOL_BLUR: - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings); break; case WPAINT_TOOL_DRAW: - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); break; } } @@ -3252,9 +3252,9 @@ static void calculate_average_color(SculptThreadedTaskData *data, struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__); data->custom_data = accum; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings); uint accum_len = 0; uint accum_value[3] = {0}; @@ -3298,21 +3298,21 @@ static void vpaint_paint_leaves(bContext *C, .lcol = (uint *)me->mloopcol, .me = me, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) { case VPAINT_TOOL_AVERAGE: calculate_average_color(&data, nodes, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); break; case VPAINT_TOOL_BLUR: - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings); break; case VPAINT_TOOL_SMEAR: - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings); break; case VPAINT_TOOL_DRAW: - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); break; } } 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 103f312975a..08ffd8e620e 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -108,7 +108,7 @@ static bool weight_from_bones_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && modifiers_isDeformedByArmature(ob)); + return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && BKE_modifiers_is_deformed_by_armature(ob)); } static int weight_from_bones_exec(bContext *C, wmOperator *op) @@ -116,7 +116,7 @@ static int weight_from_bones_exec(bContext *C, wmOperator *op) Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - Object *armob = modifiers_isDeformedByArmature(ob); + Object *armob = BKE_modifiers_is_deformed_by_armature(ob); Mesh *me = ob->data; int type = RNA_enum_get(op->ptr, "type"); 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 5a3067ef193..a483f63bc06 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c @@ -82,7 +82,7 @@ bool ED_wpaint_ensure_data(bContext *C, /* this happens on a Bone select, when no vgroup existed yet */ if (ob->actdef <= 0) { Object *modob; - if ((modob = modifiers_isDeformedByArmature(ob))) { + if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) { Bone *actbone = ((bArmature *)modob->data)->act_bone; if (actbone) { bPoseChannel *pchan = BKE_pose_channel_find_name(modob->pose, actbone->name); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 69345b70d1c..045fd54b46a 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 by Nicholas Bishop @@ -806,12 +806,12 @@ int SCULPT_nearest_vertex_get( nvtd.nearest_vertex_index = -1; nvtd.nearest_vertex_distance_squared = FLT_MAX; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = nearest_vertex_get_reduce; settings.userdata_chunk = &nvtd; settings.userdata_chunk_size = sizeof(NearestVertexTLSData); - BKE_pbvh_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings); MEM_SAFE_FREE(nodes); @@ -952,11 +952,11 @@ static bool sculpt_has_active_modifiers(Scene *scene, Object *ob) ModifierData *md; VirtualModifierData virtualModifierData; - md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* Exception for shape keys because we can edit those. */ for (; md; md = md->next) { - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { return true; } } @@ -1283,9 +1283,9 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings); MEM_SAFE_FREE(nodes); } @@ -1909,12 +1909,12 @@ static void calc_area_center( AreaNormalCenterTLSData anctd = {{{0}}}; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { @@ -1968,12 +1968,12 @@ bool SCULPT_pbvh_calc_area_normal(const Brush *brush, AreaNormalCenterTLSData anctd = {{{0}}}; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); /* For area normal. */ for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) { @@ -2009,12 +2009,12 @@ static void calc_area_normal_and_center( AreaNormalCenterTLSData anctd = {{{0}}}; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { @@ -2100,7 +2100,7 @@ static float brush_strength(const Sculpt *sd, return alpha * pressure * overlap * feather * 2.0f; case SCULPT_TOOL_CLAY_STRIPS: /* Clay Strips needs less strength to compensate the curve. */ - final_pressure = pressure * pressure * pressure; + final_pressure = powf(pressure, 1.5f); return alpha * flip * final_pressure * overlap * feather * 0.3f; case SCULPT_TOOL_CLAY_THUMB: final_pressure = pressure * pressure; @@ -2618,22 +2618,17 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * - SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - *vd.mask, - vd.index, - tls->thread_id) * - ss->cache->pressure; + const float fade = + bstrength * + SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * + ss->cache->pressure; float avg[3], val[3]; @@ -2675,10 +2670,10 @@ static void bmesh_topology_rake( .nodes = nodes, .strength = factor, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings); } } @@ -2696,12 +2691,13 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { const float fade = SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); if (bstrength > 0.0f) { (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); @@ -2731,9 +2727,9 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); } static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) @@ -2768,6 +2764,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2781,7 +2778,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -2818,9 +2815,9 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .offset = offset, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); } static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, @@ -2843,6 +2840,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2857,7 +2855,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -2894,9 +2892,9 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to .offset = offset, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings); } /* -------------------------------------------------------------------- */ @@ -2923,6 +2921,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2936,7 +2935,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float current_disp[3]; float current_disp_norm[3]; float final_disp[3]; @@ -3037,6 +3036,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3050,7 +3050,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); if (vd.mvert) { @@ -3079,15 +3079,15 @@ static void do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); if (ss->cache->alt_smooth) { for (int i = 0; i < 4; i++) { - BKE_pbvh_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings); } } else { - BKE_pbvh_parallel_range(0, totnode, &data, do_topology_slide_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_topology_slide_task_cb_ex, &settings); } } @@ -3200,6 +3200,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3213,7 +3214,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float val1[3]; float val2[3]; @@ -3288,9 +3289,9 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .flippedbstrength = flippedbstrength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); } static void do_pinch_brush_task_cb_ex(void *__restrict userdata, @@ -3311,6 +3312,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); float x_object_space[3]; float z_object_space[3]; @@ -3328,7 +3330,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float disp_center[3]; float x_disp[3]; float z_disp[3]; @@ -3401,9 +3403,9 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .stroke_xz = stroke_xz, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); } static void do_grab_brush_task_cb_ex(void *__restrict userdata, @@ -3427,6 +3429,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3441,7 +3444,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -3473,9 +3476,9 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); } static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, @@ -3582,9 +3585,9 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings); } ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3]) @@ -3744,6 +3747,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3756,7 +3760,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -3788,9 +3792,9 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .cono = cono, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); } static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, @@ -3817,6 +3821,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3829,7 +3834,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -3909,9 +3914,9 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); } static void do_thumb_brush_task_cb_ex(void *__restrict userdata, @@ -3935,6 +3940,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3949,7 +3955,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -3981,9 +3987,9 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .cono = cono, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); } static void do_rotate_brush_task_cb_ex(void *__restrict userdata, @@ -4007,6 +4013,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4022,7 +4029,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); sub_v3_v3v3(vec, orig_data.co, ss->cache->location); axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); @@ -4054,9 +4061,9 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .angle = angle, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); } static void do_layer_brush_task_cb_ex(void *__restrict userdata, @@ -4078,6 +4085,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4092,7 +4100,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); const int vi = vd.index; float *disp_factor; @@ -4169,9 +4177,9 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); } static void do_inflate_brush_task_cb_ex(void *__restrict userdata, @@ -4191,6 +4199,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4203,7 +4212,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float val[3]; if (vd.fno) { @@ -4235,9 +4244,9 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); } int SCULPT_plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3]) @@ -4293,6 +4302,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); @@ -4315,7 +4325,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4359,9 +4369,9 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); } /* -------------------------------------------------------------------- */ @@ -4447,6 +4457,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); @@ -4467,7 +4478,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4509,13 +4520,13 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) ClaySampleData csd = {{0}}; - PBVHParallelSettings sample_settings; + TaskParallelSettings sample_settings; BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode); sample_settings.func_reduce = calc_clay_surface_reduce; sample_settings.userdata_chunk = &csd; sample_settings.userdata_chunk_size = sizeof(ClaySampleData); - BKE_pbvh_parallel_range(0, totnode, &sample_data, calc_clay_surface_task_cb, &sample_settings); + BLI_task_parallel_range(0, totnode, &sample_data, calc_clay_surface_task_cb, &sample_settings); float d_offset = (csd.plane_dist[0] + csd.plane_dist[1]); d_offset = min_ff(radius, d_offset); @@ -4540,9 +4551,9 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); } static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, @@ -4566,6 +4577,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, SCULPT_brush_test_init(ss, &test); plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4589,7 +4601,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4611,7 +4623,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t const bool flip = (ss->cache->bstrength < 0.0f); const float radius = flip ? -ss->cache->radius : ss->cache->radius; const float offset = SCULPT_brush_plane_offset_get(sd, ss); - const float displace = radius * (0.25f + offset); + const float displace = radius * (0.18f + offset); /* The sculpt-plane normal (whatever its set to). */ float area_no_sp[3]; @@ -4673,9 +4685,9 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t .mat = mat, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); } static void do_fill_brush_task_cb_ex(void *__restrict userdata, @@ -4697,6 +4709,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); @@ -4720,7 +4733,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4766,9 +4779,9 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); } static void do_scrape_brush_task_cb_ex(void *__restrict userdata, @@ -4790,6 +4803,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) @@ -4812,7 +4826,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4858,9 +4872,9 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); } /* -------------------------------------------------------------------- */ @@ -4888,6 +4902,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); float plane_tilt[4]; float normal_tilt[3]; @@ -4928,7 +4943,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -5030,9 +5045,9 @@ static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to .clay_strength = clay_strength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_clay_thumb_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_clay_thumb_brush_task_cb_ex, &settings); } /** \} */ @@ -5054,6 +5069,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -5066,7 +5082,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -5101,9 +5117,9 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl .offset = offset, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); } void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) @@ -5284,7 +5300,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe /* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the * vertices and uses regular coords undo. */ - /* It also assings the paint_face_set here as it needs to be done regardless of the stroke type + /* It also assigns the paint_face_set here as it needs to be done regardless of the stroke type * and the number of nodes under the brush influence. */ if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS && ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0 && !ss->cache->alt_smooth) { @@ -5310,9 +5326,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); if (sculpt_brush_needs_normal(ss, brush)) { update_sculpt_normal(sd, ob, nodes, totnode); @@ -5566,9 +5582,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); } MEM_SAFE_FREE(nodes); @@ -5654,9 +5670,9 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used) .vertCos = vertCos, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, SCULPT_flush_stroke_deform_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, SCULPT_flush_stroke_deform_task_cb, &settings); if (vertCos) { SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); @@ -6182,7 +6198,7 @@ static float sculpt_brush_dynamic_size_get(Brush *brush, StrokeCache *cache, flo case SCULPT_TOOL_CLAY: return max_ff(initial_size * 0.20f, initial_size * pow3f(cache->pressure)); case SCULPT_TOOL_CLAY_STRIPS: - return max_ff(initial_size * 0.30f, initial_size * pow2f(cache->pressure)); + return max_ff(initial_size * 0.30f, initial_size * powf(cache->pressure, 1.5f)); case SCULPT_TOOL_CLAY_THUMB: { float clay_stabilized_pressure = sculpt_clay_thumb_get_stabilized_pressure(cache); return initial_size * clay_stabilized_pressure; @@ -7523,7 +7539,7 @@ static int ed_object_sculptmode_flush_recalc_flag(Scene *scene, { int flush_recalc = 0; /* Multires in sculpt mode could have different from object mode subdivision level. */ - flush_recalc |= mmd && BKE_multires_sculpt_level_get(mmd) != mmd->lvl; + flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl; /* If object has got active modifiers, it's dm could be different in sculpt mode. */ flush_recalc |= sculpt_has_active_modifiers(scene, ob); return flush_recalc; diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index 3ccf59ba3bb..f0f6478d3a6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index b1cc6d02bbb..62a7f1925ab 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -221,6 +221,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); /* For Pich Perpendicular Deform Type. */ float x_object_space[3]; @@ -269,7 +270,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float brush_disp[3]; float normal[3]; @@ -412,7 +413,7 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, * storing the constraints per node. */ /* Currently all constrains are added to the same global array which can't be accessed from * different threads. */ - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, false, totnode); SculptThreadedTaskData build_constraints_data = { @@ -421,7 +422,7 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, .brush = brush, .nodes = nodes, }; - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings); } @@ -490,9 +491,9 @@ static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **no .cloth_time_step = CLOTH_SIMULATION_TIME_STEP, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &solve_simulation_data, do_cloth_brush_solve_simulation_task_cb_ex, &settings); } @@ -565,9 +566,9 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod } } - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &apply_forces_data, do_cloth_brush_apply_forces_task_cb_ex, &settings); } diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index a99aa3d1bcf..b7d1cd8c005 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c index 0ab3b8cd14e..eefd8529dbf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -384,12 +384,12 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* Exception for shape keys because we can edit those. */ for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 43ff1ad3ef5..f96f08e3244 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -87,6 +87,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -107,7 +108,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); @@ -127,7 +128,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); if (fade > 0.05f) { SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); @@ -160,6 +161,8 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, bstrength *= 2.0f; } + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { @@ -172,7 +175,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); if (vd.mvert) { @@ -199,15 +202,15 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); if (ss->cache->alt_smooth) { for (int i = 0; i < 4; i++) { - BKE_pbvh_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings); } } else { - BKE_pbvh_parallel_range(0, totnode, &data, do_draw_face_sets_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_draw_face_sets_brush_task_cb_ex, &settings); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index 38bbd083994..d2a683461a7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -246,9 +246,9 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) .prev_mask = prev_mask, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) { MEM_freeN(prev_mask); @@ -275,9 +275,9 @@ void SCULPT_mask_filter_smooth_apply( }; for (int i = 0; i < smooth_iterations; i++) { - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); } } @@ -458,17 +458,17 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) .max = -FLT_MAX, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = dirty_mask_compute_range_reduce; settings.userdata_chunk = ⦥ settings.userdata_chunk_size = sizeof(DirtyMaskRangeData); - BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings); data.dirty_mask_min = range.min; data.dirty_mask_max = range.max; - BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings); MEM_SAFE_FREE(nodes); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 94b6e0eb864..7c438e9245b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -112,10 +112,10 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd) .nodes = ss->filter_cache->nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings); } @@ -496,13 +496,13 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * .filter_strength = filter_strength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); if (filter_type == MESH_FILTER_SURFACE_SMOOTH) { - BKE_pbvh_parallel_range(0, + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_surface_smooth_displace_task_cb, diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index bc7a78f491c..9b13f6e6c24 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 by Nicholas Bishop diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c index 34ca92acef9..cbb198e14a3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -288,10 +288,10 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"), }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); ss->filter_cache->mask_update_current_it = mask_expand_update_it; } @@ -458,10 +458,10 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"), }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); const char *status_str = TIP_( "Move the mouse to expand the mask from the active vertex. LMB: confirm mask, ESC/RMB: " diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c index c74a2ba503a..f3327706102 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -79,6 +79,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); /* Apply the brush normal radius to the test before sampling. */ float test_radius = sqrtf(test.radius_squared); @@ -107,7 +108,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); /* Sample the normal and area of the +X and -X axis individually. */ if (local_co[0] > 0.0f) { @@ -163,6 +164,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -208,7 +210,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -301,13 +303,13 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, MultiplaneScrapeSampleData mssd = {{{0}}}; - PBVHParallelSettings sample_settings; + TaskParallelSettings sample_settings; BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode); sample_settings.func_reduce = calc_multiplane_scrape_surface_reduce; sample_settings.userdata_chunk = &mssd; sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings); float sampled_plane_normals[2][3]; @@ -392,9 +394,9 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, normalize_v3(plane_no); plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no); - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings); } void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr, diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index fde4a9d1d23..c7511dfc80f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -263,7 +263,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, }; data.pose_initial_co = pose_target; - PBVHParallelSettings settings; + TaskParallelSettings settings; PoseGrowFactorTLSData gftd; gftd.pos_count = 0; zero_v3(gftd.pos_avg); @@ -279,7 +279,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, zero_v3(gftd.pos_avg); gftd.pos_count = 0; memcpy(data.prev_mask, pose_factor, SCULPT_vertex_count_get(ss) * sizeof(float)); - BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings); if (gftd.pos_count != 0) { mul_v3_fl(gftd.pos_avg, 1.0f / (float)gftd.pos_count); @@ -793,9 +793,9 @@ void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br for (int ik = 0; ik < ss->cache->pose_ik_chain->tot_segments; ik++) { data.pose_factor = ss->cache->pose_ik_chain->segments[ik].weights; for (int i = 0; i < br->pose_smooth_iterations; i++) { - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings); } } @@ -885,9 +885,9 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); } void SCULPT_pose_ik_chain_free(SculptPoseIKChain *ik_chain) diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 3a09d52d418..17451cb40ae 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -245,6 +245,8 @@ static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata, SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { @@ -257,7 +259,7 @@ static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata, vd.fno, smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), vd.index, - tls->thread_id); + thread_id); if (smooth_mask) { float val = SCULPT_neighbor_mask_average(ss, vd.vert_indices[vd.i]) - *vd.mask; val *= fade * bstrength; @@ -301,6 +303,7 @@ static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -313,7 +316,7 @@ static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata, vd.fno, smooth_mask ? 0.0f : *vd.mask, vd.index, - tls->thread_id); + thread_id); if (smooth_mask) { float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; val *= fade * bstrength; @@ -358,6 +361,8 @@ static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { @@ -370,7 +375,7 @@ static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, vd.fno, smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), vd.index, - tls->thread_id); + thread_id); if (smooth_mask) { float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; val *= fade * bstrength; @@ -427,18 +432,18 @@ void SCULPT_smooth(Sculpt *sd, .strength = strength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); switch (type) { case PBVH_GRIDS: - BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); break; case PBVH_FACES: - BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); break; case PBVH_BMESH: - BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); break; } } @@ -512,6 +517,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]); @@ -522,7 +528,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( const float fade = bstrength * SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); float disp[3]; SCULPT_surface_smooth_laplacian_step(ss, @@ -555,6 +561,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -562,7 +569,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( const float fade = bstrength * SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); SCULPT_surface_smooth_displace_step( ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); } @@ -590,12 +597,12 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); for (int i = 0; i < brush->surface_smooth_iterations; i++) { - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &data, SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex, &settings); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &data, SCULPT_do_surface_smooth_brush_displace_task_cb_ex, &settings); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index c7cbb6672a4..2eb1191b950 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -177,10 +177,10 @@ void ED_sculpt_update_modal_transform(struct bContext *C) mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]); } - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings); if (ss->deform_modifiers_active || ss->shapekey_active) { diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 1cb9b57e81d..905d0e0a4bf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 by Nicholas Bishop @@ -415,9 +415,9 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C, BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings); if (nodes) { diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 0a5814be626..a1094dde749 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -10,7 +10,7 @@ * 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, + * 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) Blender Foundation, 2002-2009 diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index a356962946e..b5a0c4a9e22 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -164,13 +164,13 @@ static void actedit_change_action(bContext *C, bAction *act) * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions... * OR * The NLA Editor is active (i.e. Animation Data panel -> new action) - * 2) The associated AnimData block must not be in tweakmode + * 2) The associated AnimData block must not be in tweak-mode. */ static bool action_new_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ + /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, * this operator needs to be run when creating an action from nothing... */ if (ED_operator_action_active(C)) { @@ -300,7 +300,7 @@ void ACTION_OT_new(wmOperatorType *ot) /* Criteria: * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions * 2) There must be an action active - * 3) The associated AnimData block must not be in tweakmode + * 3) The associated AnimData block must not be in tweak-mode */ static bool action_pushdown_poll(bContext *C) { @@ -308,7 +308,7 @@ static bool action_pushdown_poll(bContext *C) SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); AnimData *adt = ED_actedit_animdata_from_context(C); - /* Check for AnimData, Actions, and that tweakmode is off */ + /* Check for AnimData, Actions, and that tweak-mode is off. */ if (adt && saction->action) { /* NOTE: We check this for the AnimData block in question and not the global flag, * as the global flag may be left dirty by some of the browsing ops here. @@ -330,9 +330,8 @@ static int action_pushdown_exec(bContext *C, wmOperator *op) /* Do the deed... */ if (adt) { - /* Perform the pushdown operation - * - This will deal with all the AnimData-side usercounts - */ + /* Perform the push-down operation + * - This will deal with all the AnimData-side user-counts. */ if (action_has_motion(adt->action) == 0) { /* action may not be suitable... */ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); @@ -389,7 +388,7 @@ static int action_stash_exec(bContext *C, wmOperator *op) if (BKE_nla_action_stash(adt)) { /* The stash operation will remove the user already, * so the flushing step later shouldn't double up - * the usercount fixes. Hence, we must unset this ref + * the user-count fixes. Hence, we must unset this ref * first before setting the new action. */ saction->action = NULL; @@ -435,14 +434,14 @@ void ACTION_OT_stash(wmOperatorType *ot) /* Criteria: * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions - * 2) The associated AnimData block must not be in tweakmode + * 2) The associated AnimData block must not be in tweak-mode */ static bool action_stash_create_poll(bContext *C) { if (ED_operator_action_active(C)) { AnimData *adt = ED_actedit_animdata_from_context(C); - /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ + /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, * this operator needs to be run when creating an action from nothing... */ if (adt) { @@ -498,7 +497,7 @@ static int action_stash_create_exec(bContext *C, wmOperator *op) /* The stash operation will remove the user already, * so the flushing step later shouldn't double up - * the usercount fixes. Hence, we must unset this ref + * the user-count fixes. Hence, we must unset this ref * first before setting the new action. */ saction->action = NULL; @@ -728,8 +727,8 @@ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime) static void action_layer_switch_strip( AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip) { - /* Exit tweakmode on old strip - * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it + /* Exit tweak-mode on old strip + * NOTE: We need to manually clear this stuff ourselves, as tweak-mode exit doesn't do it */ BKE_nla_tweakmode_exit(adt); @@ -761,11 +760,11 @@ static void action_layer_switch_strip( adt->flag |= ADT_NLA_SOLO_TRACK; nlt->flag |= NLATRACK_SOLO; - // TODO: Needs restpose flushing (when we get reference track) + // TODO: Needs rest-pose flushing (when we get reference track) } } - /* Enter tweakmode again - hopefully we're now "it" */ + /* Enter tweak-mode again - hopefully we're now "it" */ BKE_nla_tweakmode_enter(adt); BLI_assert(adt->actstrip == strip); } @@ -778,7 +777,7 @@ static bool action_layer_next_poll(bContext *C) if (ED_operator_action_active(C)) { AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { - /* only allow if we're in tweakmode, and there's something above us... */ + /* only allow if we're in tweak-mode, and there's something above us... */ if (adt->flag & ADT_NLA_EDIT_ON) { /* We need to check if there are any tracks above the active one * since the track the action comes from is not stored in AnimData @@ -840,7 +839,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) } else { /* No more actions (strips) - Go back to editing the original active action - * NOTE: This will mean exiting tweakmode... + * NOTE: This will mean exiting tweak-mode... */ BKE_nla_tweakmode_exit(adt); @@ -855,13 +854,12 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) /* turn on NLA muting (to keep same effect) */ adt->flag |= ADT_NLA_EVAL_OFF; - // TODO: Needs restpose flushing (when we get reference track) + // TODO: Needs rest-pose flushing (when we get reference track) } } /* Update the action that this editor now uses - * NOTE: The calls above have already handled the usercount/animdata side of things - */ + * NOTE: The calls above have already handled the user-count/anim-data side of things. */ actedit_change_action(C, adt->action); return OPERATOR_FINISHED; } @@ -960,8 +958,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) } /* Update the action that this editor now uses - * NOTE: The calls above have already handled the usercount/animdata side of things - */ + * NOTE: The calls above have already handled the user-count/animdata side of things. */ actedit_change_action(C, adt->action); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 927e51a3e04..e90122f2585 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -313,8 +313,8 @@ void ACTION_OT_previewrange_set(wmOperatorType *ot) /** * Find the extents of the active channel * - * \param[out] min Bottom y-extent of channel - * \param[out] max Top y-extent of channel + * \param[out] min: Bottom y-extent of channel + * \param[out] max: Top y-extent of channel * \return Success of finding a selected channel */ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, float *max) @@ -448,7 +448,7 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) void ACTION_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "ACTION_OT_view_all"; ot->description = "Reset viewable area to show full keyframe range"; diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 26c29d6cbe7..bbb68f632fb 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -793,8 +793,8 @@ static int actkeys_lassoselect_exec(bContext *C, wmOperator *op) } data_lasso.rectf_view = &rect_fl; - data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot); - if (data_lasso.mcords == NULL) { + data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len); + if (data_lasso.mcoords == NULL) { return OPERATOR_CANCELLED; } @@ -805,13 +805,13 @@ static int actkeys_lassoselect_exec(bContext *C, wmOperator *op) } /* get settings from operator */ - BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot); + BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len); BLI_rctf_rcti_copy(&rect_fl, &rect); /* apply box_select action */ region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso); - MEM_freeN((void *)data_lasso.mcords); + MEM_freeN((void *)data_lasso.mcoords); /* send notifier that keyframe selection has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 587ba5b0b79..7e6088bc3cc 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -1041,7 +1041,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md); return 1; } @@ -1051,7 +1051,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Softbody); CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md); return 1; } @@ -1062,7 +1062,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid); CTX_data_pointer_set(result, &ob->id, &RNA_FluidModifier, md); return 1; } @@ -1072,7 +1072,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Collision); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Collision); CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md); return 1; } @@ -1086,7 +1086,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint); CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md); return 1; } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 00818ac77b5..6b7f86a9143 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -236,10 +236,10 @@ static void buttons_texture_users_from_context(ListBase *users, int a; /* modifiers */ - modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users); + BKE_modifiers_foreach_tex_link(ob, buttons_texture_modifier_foreach, users); /* grease pencil modifiers */ - BKE_gpencil_modifiers_foreachTexLink(ob, buttons_texture_modifier_gpencil_foreach, users); + BKE_gpencil_modifiers_foreach_tex_link(ob, buttons_texture_modifier_gpencil_foreach, users); /* particle systems */ if (psys && !limited_mode) { diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c index cd95a00c62a..c3323491085 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_ops.c +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -204,7 +204,7 @@ static int dopesheet_view_all_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_dopesheet_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->description = "Reset viewable area to show full keyframe range"; ot->idname = "CLIP_OT_dopesheet_view_all"; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a1652ca0e88..fe7ae7096a0 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1651,7 +1651,7 @@ static void draw_tracking_tracks(SpaceClip *sc, pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width; pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy; - BKE_tracking_distort_v2(tracking, pos, npos); + BKE_tracking_distort_v2(tracking, width, height, pos, npos); if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) { vec[0] = (marker->pos[0] + track->offset[0]) * width; @@ -1730,8 +1730,7 @@ static void draw_distortion(SpaceClip *sc, { float x, y; const int n = 10; - int i, j, a; - float pos[2], tpos[2], grid[11][11][2]; + float tpos[2], grid[11][11][2]; MovieTracking *tracking = &clip->tracking; bGPdata *gpd = NULL; float aspy = 1.0f / tracking->camera.pixel_aspect; @@ -1764,7 +1763,7 @@ static void draw_distortion(SpaceClip *sc, float val[4][2], idx[4][2]; float min[2], max[2]; - for (a = 0; a < 4; a++) { + for (int a = 0; a < 4; a++) { if (a < 2) { val[a][a % 2] = FLT_MAX; } @@ -1773,13 +1772,13 @@ static void draw_distortion(SpaceClip *sc, } } - zero_v2(pos); - for (i = 0; i <= n; i++) { - for (j = 0; j <= n; j++) { + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= n; j++) { if (i == 0 || j == 0 || i == n || j == n) { - BKE_tracking_distort_v2(tracking, pos, tpos); + const float pos[2] = {dx * j, dy * i}; + BKE_tracking_distort_v2(tracking, width, height, pos, tpos); - for (a = 0; a < 4; a++) { + for (int a = 0; a < 4; a++) { int ok; if (a < 2) { @@ -1796,59 +1795,49 @@ static void draw_distortion(SpaceClip *sc, } } } - - pos[0] += dx; } - - pos[0] = 0.0f; - pos[1] += dy; } INIT_MINMAX2(min, max); - for (a = 0; a < 4; a++) { - pos[0] = idx[a][0] * dx; - pos[1] = idx[a][1] * dy; + for (int a = 0; a < 4; a++) { + const float pos[2] = {idx[a][0] * dx, idx[a][1] * dy}; - BKE_tracking_undistort_v2(tracking, pos, tpos); + BKE_tracking_undistort_v2(tracking, width, height, pos, tpos); minmax_v2v2_v2(min, max, tpos); } - copy_v2_v2(pos, min); dx = (max[0] - min[0]) / n; dy = (max[1] - min[1]) / n; - for (i = 0; i <= n; i++) { - for (j = 0; j <= n; j++) { - BKE_tracking_distort_v2(tracking, pos, grid[i][j]); + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= n; j++) { + const float pos[2] = {min[0] + dx * j, min[1] + dy * i}; + + BKE_tracking_distort_v2(tracking, width, height, pos, grid[i][j]); grid[i][j][0] /= width; grid[i][j][1] /= height * aspy; - - pos[0] += dx; } - - pos[0] = min[0]; - pos[1] += dy; } immUniformColor3f(1.0f, 0.0f, 0.0f); - for (i = 0; i <= n; i++) { + for (int i = 0; i <= n; i++) { immBegin(GPU_PRIM_LINE_STRIP, n + 1); - for (j = 0; j <= n; j++) { + for (int j = 0; j <= n; j++) { immVertex2fv(position, grid[i][j]); } immEnd(); } - for (j = 0; j <= n; j++) { + for (int j = 0; j <= n; j++) { immBegin(GPU_PRIM_LINE_STRIP, n + 1); - for (i = 0; i <= n; i++) { + for (int i = 0; i <= n; i++) { immVertex2fv(position, grid[i][j]); } @@ -1882,8 +1871,8 @@ static void draw_distortion(SpaceClip *sc, while (stroke) { if (stroke->flag & GP_STROKE_2DSPACE) { if (stroke->totpoints > 1) { - for (i = 0; i < stroke->totpoints - 1; i++) { - float npos[2], dpos[2], len; + for (int i = 0; i < stroke->totpoints - 1; i++) { + float pos[2], npos[2], dpos[2], len; int steps; pos[0] = (stroke->points[i].x + offsx) * width; @@ -1897,8 +1886,8 @@ static void draw_distortion(SpaceClip *sc, /* we want to distort only long straight lines */ if (stroke->totpoints == 2) { - BKE_tracking_undistort_v2(tracking, pos, pos); - BKE_tracking_undistort_v2(tracking, npos, npos); + BKE_tracking_undistort_v2(tracking, width, height, pos, pos); + BKE_tracking_undistort_v2(tracking, width, height, npos, npos); } sub_v2_v2v2(dpos, npos, pos); @@ -1906,8 +1895,8 @@ static void draw_distortion(SpaceClip *sc, immBegin(GPU_PRIM_LINE_STRIP, steps + 1); - for (j = 0; j <= steps; j++) { - BKE_tracking_distort_v2(tracking, pos, tpos); + for (int j = 0; j <= steps; j++) { + BKE_tracking_distort_v2(tracking, width, height, pos, tpos); immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy)); add_v2_v2(pos, dpos); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index cce01947ab7..5be4b2d5df0 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -546,7 +546,7 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[ r_co[0] *= width; r_co[1] *= height * aspy; - BKE_tracking_undistort_v2(&clip->tracking, r_co, r_co); + BKE_tracking_undistort_v2(&clip->tracking, width, height, r_co, r_co); r_co[0] /= width; r_co[1] /= height * aspy; @@ -580,7 +580,7 @@ void ED_clip_point_stable_pos( float aspy = 1.0f / tracking->camera.pixel_aspect; float tmp[2] = {*xr * width, *yr * height * aspy}; - BKE_tracking_distort_v2(tracking, tmp, tmp); + BKE_tracking_distort_v2(tracking, width, height, tmp, tmp); *xr = tmp[0] / width; *yr = tmp[1] / (height * aspy); @@ -885,9 +885,9 @@ static uchar *prefetch_thread_next_frame(PrefetchQueue *queue, return mem; } -static void prefetch_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid)) +static void prefetch_task_func(TaskPool *__restrict pool, void *task_data) { - PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool); + PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_user_data(pool); MovieClip *clip = (MovieClip *)task_data; uchar *mem; size_t size; @@ -942,9 +942,8 @@ static void start_prefetch_threads(MovieClip *clip, float *progress) { PrefetchQueue queue; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; - int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler); + int i, tot_thread = BLI_task_scheduler_num_threads(); /* initialize queue */ BLI_spin_init(&queue.spin); @@ -961,7 +960,7 @@ static void start_prefetch_threads(MovieClip *clip, queue.do_update = do_update; queue.progress = progress; - task_pool = BLI_task_pool_create(task_scheduler, &queue, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&queue, TASK_PRIORITY_LOW); for (i = 0; i < tot_thread; i++) { BLI_task_pool_push(task_pool, prefetch_task_func, clip, false, NULL); } diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index e974480a233..589831b1c45 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -671,7 +671,7 @@ static int view_all_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_graph_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->description = "View all curves in editor"; ot->idname = "CLIP_OT_graph_view_all"; diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 3204374b747..984aa0a63ad 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -784,7 +784,7 @@ void CLIP_OT_view_zoom_in(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom In"; + ot->name = "Zoom In"; ot->idname = "CLIP_OT_view_zoom_in"; ot->description = "Zoom in the view"; @@ -841,7 +841,7 @@ void CLIP_OT_view_zoom_out(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom Out"; + ot->name = "Zoom Out"; ot->idname = "CLIP_OT_view_zoom_out"; ot->description = "Zoom out the view"; @@ -975,7 +975,7 @@ void CLIP_OT_view_all(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "CLIP_OT_view_all"; ot->description = "View whole image with markers"; @@ -1367,10 +1367,10 @@ static uchar *proxy_thread_next_frame(ProxyQueue *queue, return mem; } -static void proxy_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid)) +static void proxy_task_func(TaskPool *__restrict pool, void *task_data) { ProxyThread *data = (ProxyThread *)task_data; - ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool); + ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_user_data(pool); uchar *mem; size_t size; int cfra; @@ -1413,11 +1413,10 @@ static void do_sequence_proxy(void *pjv, ProxyJob *pj = pjv; MovieClip *clip = pj->clip; Scene *scene = pj->scene; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; int sfra = SFRA, efra = EFRA; ProxyThread *handles; - int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler); + int i, tot_thread = BLI_task_scheduler_num_threads(); int width, height; ProxyQueue queue; @@ -1434,7 +1433,7 @@ static void do_sequence_proxy(void *pjv, queue.do_update = do_update; queue.progress = progress; - task_pool = BLI_task_pool_create(task_scheduler, &queue, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&queue, TASK_PRIORITY_LOW); handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles"); for (i = 0; i < tot_thread; i++) { ProxyThread *handle = &handles[i]; diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 4a0df454a78..03f791ad70d 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -166,7 +166,8 @@ static float calculate_reprojection_error_at_marker(MovieClip *clip, reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) * clip_height * aspy; - BKE_tracking_distort_v2(tracking, reprojected_position, reprojected_position); + BKE_tracking_distort_v2( + tracking, clip_width, clip_height, reprojected_position, reprojected_position); marker_position[0] = (marker->pos[0] + track->offset[0]) * clip_width; marker_position[1] = (marker->pos[1] + track->offset[1]) * clip_height * aspy; diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index c2a4ebdfc63..81cc858c69f 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -598,8 +598,8 @@ void CLIP_OT_select_box(wmOperatorType *ot) /********************** lasso select operator *********************/ static int do_lasso_select_marker(bContext *C, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, bool select) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -616,7 +616,7 @@ static int do_lasso_select_marker(bContext *C, int framenr = ED_space_clip_get_clip_frame_number(sc); /* get rectangle from operator */ - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* do actual selection */ track = tracksbase->first; @@ -631,7 +631,8 @@ static int do_lasso_select_marker(bContext *C, ED_clip_point_stable_pos__reverse(sc, region, marker->pos, screen_co); if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { if (select) { BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT); } @@ -659,7 +660,8 @@ static int do_lasso_select_marker(bContext *C, ED_clip_point_stable_pos__reverse(sc, region, plane_marker->corners[i], screen_co); if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { if (select) { plane_track->flag |= SELECT; } @@ -685,10 +687,10 @@ static int do_lasso_select_marker(bContext *C, static int clip_lasso_select_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { 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)) { @@ -696,9 +698,9 @@ static int clip_lasso_select_exec(bContext *C, wmOperator *op) ED_clip_select_all(sc, SEL_DESELECT, NULL); } - do_lasso_select_marker(C, mcords, mcords_tot, select); + do_lasso_select_marker(C, mcoords, mcoords_len, select); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index ac8fa413f07..7f6d0658ec8 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1264,11 +1264,9 @@ static void filelist_intern_free(FileListIntern *filelist_intern) MEM_SAFE_FREE(filelist_intern->filtered); } -static void filelist_cache_preview_runf(TaskPool *__restrict pool, - void *taskdata, - int UNUSED(threadid)) +static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdata) { - FileListEntryCache *cache = BLI_task_pool_userdata(pool); + FileListEntryCache *cache = BLI_task_pool_user_data(pool); FileListEntryPreviewTaskData *preview_taskdata = taskdata; FileListEntryPreview *preview = preview_taskdata->preview; @@ -1306,9 +1304,7 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, // printf("%s: End (%d)...\n", __func__, threadid); } -static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), void *taskdata) { FileListEntryPreviewTaskData *preview_taskdata = taskdata; FileListEntryPreview *preview = preview_taskdata->preview; @@ -1327,9 +1323,7 @@ static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), static void filelist_cache_preview_ensure_running(FileListEntryCache *cache) { if (!cache->previews_pool) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - - cache->previews_pool = BLI_task_pool_create_background(scheduler, cache, TASK_PRIORITY_LOW); + cache->previews_pool = BLI_task_pool_create_background(cache, TASK_PRIORITY_LOW); cache->previews_done = BLI_thread_queue_init(); IMB_thumb_locks_acquire(); diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 8c931a0c4a3..6c984860efc 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -42,6 +42,7 @@ #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_screen.h" diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 08053dba4d9..8ffd2844f1a 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -328,7 +328,7 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op) void GRAPH_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "GRAPH_OT_view_all"; ot->description = "Reset viewable area to show full keyframe range"; diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index a2e9ba86dec..ae435b5624a 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -760,8 +760,8 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op) } data_lasso.rectf_view = &rect_fl; - data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot); - if (data_lasso.mcords == NULL) { + data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len); + if (data_lasso.mcoords == NULL) { return OPERATOR_CANCELLED; } @@ -782,13 +782,13 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op) } /* get settings from operator */ - BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot); + BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len); BLI_rctf_rcti_copy(&rect_fl, &rect); /* apply box_select action */ box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); - MEM_freeN((void *)data_lasso.mcords); + MEM_freeN((void *)data_lasso.mcoords); /* send notifier that keyframe selection has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 7f911113b7c..c9f2ec38354 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -264,7 +264,10 @@ void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy) } } -void ED_space_image_get_zoom(SpaceImage *sima, ARegion *region, float *r_zoomx, float *r_zoomy) +void ED_space_image_get_zoom(SpaceImage *sima, + const ARegion *region, + float *r_zoomx, + float *r_zoomy) { int width, height; @@ -314,7 +317,7 @@ void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *r_aspx, float * } /* takes event->mval */ -void ED_image_mouse_pos(SpaceImage *sima, ARegion *region, const int mval[2], float co[2]) +void ED_image_mouse_pos(SpaceImage *sima, const ARegion *region, const int mval[2], float co[2]) { int sx, sy, width, height; float zoomx, zoomy; @@ -341,7 +344,7 @@ void ED_image_view_center_to_point(SpaceImage *sima, float x, float y) } void ED_image_point_pos( - SpaceImage *sima, ARegion *region, float x, float y, float *r_x, float *r_y) + SpaceImage *sima, const ARegion *region, float x, float y, float *r_x, float *r_y) { int sx, sy, width, height; float zoomx, zoomy; @@ -356,7 +359,7 @@ void ED_image_point_pos( } void ED_image_point_pos__reverse(SpaceImage *sima, - ARegion *region, + const ARegion *region, const float co[2], float r_co[2]) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index c2054756795..eb97077f77a 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -826,7 +826,7 @@ void IMAGE_OT_view_all(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "IMAGE_OT_view_all"; ot->description = "View the entire image"; @@ -986,7 +986,7 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom In"; + ot->name = "Zoom In"; ot->idname = "IMAGE_OT_view_zoom_in"; ot->description = "Zoom in the image (centered around 2D cursor)"; @@ -1045,7 +1045,7 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom Out"; + ot->name = "Zoom Out"; ot->idname = "IMAGE_OT_view_zoom_out"; ot->description = "Zoom out the image (centered around 2D cursor)"; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 1e1d4373fea..d7d85112497 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -127,6 +127,7 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce simage->zoom = 1.0f; simage->lock = true; simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS; + simage->uv_opacity = 1.0f; BKE_imageuser_default(&simage->iuser); simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index a91a11b2465..f8c0e66873f 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -33,6 +33,8 @@ #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" +#include "BLF_api.h" + #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" @@ -59,9 +61,10 @@ #include "ED_armature.h" #include "ED_info.h" +#include "UI_resources.h" + #include "GPU_extensions.h" -#define MAX_INFO_LEN 512 #define MAX_INFO_NUM_LEN 16 typedef struct SceneStats { @@ -73,8 +76,6 @@ typedef struct SceneStats { uint64_t totlamp, totlampsel; uint64_t tottri; uint64_t totgplayer, totgpframe, totgpstroke, totgppoint; - - char infostr[MAX_INFO_LEN]; } SceneStats; typedef struct SceneStatsFmt { @@ -368,10 +369,16 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer) if (obedit) { /* Edit Mode */ - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, ((View3D *)NULL), ob->type, ob->mode, ob_iter) { - stats_object_edit(ob_iter, &stats); + FOREACH_OBJECT_BEGIN (view_layer, ob_iter) { + if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) { + if (ob_iter->mode == OB_MODE_EDIT) { + stats_object_edit(ob_iter, &stats); + stats.totobjsel++; + } + stats.totobj++; + } } - FOREACH_OBJECT_IN_MODE_END; + FOREACH_OBJECT_END; } else if (ob && (ob->mode & OB_MODE_POSE)) { /* Pose Mode */ @@ -398,26 +405,98 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer) *(view_layer->stats) = stats; } -static void stats_string(ViewLayer *view_layer) +static const char *footer_string(ViewLayer *view_layer) { #define MAX_INFO_MEM_LEN 64 - SceneStats *stats = view_layer->stats; - SceneStatsFmt stats_fmt; - LayerCollection *layer_collection = view_layer->active_collection; - Object *ob = OBACT(view_layer); - Object *obedit = OBEDIT_FROM_OBACT(ob); - eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT; - uintptr_t mem_in_use, mmap_in_use; char memstr[MAX_INFO_MEM_LEN]; char gpumemstr[MAX_INFO_MEM_LEN] = ""; char formatted_mem[15]; - char *s; size_t ofs = 0; - mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); + uintptr_t mem_in_use = MEM_get_memory_in_use(); + uintptr_t mmap_in_use = MEM_get_mapped_memory_in_use(); + + /* get memory statistics */ + BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, false); + ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, TIP_("Mem: %s"), formatted_mem); + + if (mmap_in_use) { + BLI_str_format_byte_unit(formatted_mem, mmap_in_use, false); + BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_(" (%s)"), formatted_mem); + } + + if (GPU_mem_stats_supported()) { + int gpu_free_mem, gpu_tot_memory; + + GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem); + + BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, false); + ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, TIP_(" | Free GPU Mem: %s"), formatted_mem); + + if (gpu_tot_memory) { + BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, false); + BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_("/%s"), formatted_mem); + } + } + + BLI_snprintf(view_layer->footer_str, + sizeof(view_layer->footer_str), + "%s%s | %s", + memstr, + gpumemstr, + versionstr); + + return view_layer->footer_str; + +#undef MAX_INFO_MEM_LEN +} + +void ED_info_stats_clear(ViewLayer *view_layer) +{ + if (view_layer->stats) { + MEM_freeN(view_layer->stats); + view_layer->stats = NULL; + } +} + +const char *ED_info_footer_string(ViewLayer *view_layer) +{ + return footer_string(view_layer); +} + +static void stats_row(int col1, + const char *key, + int col2, + const char *value1, + const char *value2, + int *y, + int height) +{ + *y -= height; + BLF_draw_default(col1, *y, 0.0f, key, 128); + char values[128]; + BLI_snprintf(values, sizeof(values), (value2) ? "%s / %s" : "%s", value1, value2); + BLF_draw_default(col2, *y, 0.0f, values, sizeof(values)); +} + +void ED_info_draw_stats( + Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height) +{ + /* Create stats if they don't already exist. */ + if (!view_layer->stats) { + /* Do not not access dependency graph if interface is marked as locked. */ + wmWindowManager *wm = bmain->wm.first; + if (wm->is_interface_locked) { + return; + } + Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true); + stats_update(depsgraph, view_layer); + } - /* Generate formatted numbers */ + SceneStats *stats = view_layer->stats; + SceneStatsFmt stats_fmt; + + /* Generate formatted numbers. */ #define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt._id, stats->_id) SCENE_STATS_FMT_INT(totvert); @@ -447,151 +526,94 @@ static void stats_string(ViewLayer *view_layer) #undef SCENE_STATS_FMT_INT - /* get memory statistics */ - BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, false); - ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, TIP_(" | Mem: %s"), formatted_mem); - - if (mmap_in_use) { - BLI_str_format_byte_unit(formatted_mem, mmap_in_use, false); - BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_(" (%s)"), formatted_mem); + Object *ob = OBACT(view_layer); + Object *obedit = OBEDIT_FROM_OBACT(ob); + eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT; + const int font_id = BLF_default(); + + UI_FontThemeColor(font_id, TH_TEXT_HI); + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); + + /* Translated labels for each stat row. */ + enum { + OBJ, + VERTS, + EDGES, + FACES, + TRIS, + BONES, + LAYERS, + FRAMES, + STROKES, + POINTS, + MAX_LABELS_COUNT + }; + char labels[MAX_LABELS_COUNT][64]; + + STRNCPY(labels[OBJ], IFACE_("Objects")); + STRNCPY(labels[VERTS], IFACE_("Vertices")); + STRNCPY(labels[EDGES], IFACE_("Edges")); + STRNCPY(labels[FACES], IFACE_("Faces")); + STRNCPY(labels[TRIS], IFACE_("Triangles")); + STRNCPY(labels[BONES], IFACE_("Bones")); + STRNCPY(labels[LAYERS], IFACE_("Layers")); + STRNCPY(labels[FRAMES], IFACE_("Frames")); + STRNCPY(labels[STROKES], IFACE_("Strokes")); + STRNCPY(labels[POINTS], IFACE_("Points")); + + int longest_label = 0; + int i; + for (i = 0; i < MAX_LABELS_COUNT; ++i) { + longest_label = max_ii(longest_label, BLF_width(font_id, labels[i], sizeof(labels[i]))); } - if (GPU_mem_stats_supported()) { - int gpu_free_mem, gpu_tot_memory; - - GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem); - - BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, false); - ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, TIP_(" | Free GPU Mem: %s"), formatted_mem); - - if (gpu_tot_memory) { - BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, false); - BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_("/%s"), formatted_mem); - } - } + int col1 = x; + int col2 = x + longest_label + (0.5f * U.widget_unit); - s = stats->infostr; - ofs = 0; + /* Add some extra margin above this section. */ + *y -= (0.6f * height); if (object_mode == OB_MODE_OBJECT) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - "%s | ", - BKE_collection_ui_name_get(layer_collection->collection)); - } - - if (ob) { - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", ob->id.name + 2); + stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height); } if (obedit) { - if (BKE_keyblock_from_object(obedit)) { - ofs += BLI_strncpy_rlen(s + ofs, TIP_("(Key) "), MAX_INFO_LEN - ofs); - } - if (obedit->type == OB_MESH) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"), - stats_fmt.totvertsel, - stats_fmt.totvert, - stats_fmt.totedgesel, - stats_fmt.totedge, - stats_fmt.totfacesel, - stats_fmt.totface, - stats_fmt.tottri); + stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); + stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height); + stats_row(col1, labels[FACES], col2, stats_fmt.totfacesel, stats_fmt.totface, y, height); + stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height); } else if (obedit->type == OB_ARMATURE) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s/%s | Bones:%s/%s"), - stats_fmt.totvertsel, - stats_fmt.totvert, - stats_fmt.totbonesel, - stats_fmt.totbone); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); + stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height); } else { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s/%s"), - stats_fmt.totvertsel, - stats_fmt.totvert); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); } - - ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs); - ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs); } else if (ob && (object_mode & OB_MODE_POSE)) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Bones:%s/%s %s%s"), - stats_fmt.totbonesel, - stats_fmt.totbone, - memstr, - gpumemstr); + stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height); } else if ((ob) && (ob->type == OB_GPENCIL)) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Layers:%s | Frames:%s | Strokes:%s | Points:%s | Objects:%s/%s"), - stats_fmt.totgplayer, - stats_fmt.totgpframe, - stats_fmt.totgpstroke, - stats_fmt.totgppoint, - stats_fmt.totobjsel, - stats_fmt.totobj); - - ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs); - ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs); + stats_row(col1, labels[LAYERS], col2, stats_fmt.totgplayer, NULL, y, height); + stats_row(col1, labels[FRAMES], col2, stats_fmt.totgpframe, NULL, y, height); + stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, NULL, y, height); + stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, NULL, y, height); } else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s | Tris:%s%s"), - stats_fmt.totvert, - stats_fmt.tottri, - gpumemstr); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height); + stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height); } else { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s%s%s"), - stats_fmt.totvert, - stats_fmt.totface, - stats_fmt.tottri, - stats_fmt.totobjsel, - stats_fmt.totobj, - memstr, - gpumemstr); - } - - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, " | %s", versionstr); -#undef MAX_INFO_MEM_LEN -} - -#undef MAX_INFO_LEN - -void ED_info_stats_clear(ViewLayer *view_layer) -{ - if (view_layer->stats) { - MEM_freeN(view_layer->stats); - view_layer->stats = NULL; + stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height); + stats_row(col1, labels[EDGES], col2, stats_fmt.totedge, NULL, y, height); + stats_row(col1, labels[FACES], col2, stats_fmt.totface, NULL, y, height); + stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height); } -} -const char *ED_info_stats_string(Main *bmain, Scene *scene, ViewLayer *view_layer) -{ - /* Looping through dependency graph when interface is locked is not safe. - * The interface is marked as locked when jobs wants to modify the - * dependency graph. */ - wmWindowManager *wm = bmain->wm.first; - if (wm->is_interface_locked) { - return ""; - } - Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true); - if (!view_layer->stats) { - stats_update(depsgraph, view_layer); - } - stats_string(view_layer); - return view_layer->stats->infostr; + BLF_disable(font_id, BLF_SHADOW); } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 218e2be0362..307b6d9bc21 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -143,7 +143,8 @@ bool nla_panel_context(const bContext *C, case ANIMTYPE_PALETTE: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* for these channels, we only do AnimData */ if (ale->adt && adt_ptr) { ID *id; @@ -354,7 +355,7 @@ static void nla_panel_properties(const bContext *C, Panel *panel) { PointerRNA strip_ptr; uiLayout *layout = panel->layout; - uiLayout *column; + uiLayout *column, *row; uiBlock *block; short showEvalProps = 1; @@ -401,20 +402,19 @@ static void nla_panel_properties(const bContext *C, Panel *panel) uiItemR(column, &strip_ptr, "blend_in", 0, IFACE_("Blend In"), ICON_NONE); uiItemR(column, &strip_ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE); - column = uiLayoutColumn(layout, true); - uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false); - uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? - - uiItemS(layout); + row = uiLayoutRow(column, true); + uiLayoutSetActive(row, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false); + uiItemR(row, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? /* settings */ - column = uiLayoutColumn(layout, true); - uiLayoutSetActive(column, + column = uiLayoutColumnWithHeading(layout, true, "Playback"); + row = uiLayoutRow(column, true); + uiLayoutSetActive(row, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time"))); - uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE); + uiItemR(row, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE); - uiItemR(layout, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE); + uiItemR(column, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE); } } @@ -442,15 +442,12 @@ static void nla_panel_actclip(const bContext *C, Panel *panel) uiItemR(row, &strip_ptr, "action", 0, NULL, ICON_ACTION); /* action extents */ - // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future? column = uiLayoutColumn(layout, true); uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Frame Start"), ICON_NONE); uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End"), ICON_NONE); - /* XXX: this layout may actually be too abstract and confusing, - * and may be better using standard column layout. */ - row = uiLayoutRow(layout, false); - uiItemR(row, &strip_ptr, "use_sync_length", 0, IFACE_("Sync Length"), ICON_NONE); + row = uiLayoutRowWithHeading(layout, false, "Sync Length"); + uiItemR(row, &strip_ptr, "use_sync_length", 0, "", ICON_NONE); uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length"); /* action usage */ diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 5adcec8a5d7..d399ea47d7e 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -193,7 +193,8 @@ static int mouse_nla_channels( case ANIMTYPE_PALETTE: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* sanity checking... */ if (ale->adt) { /* select/deselect */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 5b949911158..f68896e21d6 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -410,8 +410,8 @@ void NLA_OT_previewrange_set(wmOperatorType *ot) /** * Find the extents of the active channel * - * \param[out] min Bottom y-extent of channel - * \param[out] max Top y-extent of channel + * \param[out] min: Bottom y-extent of channel. + * \param[out] max: Top y-extent of channel. * \return Success of finding a selected channel */ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, float *max) @@ -526,7 +526,7 @@ static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) void NLA_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "NLA_OT_view_all"; ot->description = "Reset viewable area to show full strips range"; diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index f8c30f9a688..4e21cdc9d16 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -75,6 +75,10 @@ if(WITH_OPENIMAGEDENOISE) add_definitions(-DWITH_OPENIMAGEDENOISE) endif() +if (WITH_NEW_SIMULATION_TYPE) + add_definitions(-DWITH_NEW_SIMULATION_TYPE) +endif() + add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index e5ca2efb26f..44003a5b9bc 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -69,9 +69,13 @@ #include "NOD_composite.h" #include "NOD_shader.h" +#include "NOD_simulation.h" #include "NOD_texture.h" #include "node_intern.h" /* own include */ +/* Default flags for uiItemR(). Name is kept short since this is used a lot in this file. */ +#define DEFAULT_FLAGS UI_ITEM_R_SPLIT_EMPTY_NAME + /* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */ static void node_socket_button_label(bContext *UNUSED(C), @@ -93,7 +97,7 @@ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *p PointerRNA sockptr; RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); - uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); + uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE); } static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -107,7 +111,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr col = uiLayoutColumn(layout, false); uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); - uiItemR(col, &sockptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(col, &sockptr, "default_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); } static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -118,12 +122,12 @@ static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); - uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE); + uiItemR(row, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); if (ELEM(ntree->type, NTREE_COMPOSIT, NTREE_TEXTURE)) { - uiItemR(row, ptr, "use_alpha", 0, "", ICON_IMAGE_RGB_ALPHA); + uiItemR(row, ptr, "use_alpha", DEFAULT_FLAGS, "", ICON_IMAGE_RGB_ALPHA); } - uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -145,8 +149,8 @@ static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt uiTemplateCurveMapping(layout, ptr, "curve", 's', false, false, false, false); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "frame_start", 0, IFACE_("Sta"), ICON_NONE); - uiItemR(row, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE); + uiItemR(row, ptr, "frame_start", DEFAULT_FLAGS, IFACE_("Sta"), ICON_NONE); + uiItemR(row, ptr, "frame_end", DEFAULT_FLAGS, IFACE_("End"), ICON_NONE); } static void node_buts_colorramp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -196,7 +200,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA * PointerRNA sockptr; RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); - uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); + uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE); } #if 0 /* not used in 2.5x yet */ @@ -242,33 +246,33 @@ static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA short multi = (node->id && ((Tex *)node->id)->use_nodes && (node->type != CMP_NODE_TEXTURE) && (node->type != TEX_NODE_TEXTURE)); - uiItemR(layout, ptr, "texture", 0, "", ICON_NONE); + uiItemR(layout, ptr, "texture", DEFAULT_FLAGS, "", ICON_NONE); if (multi) { /* Number Drawing not optimal here, better have a list*/ - uiItemR(layout, ptr, "node_output", 0, "", ICON_NONE); + uiItemR(layout, ptr, "node_output", DEFAULT_FLAGS, "", ICON_NONE); } } static void node_shader_buts_clamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "clamp_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "clamp_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation_type", DEFAULT_FLAGS, "", ICON_NONE); if (!ELEM(RNA_enum_get(ptr, "interpolation_type"), NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) { - uiItemR(layout, ptr, "clamp", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } } static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); - uiItemR(layout, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static int node_resize_area_default(bNode *node, int x, int y) @@ -534,9 +538,9 @@ static int node_resize_area_frame(bNode *node, int x, int y) static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE); - uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE); - uiItemR(layout, ptr, "text", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "label_size", DEFAULT_FLAGS, IFACE_("Label Size"), ICON_NONE); + uiItemR(layout, ptr, "shrink", DEFAULT_FLAGS, IFACE_("Shrink"), ICON_NONE); + uiItemR(layout, ptr, "text", DEFAULT_FLAGS, NULL, ICON_NONE); } #define NODE_REROUTE_SIZE 8.0f @@ -697,7 +701,7 @@ static void node_buts_image_user(uiLayout *layout, col = uiLayoutColumn(layout, false); - uiItemR(col, imaptr, "source", 0, "", ICON_NONE); + uiItemR(col, imaptr, "source", DEFAULT_FLAGS, "", ICON_NONE); source = RNA_enum_get(imaptr, "source"); @@ -716,23 +720,23 @@ static void node_buts_image_user(uiLayout *layout, if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_cyclic", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "frame_duration", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "frame_start", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "frame_offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_cyclic", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_auto_refresh", DEFAULT_FLAGS, NULL, ICON_NONE); } if (compositor && RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER && RNA_boolean_get(ptr, "has_layers")) { col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "layer", DEFAULT_FLAGS, NULL, ICON_NONE); } uiLayout *split = uiLayoutSplit(layout, 0.5f, true); PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings"); uiItemL(split, IFACE_("Color Space"), ICON_NONE); - uiItemR(split, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); + uiItemR(split, &colorspace_settings_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); /* Avoid losing changes image is painted. */ if (BKE_image_is_dirty(imaptr->data)) { @@ -742,35 +746,35 @@ static void node_buts_image_user(uiLayout *layout, static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "vector_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_vector_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "rotation_type", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "invert", 0, NULL, 0); + uiItemR(layout, ptr, "rotation_type", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "convert_from", 0, "", ICON_NONE); - uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE); + uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "convert_from", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "convert_to", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE); + uiItemR(layout, ptr, "attribute_name", DEFAULT_FLAGS, IFACE_("Name"), ICON_NONE); } static void node_shader_buts_wireframe(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_pixel_size", 0, NULL, 0); + uiItemR(layout, ptr, "use_pixel_size", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -789,14 +793,14 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA UI_TEMPLATE_ID_FILTER_ALL, false, NULL); - uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); - uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) { - uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE); + uiItemR(layout, ptr, "projection_blend", DEFAULT_FLAGS, "Blend", ICON_NONE); } - uiItemR(layout, ptr, "extension", 0, "", ICON_NONE); + uiItemR(layout, ptr, "extension", DEFAULT_FLAGS, "", ICON_NONE); /* note: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. @@ -827,8 +831,8 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin false, NULL); - uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); - uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE); node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false); } @@ -838,29 +842,29 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0); - uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE); - uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, IFACE_("Interpolation"), ICON_NONE); + uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, IFACE_("Projection"), ICON_NONE); } static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "sky_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE); - uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "sky_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW) { - uiItemR(layout, ptr, "ground_albedo", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "ground_albedo", DEFAULT_FLAGS, NULL, ICON_NONE); } } static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "gradient_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "gradient_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "turbulence_depth", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -868,48 +872,48 @@ static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "offset", UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); - uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); + uiItemR(col, ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE); - uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE); + uiItemR(col, ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); } static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "wave_type", DEFAULT_FLAGS, "", ICON_NONE); int type = RNA_enum_get(ptr, "wave_type"); if (type == SHD_WAVE_BANDS) { - uiItemR(layout, ptr, "bands_direction", 0, "", ICON_NONE); + uiItemR(layout, ptr, "bands_direction", DEFAULT_FLAGS, "", ICON_NONE); } else { /* SHD_WAVE_RINGS */ - uiItemR(layout, ptr, "rings_direction", 0, "", ICON_NONE); + uiItemR(layout, ptr, "rings_direction", DEFAULT_FLAGS, "", ICON_NONE); } - uiItemR(layout, ptr, "wave_profile", 0, "", ICON_NONE); + uiItemR(layout, ptr, "wave_profile", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "musgrave_dimensions", 0, "", ICON_NONE); - uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "musgrave_dimensions", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "voronoi_dimensions", 0, "", ICON_NONE); - uiItemR(layout, ptr, "feature", 0, "", ICON_NONE); + uiItemR(layout, ptr, "voronoi_dimensions", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "feature", DEFAULT_FLAGS, "", ICON_NONE); int feature = RNA_enum_get(ptr, "feature"); if (!ELEM(feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS) && RNA_enum_get(ptr, "voronoi_dimensions") != 1) { - uiItemR(layout, ptr, "distance", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, "", ICON_NONE); } } static void node_shader_buts_tex_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "noise_dimensions", 0, "", ICON_NONE); + uiItemR(layout, ptr, "noise_dimensions", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_pointdensity(uiLayout *layout, @@ -925,7 +929,7 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, RNA_id_pointer_create(ob ? (ID *)ob->data : NULL, &obdata_ptr); uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, ICON_NONE); if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { PointerRNA dataptr; @@ -933,15 +937,15 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, uiItemPointerR(layout, ptr, "particle_system", &dataptr, "particle_systems", NULL, ICON_NONE); } - uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "radius", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "resolution", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "radius", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "resolution", DEFAULT_FLAGS, NULL, ICON_NONE); if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { - uiItemR(layout, ptr, "particle_color_source", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "particle_color_source", DEFAULT_FLAGS, NULL, ICON_NONE); } else { - uiItemR(layout, ptr, "vertex_color_source", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "vertex_color_source", DEFAULT_FLAGS, NULL, ICON_NONE); if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) { if (ob_ptr.data) { uiItemPointerR( @@ -959,18 +963,18 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "object", 0, NULL, 0); - uiItemR(layout, ptr, "from_instancer", 0, NULL, 0); + uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_bump(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "invert", 0, NULL, 0); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiItemR(layout, ptr, "from_instancer", 0, NULL, 0); + uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0); if (!RNA_boolean_get(ptr, "from_instancer")) { PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); @@ -996,12 +1000,12 @@ static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, Pointer static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_tips", 0, NULL, 0); + uiItemR(layout, ptr, "use_tips", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiItemR(layout, ptr, "space", 0, "", 0); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", 0); if (RNA_enum_get(ptr, "space") == SHD_SPACE_TANGENT) { PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); @@ -1011,14 +1015,14 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else { - uiItemR(layout, ptr, "uv_map", 0, "", 0); + uiItemR(layout, ptr, "uv_map", DEFAULT_FLAGS, "", 0); } } } static void node_shader_buts_displacement(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "space", 0, "", 0); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", 0); } static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -1027,7 +1031,7 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA * split = uiLayoutSplit(layout, 0.0f, false); - uiItemR(split, ptr, "direction_type", 0, "", 0); + uiItemR(split, ptr, "direction_type", DEFAULT_FLAGS, "", 0); row = uiLayoutRow(split, false); @@ -1039,50 +1043,50 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA * uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else { - uiItemR(row, ptr, "uv_map", 0, "", 0); + uiItemR(row, ptr, "uv_map", DEFAULT_FLAGS, "", 0); } } else { - uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0); + uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, 0); } } static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_principled(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); - uiItemR(layout, ptr, "subsurface_method", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "subsurface_method", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_subsurface(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE); + uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "component", 0, "", ICON_NONE); + uiItemR(layout, ptr, "component", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "component", 0, "", ICON_NONE); + uiItemR(layout, ptr, "component", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_principled_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "parametrization", 0, "", ICON_NONE); + uiItemR(layout, ptr, "parametrization", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1090,15 +1094,15 @@ static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerR uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(layout, true); if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL) { - uiItemR(row, ptr, "ies", 0, "", ICON_NONE); + uiItemR(row, ptr, "ies", DEFAULT_FLAGS, "", ICON_NONE); } else { - uiItemR(row, ptr, "filepath", 0, "", ICON_NONE); + uiItemR(row, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE); } } @@ -1107,15 +1111,15 @@ static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), Point uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(layout, true); if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL) { - uiItemR(row, ptr, "script", 0, "", ICON_NONE); + uiItemR(row, ptr, "script", DEFAULT_FLAGS, "", ICON_NONE); } else { - uiItemR(row, ptr, "filepath", 0, "", ICON_NONE); + uiItemR(row, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE); } uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update"); @@ -1129,14 +1133,14 @@ static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA #if 0 /* not implemented yet */ if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) { - uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_auto_update", DEFAULT_FLAGS, NULL, ICON_NONE); } #endif } static void node_buts_output_shader(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "target", 0, "", ICON_NONE); + uiItemR(layout, ptr, "target", DEFAULT_FLAGS, "", ICON_NONE); } static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1145,32 +1149,32 @@ static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), Po col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); - uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE); - uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "inside", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "only_local", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "noise_dimensions", 0, "", ICON_NONE); + uiItemR(layout, ptr, "noise_dimensions", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_output_aov(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "name", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "name", DEFAULT_FLAGS, NULL, ICON_NONE); } /* only once called */ @@ -1355,10 +1359,10 @@ static void node_buts_image_views(uiLayout *layout, if (RNA_boolean_get(ptr, "has_views")) { if (RNA_enum_get(ptr, "view") == 0) { - uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO); + uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_CAMERA_STEREO); } else { - uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE); + uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_SCENE); } } } @@ -1419,7 +1423,7 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); - uiItemR(row, ptr, "layer", 0, "", ICON_NONE); + uiItemR(row, ptr, "layer", DEFAULT_FLAGS, "", ICON_NONE); prop = RNA_struct_find_property(ptr, "layer"); if (!(RNA_property_enum_identifier( @@ -1446,56 +1450,56 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point filter = RNA_enum_get(ptr, "filter_type"); reference = RNA_boolean_get(ptr, "use_variable_size"); - uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(col, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); if (filter != R_FILTER_FAST_GAUSS) { - uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE); if (!reference) { - uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_bokeh", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_boolean_get(ptr, "use_relative")) { uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "aspect_correction", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE); - uiItemR(col, ptr, "factor_y", 0, IFACE_("Y"), ICON_NONE); + uiItemR(col, ptr, "factor_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); + uiItemR(col, ptr, "factor_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE); } else { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "size_x", 0, IFACE_("X"), ICON_NONE); - uiItemR(col, ptr, "size_y", 0, IFACE_("Y"), ICON_NONE); + uiItemR(col, ptr, "size_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); + uiItemR(col, ptr, "size_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE); } - uiItemR(col, ptr, "use_extended_bounds", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_wrap", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Center:"), ICON_NONE); - uiItemR(col, ptr, "center_x", 0, IFACE_("X"), ICON_NONE); - uiItemR(col, ptr, "center_y", 0, IFACE_("Y"), ICON_NONE); + uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); + uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE); uiItemS(layout); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); uiItemS(layout); - uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "spin", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "zoom", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_bilateralblur(uiLayout *layout, @@ -1505,9 +1509,9 @@ static void node_composit_buts_bilateralblur(uiLayout *layout, uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "sigma_space", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "sigma_color", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "sigma_space", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -1516,60 +1520,60 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE); - uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE); - uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "bokeh", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == true); - uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_preview", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_zbuffer", DEFAULT_FLAGS, NULL, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == false); - uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE); + uiItemR(sub, ptr, "z_scale", DEFAULT_FLAGS, NULL, ICON_NONE); } /* qdn: glare node */ static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "glare_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "quality", 0, "", ICON_NONE); + uiItemR(layout, ptr, "glare_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "quality", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "glare_type") != 1) { - uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") != 0) { - uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "color_modulation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } } - uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "mix", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") == 2) { - uiItemR(layout, ptr, "streaks", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "angle_offset", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "streaks", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "angle_offset", DEFAULT_FLAGS, NULL, ICON_NONE); } if (RNA_enum_get(ptr, "glare_type") == 0 || RNA_enum_get(ptr, "glare_type") == 2) { - uiItemR(layout, ptr, "fade", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "fade", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") == 0) { - uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_rotate_45", DEFAULT_FLAGS, NULL, ICON_NONE); } } if (RNA_enum_get(ptr, "glare_type") == 1) { - uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -1578,17 +1582,17 @@ static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "tonemap_type", 0, "", ICON_NONE); + uiItemR(col, ptr, "tonemap_type", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "tonemap_type") == 0) { - uiItemR(col, ptr, "key", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "gamma", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "key", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); } else { - uiItemR(col, ptr, "intensity", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "adaptation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "correction", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "intensity", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "adaptation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "correction", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } } @@ -1597,12 +1601,12 @@ static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), P uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_projector", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(col, false); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == false); - uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_jitter", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_fit", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1610,46 +1614,46 @@ static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "factor", 0, IFACE_("Blur"), ICON_NONE); + uiItemR(col, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "factor", DEFAULT_FLAGS, IFACE_("Blur"), ICON_NONE); col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Speed:"), ICON_NONE); - uiItemR(col, ptr, "speed_min", 0, IFACE_("Min"), ICON_NONE); - uiItemR(col, ptr, "speed_max", 0, IFACE_("Max"), ICON_NONE); + uiItemR(col, ptr, "speed_min", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE); + uiItemR(col, ptr, "speed_max", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE); - uiItemR(layout, ptr, "use_curved", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_curved", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_flip(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "axis", 0, "", ICON_NONE); + uiItemR(layout, ptr, "axis", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "use_crop_size", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "relative", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_crop_size", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "relative", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); if (RNA_boolean_get(ptr, "relative")) { - uiItemR(col, ptr, "rel_min_x", 0, IFACE_("Left"), ICON_NONE); - uiItemR(col, ptr, "rel_max_x", 0, IFACE_("Right"), ICON_NONE); - uiItemR(col, ptr, "rel_min_y", 0, IFACE_("Up"), ICON_NONE); - uiItemR(col, ptr, "rel_max_y", 0, IFACE_("Down"), ICON_NONE); + uiItemR(col, ptr, "rel_min_x", DEFAULT_FLAGS, IFACE_("Left"), ICON_NONE); + uiItemR(col, ptr, "rel_max_x", DEFAULT_FLAGS, IFACE_("Right"), ICON_NONE); + uiItemR(col, ptr, "rel_min_y", DEFAULT_FLAGS, IFACE_("Up"), ICON_NONE); + uiItemR(col, ptr, "rel_max_y", DEFAULT_FLAGS, IFACE_("Down"), ICON_NONE); } else { - uiItemR(col, ptr, "min_x", 0, IFACE_("Left"), ICON_NONE); - uiItemR(col, ptr, "max_x", 0, IFACE_("Right"), ICON_NONE); - uiItemR(col, ptr, "min_y", 0, IFACE_("Up"), ICON_NONE); - uiItemR(col, ptr, "max_y", 0, IFACE_("Down"), ICON_NONE); + uiItemR(col, ptr, "min_x", DEFAULT_FLAGS, IFACE_("Left"), ICON_NONE); + uiItemR(col, ptr, "max_x", DEFAULT_FLAGS, IFACE_("Right"), ICON_NONE); + uiItemR(col, ptr, "min_y", DEFAULT_FLAGS, IFACE_("Up"), ICON_NONE); + uiItemR(col, ptr, "max_y", DEFAULT_FLAGS, IFACE_("Down"), ICON_NONE); } } @@ -1659,8 +1663,8 @@ static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C) col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(col, ptr, "factor", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_double_edge_mask(uiLayout *layout, @@ -1672,9 +1676,9 @@ static void node_composit_buts_double_edge_mask(uiLayout *layout, col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE); - uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE); + uiItemR(col, ptr, "inner_mode", DEFAULT_FLAGS, "", ICON_NONE); uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE); - uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE); + uiItemR(col, ptr, "edge_mode", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1682,7 +1686,7 @@ static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1690,20 +1694,20 @@ static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), uiLayout *sub, *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "size", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_min", DEFAULT_FLAGS, NULL, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min")); - uiItemR(sub, ptr, "min", 0, "", ICON_NONE); + uiItemR(sub, ptr, "min", DEFAULT_FLAGS, "", ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_max", DEFAULT_FLAGS, NULL, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max")); - uiItemR(sub, ptr, "max", 0, "", ICON_NONE); + uiItemR(sub, ptr, "max", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1711,8 +1715,8 @@ static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "premul", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1720,27 +1724,27 @@ static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), P uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_antialias_z", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_antialias_z", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); switch (RNA_enum_get(ptr, "mode")) { case CMP_NODE_DILATEERODE_DISTANCE_THRESH: - uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "edge", DEFAULT_FLAGS, NULL, ICON_NONE); break; case CMP_NODE_DILATEERODE_DISTANCE_FEATHER: - uiItemR(layout, ptr, "falloff", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, NULL, ICON_NONE); break; } } static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1748,8 +1752,8 @@ static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "threshold_neighbor", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold_neighbor", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1757,8 +1761,8 @@ static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_distance_matte(uiLayout *layout, @@ -1771,10 +1775,10 @@ static void node_composit_buts_distance_matte(uiLayout *layout, uiItemL(layout, IFACE_("Color Space:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1783,23 +1787,23 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C) uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "limit_method") == 0) { uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); } - uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "ratio", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "use_unspill", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_boolean_get(ptr, "use_unspill") == true) { - uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "unspill_red", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "unspill_green", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "unspill_blue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } } @@ -1808,12 +1812,12 @@ static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); /*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now */ - uiItemR(col, ptr, "gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); /*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now*/ } @@ -1822,9 +1826,9 @@ static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C) uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "color_hue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "color_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "color_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_channel_matte(uiLayout *layout, @@ -1835,24 +1839,24 @@ static void node_composit_buts_channel_matte(uiLayout *layout, uiItemL(layout, IFACE_("Color Space:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "color_space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Key Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "matte_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "matte_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "limit_method") == 0) { uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); } - uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1860,19 +1864,19 @@ static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "alpha", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "index", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "index", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_antialiasing", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1886,7 +1890,7 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C) else { uiItemL(layout, IFACE_("Base Path:"), ICON_NONE); } - uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE); + uiItemR(layout, ptr, "base_path", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { @@ -1972,7 +1976,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi uiItemL(col, IFACE_("Layer:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE); + uiItemR(row, &active_input_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", @@ -1987,7 +1991,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi uiItemL(col, IFACE_("File Subpath:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE); + uiItemR(row, &active_input_ptr, "path", DEFAULT_FLAGS, "", ICON_NONE); uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", @@ -2002,7 +2006,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Format:"), ICON_NONE); - uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE); + uiItemR(col, &active_input_ptr, "use_node_format", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false); @@ -2017,20 +2021,20 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "space", 0, "", ICON_NONE); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) { uiLayout *row; - uiItemR(layout, ptr, "frame_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "frame_method", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE); - uiItemR(row, ptr, "offset_y", 0, "Y", ICON_NONE); + uiItemR(row, ptr, "offset_x", DEFAULT_FLAGS, "X", ICON_NONE); + uiItemR(row, ptr, "offset_y", DEFAULT_FLAGS, "Y", ICON_NONE); } } static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2038,25 +2042,25 @@ static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), Poi uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "invert_rgb", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "invert_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE); + uiItemR(layout, ptr, "mapping", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); } static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *split, *col, *row; - uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "correction_method") == 0) { @@ -2064,17 +2068,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE); } else { @@ -2082,46 +2086,46 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "offset_basis", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "offset_basis", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "power", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE); } } static void node_composit_buts_colorbalance_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "correction_method") == 0) { uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1); - uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1); - uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1); - uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE); } else { uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1); - uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1); - uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1); - uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2143,7 +2147,7 @@ static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2180,19 +2184,19 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe return; } - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "invert", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_translate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_relative", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "wrap_axis", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "wrap_axis", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2206,7 +2210,7 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po return; } - uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distortion_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_colorcorrection(uiLayout *layout, @@ -2216,9 +2220,9 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "red", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "green", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, "", ICON_NONE); @@ -2230,39 +2234,39 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Master"), ICON_NONE); - uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Highlights"), ICON_NONE); - uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Midtones"), ICON_NONE); - uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Shadows"), ICON_NONE); - uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "midtones_start", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_colorcorrection_ex(uiLayout *layout, @@ -2272,48 +2276,48 @@ static void node_composit_buts_colorcorrection_ex(uiLayout *layout, uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "red", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "green", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE); row = layout; uiItemL(row, IFACE_("Saturation"), ICON_NONE); - uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Contrast"), ICON_NONE); - uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Gamma"), ICON_NONE); - uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Gain"), ICON_NONE); - uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Lift"), ICON_NONE); - uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "check", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_switch_view_ex(uiLayout *layout, @@ -2335,32 +2339,32 @@ static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *row; row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "x", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "y", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "flaps", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "rounding", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "catadioptric", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "shift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "flaps", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "rounding", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "catadioptric", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "shift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_variable_size", 0, NULL, ICON_NONE); - // uiItemR(layout, ptr, "f_stop", 0, NULL, ICON_NONE); // UNUSED - uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_extended_bounds", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE); + // uiItemR(layout, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE); // UNUSED + uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_backdrop_viewer( @@ -2486,36 +2490,36 @@ static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C) { uiLayout *row; row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "x", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "y", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_composite(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "tile_order", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "tile_order") == 0) { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "center_x", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "center_y", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2524,19 +2528,19 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p bNode *node = ptr->data; uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); - uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_feather", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE); + uiItemR(layout, ptr, "size_source", DEFAULT_FLAGS, "", ICON_NONE); if (node->custom1 & (CMP_NODEFLAG_MASK_FIXED | CMP_NODEFLAG_MASK_FIXED_SCENE)) { - uiItemR(layout, ptr, "size_x", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "size_y", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "size_x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "size_y", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE); if (node->custom1 & CMP_NODEFLAG_MASK_MOTION_BLUR) { - uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2562,18 +2566,18 @@ static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), Poi { /* bNode *node = ptr->data; */ /* UNUSED */ - uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "despill_balance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "edge_kernel_radius", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "edge_kernel_tolerance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "feather_falloff", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "feather_distance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "blur_post", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_pre", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "screen_balance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "despill_factor", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "despill_balance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "edge_kernel_radius", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "edge_kernel_tolerance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "clip_black", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "clip_white", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "dilate_distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "feather_falloff", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "feather_distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_post", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2605,13 +2609,13 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA); } else { - uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA); + uiItemR(layout, ptr, "track_name", DEFAULT_FLAGS, "", ICON_ANIM_DATA); } - uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "position", DEFAULT_FLAGS, NULL, ICON_NONE); if (ELEM(node->custom1, CMP_TRACKPOS_RELATIVE_FRAME, CMP_TRACKPOS_ABSOLUTE_FRAME)) { - uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "frame_relative", DEFAULT_FLAGS, NULL, ICON_NONE); } } } @@ -2650,10 +2654,10 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P } } - uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE); if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) { - uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2665,8 +2669,8 @@ static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "source", UI_ITEM_R_EXPAND, "", ICON_NONE); - uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, "", ICON_NONE); + uiItemR(layout, ptr, "ray_length", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2679,7 +2683,7 @@ static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C) uiTemplateCryptoPicker(row, ptr, "add"); uiTemplateCryptoPicker(row, ptr, "remove"); - uiItemR(col, ptr, "matte_id", 0, "", ICON_NONE); + uiItemR(col, ptr, "matte_id", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_cryptomatte_ex(uiLayout *layout, @@ -2694,7 +2698,7 @@ static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2707,7 +2711,7 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), Po } #endif - uiItemR(layout, ptr, "use_hdr", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_hdr", DEFAULT_FLAGS, NULL, ICON_NONE); } /* only once called */ @@ -2957,12 +2961,12 @@ static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), Poin uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "offset", UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); - uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); + uiItemR(col, ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE); - uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE); + uiItemR(col, ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); } static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2979,68 +2983,73 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe switch (tex->type) { case TEX_BLEND: - uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "progression", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "use_flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "use_flip_axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); break; case TEX_MARBLE: row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "marble_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "marble_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(row, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); break; case TEX_MAGIC: - uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "noise_depth", DEFAULT_FLAGS, NULL, ICON_NONE); break; case TEX_STUCCI: row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "stucci_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "stucci_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); break; case TEX_WOOD: - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); - uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, &tex_ptr, "wood_type", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); uiLayoutSetActive(row, !(ELEM(tex->stype, TEX_BAND, TEX_RING))); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); break; case TEX_CLOUDS: - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "cloud_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "cloud_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, &tex_ptr, "noise_depth", UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(col, + &tex_ptr, + "noise_depth", + DEFAULT_FLAGS | UI_ITEM_R_EXPAND, + IFACE_("Depth"), + ICON_NONE); break; case TEX_DISTNOISE: - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); - uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_distortion", DEFAULT_FLAGS, "", ICON_NONE); break; case TEX_MUSGRAVE: - uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE); - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); break; case TEX_VORONOI: - uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "distance_metric", DEFAULT_FLAGS, "", ICON_NONE); if (tex->vn_distm == TEX_MINKOVSKY) { - uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "minkovsky_exponent", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "color_mode", DEFAULT_FLAGS, "", ICON_NONE); break; } } @@ -3070,7 +3079,7 @@ static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE); } /* only once called */ @@ -3122,6 +3131,96 @@ static void node_texture_set_butfunc(bNodeType *ntype) } } +/* ****************** BUTTON CALLBACKS FOR SIMULATION NODES ***************** */ + +static void node_simulation_buts_particle_simulation(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_particle_time_step_event(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_particle_attribute(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_set_particle_attribute(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_set_butfunc(bNodeType *ntype) +{ + switch (ntype->type) { + case SIM_NODE_PARTICLE_SIMULATION: + ntype->draw_buttons = node_simulation_buts_particle_simulation; + break; + case SIM_NODE_PARTICLE_TIME_STEP_EVENT: + ntype->draw_buttons = node_simulation_buts_particle_time_step_event; + break; + case SIM_NODE_PARTICLE_ATTRIBUTE: + ntype->draw_buttons = node_simulation_buts_particle_attribute; + break; + case SIM_NODE_SET_PARTICLE_ATTRIBUTE: + ntype->draw_buttons = node_simulation_buts_set_particle_attribute; + break; + case SIM_NODE_TIME: + ntype->draw_buttons = node_simulation_buts_time; + break; + } +} + +/* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */ + +static void node_function_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_function_buts_float_compare(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_function_set_butfunc(bNodeType *ntype) +{ + switch (ntype->type) { + case FN_NODE_BOOLEAN_MATH: + ntype->draw_buttons = node_function_buts_boolean_math; + break; + case FN_NODE_FLOAT_COMPARE: + ntype->draw_buttons = node_function_buts_float_compare; + break; + case FN_NODE_SWITCH: + ntype->draw_buttons = node_function_buts_switch; + break; + } +} + /* ****** init draw callbacks for all tree types, only called in usiblender.c, once ************ */ static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -3230,6 +3329,8 @@ void ED_node_init_butfuncs(void) node_composit_set_butfunc(ntype); node_shader_set_butfunc(ntype); node_texture_set_butfunc(ntype); + node_simulation_set_butfunc(ntype); + node_function_set_butfunc(ntype); /* define update callbacks for socket properties */ node_template_properties_update(ntype); @@ -3240,6 +3341,7 @@ void ED_node_init_butfuncs(void) ntreeType_Composite->ui_icon = ICON_NODE_COMPOSITING; ntreeType_Shader->ui_icon = ICON_NODE_MATERIAL; ntreeType_Texture->ui_icon = ICON_NODE_TEXTURE; + ntreeType_Simulation->ui_icon = ICON_PHYSICS; /* TODO: Use correct icon. */ } void ED_init_custom_node_type(bNodeType *ntype) @@ -3268,6 +3370,12 @@ static const float std_node_socket_colors[][4] = { {0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */ {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */ {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */ + {0.40, 0.10, 0.10, 1.0}, /* SOCK_OBJECT */ + {0.10, 0.40, 0.10, 1.0}, /* SOCK_IMAGE */ + {0.80, 0.80, 0.20, 1.0}, /* SOCK_EMITTERS */ + {0.80, 0.20, 0.80, 1.0}, /* SOCK_EVENTS */ + {0.20, 0.80, 0.80, 1.0}, /* SOCK_FORCES */ + {0.30, 0.30, 0.30, 1.0}, /* SOCK_CONTROL_FLOW */ }; /* common color callbacks for standard types */ @@ -3362,7 +3470,7 @@ static void std_node_socket_draw( case SOCK_FLOAT: case SOCK_INT: case SOCK_BOOLEAN: - uiItemR(layout, ptr, "default_value", 0, text, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); break; case SOCK_VECTOR: if (sock->flag & SOCK_COMPACT) { @@ -3370,11 +3478,11 @@ static void std_node_socket_draw( } else { if (sock->typeinfo->subtype == PROP_DIRECTION) { - uiItemR(layout, ptr, "default_value", 0, "", ICON_NONE); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE); } else { uiLayout *column = uiLayoutColumn(layout, true); - uiItemR(column, ptr, "default_value", 0, text, ICON_NONE); + uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE); } } break; @@ -3382,7 +3490,15 @@ static void std_node_socket_draw( case SOCK_STRING: { uiLayout *row = uiLayoutSplit(layout, 0.5f, false); uiItemL(row, text, 0); - uiItemR(row, ptr, "default_value", 0, "", 0); + uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0); + break; + } + case SOCK_OBJECT: { + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); + break; + } + case SOCK_IMAGE: { + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); break; } default: @@ -3400,32 +3516,32 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout switch (type) { case SOCK_FLOAT: { uiLayout *row; - uiItemR(layout, ptr, "default_value", 0, NULL, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0); - uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); + uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0); + uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0); break; } case SOCK_INT: { uiLayout *row; - uiItemR(layout, ptr, "default_value", 0, NULL, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0); - uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); + uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0); + uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0); break; } case SOCK_VECTOR: { uiLayout *row; - uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, 0); + uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, DEFAULT_FLAGS); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0); - uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); + uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0); + uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0); break; } case SOCK_BOOLEAN: case SOCK_RGBA: case SOCK_STRING: { - uiItemR(layout, ptr, "default_value", 0, NULL, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0); break; } } diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 4cf67dddb57..8fc343a9ed4 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -84,7 +84,7 @@ static void node_sockets_panel(const bContext *C, Panel *panel) split = uiLayoutSplit(layout, 0.35f, false); uiItemL(split, name, ICON_NONE); - uiTemplateNodeLink(split, ntree, node, sock); + uiTemplateNodeLink(split, (bContext *)C, ntree, node, sock); } } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 0552660b9bf..bd8950c5085 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -94,23 +94,11 @@ void ED_node_tree_update(const bContext *C) static bNodeTree *node_tree_from_ID(ID *id) { if (id) { - short idtype = GS(id->name); - - switch (idtype) { - case ID_NT: - return (bNodeTree *)id; - case ID_MA: - return ((Material *)id)->nodetree; - case ID_LA: - return ((Light *)id)->nodetree; - case ID_WO: - return ((World *)id)->nodetree; - case ID_SCE: - return ((Scene *)id)->nodetree; - case ID_TE: - return ((Tex *)id)->nodetree; - case ID_LS: - return ((FreestyleLineStyle *)id)->nodetree; + if (GS(id->name) == ID_NT) { + return (bNodeTree *)id; + } + else { + return ntreeFromID(id); } } @@ -719,39 +707,19 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) #define MARKER_SHAPE_CIRCLE 0x2 #define MARKER_SHAPE_INNER_DOT 0x10 -static void node_socket_draw(const bContext *C, - bNodeTree *ntree, - PointerRNA node_ptr, - bNodeSocket *sock, +static void node_socket_draw(const bNodeSocket *sock, + const float color[4], + const float color_outline[4], + float size, + int locx, + int locy, uint pos_id, uint col_id, uint shape_id, uint size_id, - uint outline_col_id, - float size, - bool selected) + uint outline_col_id) { - PointerRNA ptr; - float color[4]; - float outline_color[4]; - uint flags = 0; - - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); - sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); - - bNode *node = node_ptr.data; - if (node->flag & NODE_MUTED) { - color[3] *= 0.25f; - } - - if (selected) { - UI_GetThemeColor4fv(TH_TEXT_HI, outline_color); - outline_color[3] = 0.9f; - } - else { - copy_v4_fl(outline_color, 0.0f); - outline_color[3] = 0.6f; - } + int flags; /* sets shape flags */ switch (sock->display_shape) { @@ -780,8 +748,120 @@ static void node_socket_draw(const bContext *C, immAttr4fv(col_id, color); immAttr1u(shape_id, flags); immAttr1f(size_id, size); - immAttr4fv(outline_col_id, outline_color); - immVertex2f(pos_id, sock->locx, sock->locy); + immAttr4fv(outline_col_id, color_outline); + immVertex2f(pos_id, locx, locy); +} + +static void node_socket_outline_color_get(bool selected, float r_outline_color[4]) +{ + if (selected) { + UI_GetThemeColor4fv(TH_TEXT_HI, r_outline_color); + r_outline_color[3] = 0.9f; + } + else { + copy_v4_fl(r_outline_color, 0.0f); + r_outline_color[3] = 0.6f; + } +} + +/* Usual convention here would be node_socket_get_color(), but that's already used (for setting a + * color property socket). */ +void node_socket_color_get( + bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4]) +{ + PointerRNA ptr; + + BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node)); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + + sock->typeinfo->draw_color(C, &ptr, node_ptr, r_color); + + bNode *node = node_ptr->data; + if (node->flag & NODE_MUTED) { + r_color[3] *= 0.25f; + } +} + +static void node_socket_draw_nested(const bContext *C, + bNodeTree *ntree, + PointerRNA *node_ptr, + bNodeSocket *sock, + uint pos_id, + uint col_id, + uint shape_id, + uint size_id, + uint outline_col_id, + float size, + bool selected) +{ + float color[4]; + float outline_color[4]; + + node_socket_color_get((bContext *)C, ntree, node_ptr, sock, color); + node_socket_outline_color_get(selected, outline_color); + + node_socket_draw(sock, + color, + outline_color, + size, + sock->locx, + sock->locy, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id); +} + +/** + * Draw a single node socket at default size. + * \note this is only called from external code, internally #node_socket_draw_nested() is used for + * optimized drawing of multiple/all sockets of a node. + */ +void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale) +{ + const float size = 2.25f * NODE_SOCKSIZE * scale; + rcti draw_rect = *rect; + float outline_color[4] = {0}; + + node_socket_outline_color_get(sock->flag & SELECT, outline_color); + + BLI_rcti_resize(&draw_rect, size, size); + + GPUVertFormat *format = immVertexFormat(); + uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); + uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uint outline_col_id = GPU_vertformat_attr_add( + format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + + gpuPushAttr(GPU_BLEND_BIT); + GPU_blend(true); + GPU_program_point_size(true); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 0.7f); + immUniform2f("ViewportSize", -1.0f, -1.0f); + + /* Single point */ + immBegin(GPU_PRIM_POINTS, 1); + node_socket_draw(sock, + color, + outline_color, + BLI_rcti_size_y(&draw_rect), + BLI_rcti_cent_x(&draw_rect), + BLI_rcti_cent_y(&draw_rect), + pos_id, + col_id, + shape_id, + size_id, + outline_col_id); + immEnd(); + + immUnbindProgram(); + GPU_program_point_size(false); + gpuPopAttr(); } /* ************** Socket callbacks *********** */ @@ -974,17 +1054,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } /* socket outputs */ @@ -999,17 +1079,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } } @@ -1032,17 +1112,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_input_len == 0) { break; /* stop as soon as last one is drawn */ } @@ -1057,17 +1137,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_output_len == 0) { break; /* stop as soon as last one is drawn */ } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index a82acfc4dbe..bd5ce135f82 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -69,6 +69,7 @@ #include "NOD_composite.h" #include "NOD_shader.h" +#include "NOD_simulation.h" #include "NOD_texture.h" #include "node_intern.h" /* own include */ @@ -438,6 +439,11 @@ bool ED_node_is_texture(struct SpaceNode *snode) return STREQ(snode->tree_idname, ntreeType_Texture->idname); } +bool ED_node_is_simulation(struct SpaceNode *snode) +{ + return STREQ(snode->tree_idname, ntreeType_Simulation->idname); +} + /* assumes nothing being done in ntree yet, sets the default in/out node */ /* called from shading buttons or header */ void ED_node_shader_default(const bContext *C, ID *id) diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 3a0ef45a68d..2617384d046 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -69,7 +69,8 @@ static bool node_group_operator_active(bContext *C) */ if (STREQ(snode->tree_idname, "ShaderNodeTree") || STREQ(snode->tree_idname, "CompositorNodeTree") || - STREQ(snode->tree_idname, "TextureNodeTree")) { + STREQ(snode->tree_idname, "TextureNodeTree") || + STREQ(snode->tree_idname, "SimulationNodeTree")) { return true; } } @@ -85,7 +86,8 @@ static bool node_group_operator_editable(bContext *C) * Disabled otherwise to allow pynodes define their own operators * with same keymap. */ - if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode)) { + if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode) || + ED_node_is_simulation(snode)) { return true; } } @@ -111,6 +113,9 @@ static const char *group_node_idname(bContext *C) else if (ED_node_is_texture(snode)) { return "TextureNodeGroup"; } + else if (ED_node_is_simulation(snode)) { + return "SimulationNodeGroup"; + } return ""; } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 42439e88c96..04186c3a727 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -38,6 +38,7 @@ struct bContext; struct bNode; struct bNodeLink; struct bNodeSocket; +struct wmGizmoGroupType; struct wmKeyConfig; struct wmWindow; @@ -77,6 +78,11 @@ void node_draw_sockets(struct View2D *v2d, void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); int node_select_area_default(struct bNode *node, int x, int y); int node_tweak_area_default(struct bNode *node, int x, int y); +void node_socket_color_get(struct bContext *C, + struct bNodeTree *ntree, + struct PointerRNA *node_ptr, + struct bNodeSocket *sock, + float r_color[4]); void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree); void node_draw_nodetree(const struct bContext *C, struct ARegion *region, @@ -122,7 +128,7 @@ void NODE_OT_find_node(struct wmOperatorType *ot); /* node_view.c */ int space_node_view_flag(struct bContext *C, - SpaceNode *snode, + struct SpaceNode *snode, ARegion *region, const int node_flag, const int smooth_viewtx); @@ -196,7 +202,7 @@ void NODE_OT_detach(struct wmOperatorType *ot); void NODE_OT_link_viewer(struct wmOperatorType *ot); -void NODE_OT_insert_offset(wmOperatorType *ot); +void NODE_OT_insert_offset(struct wmOperatorType *ot); /* node_edit.c */ void snode_notify(struct bContext *C, struct SpaceNode *snode); @@ -207,8 +213,8 @@ void snode_update(struct SpaceNode *snode, struct bNode *node); bool composite_node_active(struct bContext *C); bool composite_node_editable(struct bContext *C); -int node_has_hidden_sockets(bNode *node); -void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set); +int node_has_hidden_sockets(struct bNode *node); +void node_set_hidden_sockets(struct SpaceNode *snode, bNode *node, int set); int node_render_changed_exec(bContext *, struct wmOperator *); int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 8c2f79109f6..144e3bd3506 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -1657,7 +1657,7 @@ static bool node_link_insert_offset_frame_chain_cb(bNode *fromnode, } /** - * Applies NodeInsertOfsData.offset_x to all childs of \a parent + * Applies #NodeInsertOfsData.offset_x to all children of \a parent. */ static void node_link_insert_offset_frame_chains(const bNodeTree *ntree, const bNode *parent, diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index e96d03f70f4..9eabcc44d80 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -769,7 +769,10 @@ static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent * return WM_gesture_lasso_invoke(C, op, event); } -static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves, eSelectOp sel_op) +static bool do_lasso_select_node(bContext *C, + const int mcoords[][2], + const int mcoords_len, + eSelectOp sel_op) { SpaceNode *snode = CTX_wm_space_node(C); bNode *node; @@ -786,7 +789,7 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves } /* get rectangle from operator */ - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* do actual selection */ for (node = snode->edittree->nodes.first; node; node = node->next) { @@ -802,7 +805,7 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves if (UI_view2d_view_to_region_clip( ®ion->v2d, cent[0], cent[1], &screen_co[0], &screen_co[1]) && BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) { + BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) { nodeSetSelected(node, select); changed = true; } @@ -817,15 +820,15 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves static int node_lasso_select_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - do_lasso_select_node(C, mcords, mcords_tot, sel_op); + do_lasso_select_node(C, mcoords, mcoords_len, sel_op); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); return OPERATOR_FINISHED; } @@ -1116,10 +1119,10 @@ void NODE_OT_select_same_type_step(wmOperatorType *ot) * \{ */ /* generic search invoke */ -static void node_find_cb(const struct bContext *C, - void *UNUSED(arg), - const char *str, - uiSearchItems *items) +static void node_find_update_fn(const struct bContext *C, + void *UNUSED(arg), + const char *str, + uiSearchItems *items) { SpaceNode *snode = CTX_wm_space_node(C); bNode *node; @@ -1142,7 +1145,7 @@ static void node_find_cb(const struct bContext *C, } } -static void node_find_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2) +static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2) { SpaceNode *snode = CTX_wm_space_node(C); bNode *active = arg2; @@ -1182,7 +1185,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op) 0, 0, ""); - UI_but_func_search_set(but, NULL, node_find_cb, op->type, NULL, node_find_call_cb, NULL, NULL); + UI_but_func_search_set(but, NULL, node_find_update_fn, op->type, NULL, node_find_exec_fn, NULL); UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); /* fake button, it holds space for search items */ diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 7d4095326f8..87b1f662b59 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -45,6 +45,7 @@ #include "UI_interface.h" #include "ED_node.h" /* own include */ +#include "node_intern.h" #include "ED_undo.h" @@ -662,17 +663,23 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group")); } -void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock) +void uiTemplateNodeLink( + uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock) { uiBlock *block = uiLayoutGetBlock(layout); NodeLinkArg *arg; uiBut *but; + float socket_col[4]; arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg"); arg->ntree = ntree; arg->node = node; arg->sock = sock; + PointerRNA node_ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); + node_socket_color_get(C, ntree, &node_ptr, sock, socket_col); + UI_block_layout_set_current(block, layout); if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) { @@ -687,8 +694,9 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo } UI_but_type_set_menu_from_pulldown(but); + UI_but_node_link_set(but, sock, socket_col); + UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); - but->flag |= UI_BUT_NODE_LINK; but->poin = (char *)but; but->func_argN = arg; @@ -708,18 +716,14 @@ static void ui_node_draw_node( uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth) { bNodeSocket *input; - uiLayout *col, *split; PointerRNA nodeptr; RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); if (node->typeinfo->draw_buttons) { if (node->type != NODE_GROUP) { - split = uiLayoutSplit(layout, 0.5f, false); - col = uiLayoutColumn(split, false); - col = uiLayoutColumn(split, false); - - node->typeinfo->draw_buttons(col, C, &nodeptr); + uiLayoutSetPropSep(layout, true); + node->typeinfo->draw_buttons(layout, C, &nodeptr); } } @@ -733,12 +737,9 @@ static void ui_node_draw_input( { PointerRNA inputptr, nodeptr; uiBlock *block = uiLayoutGetBlock(layout); - uiBut *bt; - uiLayout *split, *row, *col; + uiLayout *row = NULL; bNode *lnode; - char label[UI_MAX_NAME_STR]; - int i, indent = (depth > 1) ? 2 * (depth - 1) : 0; - int dependency_loop; + bool dependency_loop; if (input->flag & SOCK_UNAVAIL) { return; @@ -757,48 +758,43 @@ static void ui_node_draw_input( RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr); RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); - /* indented label */ - for (i = 0; i < indent; i++) { - label[i] = ' '; - } - label[indent] = '\0'; - BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s", IFACE_(input->name)); + row = uiLayoutRow(layout, true); + /* Decorations are added manually here. */ + uiLayoutSetPropDecorate(row, false); - /* split in label and value */ - split = uiLayoutSplit(layout, 0.5f, false); + uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(row); + /* Empty decorator item for alignment. */ + bool add_dummy_decorator = false; - row = uiLayoutRow(split, true); + { + uiLayout *sub = uiLayoutRow(split_wrapper.label_column, true); - if (depth > 0) { - UI_block_emboss_set(block, UI_EMBOSS_NONE); + if (depth > 0) { + UI_block_emboss_set(block, UI_EMBOSS_NONE); - if (lnode && - (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) { - int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : - ICON_DISCLOSURE_TRI_DOWN; - uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); - } - else { - uiItemL(row, "", ICON_BLANK1); - } + if (lnode && + (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) { + int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : + ICON_DISCLOSURE_TRI_DOWN; + uiItemR(sub, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); + } - bt = block->buttons.last; - bt->rect.xmax = UI_UNIT_X / 2; + UI_block_emboss_set(block, UI_EMBOSS); + } - UI_block_emboss_set(block, UI_EMBOSS); + sub = uiLayoutRow(sub, true); + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT); + uiItemL(sub, IFACE_(input->name), ICON_NONE); } - uiItemL(row, label, ICON_NONE); - bt = block->buttons.last; - bt->drawflag = UI_BUT_TEXT_RIGHT; - if (dependency_loop) { - row = uiLayoutRow(split, false); uiItemL(row, IFACE_("Dependency Loop"), ICON_ERROR); + add_dummy_decorator = true; } else if (lnode) { /* input linked to a node */ - uiTemplateNodeLink(split, ntree, node, input); + uiTemplateNodeLink(row, C, ntree, node, input); + add_dummy_decorator = true; if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) { if (depth == 0) { @@ -809,33 +805,41 @@ static void ui_node_draw_input( } } else { + row = uiLayoutRow(row, true); + + uiTemplateNodeLink(row, C, ntree, node, input); + + if (input->flag & SOCK_HIDE_VALUE) { + add_dummy_decorator = true; + } /* input not linked, show value */ - if (!(input->flag & SOCK_HIDE_VALUE)) { + else { + uiLayout *sub = row; + switch (input->type) { + case SOCK_VECTOR: + if (input->type == SOCK_VECTOR) { + uiItemS(row); + sub = uiLayoutColumn(row, true); + } + ATTR_FALLTHROUGH; case SOCK_FLOAT: case SOCK_INT: case SOCK_BOOLEAN: case SOCK_RGBA: case SOCK_STRING: - row = uiLayoutRow(split, true); - uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE); - break; - case SOCK_VECTOR: - row = uiLayoutRow(split, false); - col = uiLayoutColumn(row, false); - uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE); + uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE); + uiItemDecoratorR( + split_wrapper.decorate_column, &inputptr, "default_value", RNA_NO_INDEX); break; - default: - row = uiLayoutRow(split, false); - break; + add_dummy_decorator = true; } } - else { - row = uiLayoutRow(split, false); - } + } - uiTemplateNodeLink(row, ntree, node, input); + if (add_dummy_decorator) { + uiItemDecoratorR(split_wrapper.decorate_column, NULL, NULL, 0); } /* clear */ diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 5bdca04856b..740d090e641 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -141,7 +141,7 @@ static int node_view_all_exec(bContext *C, wmOperator *op) void NODE_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "NODE_OT_view_all"; ot->description = "Resize view so you can see all nodes"; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 9df04c097bb..f339d11b842 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -936,6 +936,11 @@ static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, bool free; const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free); for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) { +#ifndef WITH_NEW_SIMULATION_TYPE + if (STREQ(item_iter->identifier, "SimulationNodeTree")) { + continue; + } +#endif RNA_enum_item_add(item, totitem, item_iter); } if (free) { diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index c77ee67b859..82ff9e06194 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -300,19 +300,15 @@ static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *c return TRAVERSE_CONTINUE; } -static int collection_delete_exec(bContext *C, wmOperator *op) +void outliner_collection_delete( + bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool hierarchy) { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *basact_prev = BASACT(view_layer); SpaceOutliner *soops = CTX_wm_space_outliner(C); + struct CollectionEditData data = { .scene = scene, .soops = soops, }; - bool hierarchy = RNA_boolean_get(op->ptr, "hierarchy"); data.collections_to_edit = BLI_gset_ptr_new(__func__); @@ -358,7 +354,7 @@ static int collection_delete_exec(bContext *C, wmOperator *op) } else { BKE_reportf( - op->reports, + reports, RPT_WARNING, "Cannot delete linked collection '%s', it is used by other linked scenes/collections", collection->id.name + 2); @@ -367,6 +363,17 @@ static int collection_delete_exec(bContext *C, wmOperator *op) } BLI_gset_free(data.collections_to_edit, NULL); +} + +static int collection_hierarchy_delete_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + const Base *basact_prev = BASACT(view_layer); + + outliner_collection_delete(C, bmain, scene, op->reports, true); DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); @@ -382,24 +389,19 @@ static int collection_delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void OUTLINER_OT_collection_delete(wmOperatorType *ot) +void OUTLINER_OT_collection_hierarchy_delete(wmOperatorType *ot) { /* identifiers */ - ot->name = "Delete Collection"; - ot->idname = "OUTLINER_OT_collection_delete"; - ot->description = "Delete selected collections"; + ot->name = "Delete Hierarchy"; + ot->idname = "OUTLINER_OT_collection_hierarchy_delete"; + ot->description = "Delete selected collection hierarchies"; /* api callbacks */ - ot->exec = collection_delete_exec; + ot->exec = collection_hierarchy_delete_exec; ot->poll = ED_outliner_collections_editor_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - PropertyRNA *prop = RNA_def_boolean( - ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index ce83cfc3c97..6eba41982a7 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2581,6 +2581,10 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case ID_PC: data.icon = ICON_CURVE_BEZCURVE; break; + case ID_SIM: + /* TODO: Use correct icon. */ + data.icon = ICON_PHYSICS; + break; default: break; } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 469a0065e3a..8b4e38a77fd 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -83,9 +83,11 @@ #include "outliner_intern.h" -/* ************************************************************** */ +/** \} */ -/* Highlight --------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Highlight on Cursor Motion Operator + * \{ */ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { @@ -140,7 +142,11 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* Toggle Open/Closed ------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Open/Closed Operator + * \{ */ /* Open or close a tree element, optionally toggling all children recursively */ void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all) @@ -262,8 +268,10 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items"); } +/** \} */ + /* -------------------------------------------------------------------- */ -/** \name Object Mode Enter/Exit +/** \name Object Mode Enter/Exit Utilities * \{ */ static void item_object_mode_enter_exit(bContext *C, ReportList *reports, Object *ob, bool enter) @@ -317,7 +325,9 @@ void item_object_mode_exit_cb(bContext *C, /** \} */ -/* Rename --------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Rename Operator + * \{ */ static void do_item_rename(ARegion *region, TreeElement *te, @@ -449,7 +459,11 @@ void OUTLINER_OT_item_rename(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* ID delete --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Delete Operator + * \{ */ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem) { @@ -563,7 +577,11 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* ID remap --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Remap Operator + * \{ */ static int outliner_id_remap_exec(bContext *C, wmOperator *op) { @@ -736,7 +754,11 @@ void id_remap_cb(bContext *C, WM_operator_properties_free(&op_props); } -/* ID copy/Paste ------------------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Copy Operator + * \{ */ static int outliner_id_copy_tag(SpaceOutliner *soops, ListBase *tree) { @@ -801,6 +823,12 @@ void OUTLINER_OT_id_copy(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Paste Operator + * \{ */ + static int outliner_id_paste_exec(bContext *C, wmOperator *op) { char str[FILE_MAX]; @@ -835,7 +863,11 @@ void OUTLINER_OT_id_paste(wmOperatorType *ot) ot->flag = 0; } -/* Library relocate/reload --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Library Relocate Operator + * \{ */ static int lib_relocate( bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload) @@ -979,6 +1011,12 @@ static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent return OPERATOR_CANCELLED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Library Reload Operator + * \{ */ + void OUTLINER_OT_lib_reload(wmOperatorType *ot) { ot->name = "Reload Library"; @@ -1002,13 +1040,11 @@ void lib_reload_cb(bContext *C, lib_relocate(C, te, tselem, ot, true); } -/* ************************************************************** */ -/* Setting Toggling Operators */ - -/* =============================================== */ -/* Toggling Utilities (Exported) */ +/** \} */ -/* Apply Settings ------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Apply Settings Utilities + * \{ */ static int outliner_count_levels(ListBase *lb, const int curlevel) { @@ -1090,7 +1126,11 @@ bool outliner_flag_flip(ListBase *lb, short flag) return changed; } -/* Restriction Columns ------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Restriction Column Utility + * \{ */ /* same check needed for both object operation and restrict column button func * return 0 when in edit mode (cannot restrict view or select) @@ -1116,10 +1156,11 @@ int common_restrict_check(bContext *C, Object *ob) return 1; } -/* =============================================== */ -/* Outliner setting toggles */ +/** \} */ -/* Toggle Expanded (Outliner) ---------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Toggle Expanded (Outliner) Operator + * \{ */ static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1152,7 +1193,11 @@ void OUTLINER_OT_expanded_toggle(wmOperatorType *ot) /* no undo or registry, UI option */ } -/* Toggle Selected (Outliner) ---------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Selected (Outliner) Operator + * \{ */ static int outliner_select_all_exec(bContext *C, wmOperator *op) { @@ -1202,10 +1247,11 @@ void OUTLINER_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } -/* ************************************************************** */ -/* Hotkey Only Operators */ +/** \} */ -/* Show Active --------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name View Show Active (Outliner) Operator + * \{ */ static void outliner_set_coordinates_element_recursive(SpaceOutliner *soops, TreeElement *te, @@ -1355,7 +1401,11 @@ void OUTLINER_OT_show_active(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* View Panning --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Panning (Outliner) Operator + * \{ */ static int outliner_scroll_page_exec(bContext *C, wmOperator *op) { @@ -1393,10 +1443,14 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* Search ------------------------------------------------------- */ -// TODO: probably obsolete now with filtering? +/** \} */ + +#if 0 // TODO: probably obsolete now with filtering? + +/* -------------------------------------------------------------------- */ +/** \name Search + * \{ */ -#if 0 /* find next element that has this name */ static TreeElement *outliner_find_name( @@ -1509,9 +1563,14 @@ static void outliner_find_panel( BKE_reportf(reports, RPT_WARNING, "Not found: %s", name); } } -#endif -/* Show One Level ----------------------------------------------- */ +/** \} */ + +#endif /* if 0 */ + +/* -------------------------------------------------------------------- */ +/** \name Show One Level Operator + * \{ */ /* helper function for Show/Hide one level operator */ static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int open) @@ -1584,7 +1643,11 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* Show Hierarchy ----------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Show Hierarchy Operator + * \{ */ /* Helper function for tree_element_shwo_hierarchy() - * recursively checks whether subtrees have any objects. */ @@ -1676,11 +1739,15 @@ void OUTLINER_OT_show_hierarchy(wmOperatorType *ot) /* no undo or registry, UI option */ } -/* ************************************************************** */ -/* ANIMATO OPERATIONS */ -/* KeyingSet and Driver Creation - Helper functions */ +/** \} */ -/* specialized poll callback for these operators to work in Datablocks view only */ +/* -------------------------------------------------------------------- */ +/** \name Animation Internal Utilities + * \{ */ + +/** + * Specialized poll callback for these operators to work in data-blocks view only. + */ static bool ed_operator_outliner_datablocks_active(bContext *C) { ScrArea *area = CTX_wm_area(C); @@ -1842,19 +1909,23 @@ static void tree_element_to_path(TreeElement *te, BLI_freelistN(&hierarchy); } -/* =============================================== */ -/* Driver Operations */ +/** \} */ -/* These operators are only available in databrowser mode for now, as - * they depend on having RNA paths and/or hierarchies available. +/* -------------------------------------------------------------------- */ +/** \name Driver Internal Utilities + * \{ */ + +/** + * Driver Operations + * + * These operators are only available in data-browser mode for now, + * as they depend on having RNA paths and/or hierarchies available. */ enum { DRIVERS_EDITMODE_ADD = 0, DRIVERS_EDITMODE_REMOVE, } /*eDrivers_EditModes*/; -/* Utilities ---------------------------------- */ - /* Recursively iterate over tree, finding and working on selected items */ static void do_outliner_drivers_editop(SpaceOutliner *soops, ListBase *tree, @@ -1930,7 +2001,11 @@ static void do_outliner_drivers_editop(SpaceOutliner *soops, } } -/* Add Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Add Operator + * \{ */ static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op) { @@ -1965,7 +2040,11 @@ void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* Remove Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Remove Operator + * \{ */ static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op) { @@ -2000,10 +2079,16 @@ void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* =============================================== */ -/* Keying Set Operations */ +/** \} */ -/* These operators are only available in databrowser mode for now, as +/* -------------------------------------------------------------------- */ +/** \name Keying-Set Internal Utilities + * \{ */ + +/** + * Keying-Set Operations + * + * These operators are only available in data-browser mode for now, as * they depend on having RNA paths and/or hierarchies available. */ enum { @@ -2011,8 +2096,6 @@ enum { KEYINGSET_EDITMODE_REMOVE, } /*eKeyingSet_EditModes*/; -/* Utilities ---------------------------------- */ - /* find the 'active' KeyingSet, and add if not found (if adding is allowed) */ // TODO: should this be an API func? static KeyingSet *verify_active_keyingset(Scene *scene, short add) @@ -2104,7 +2187,11 @@ static void do_outliner_keyingset_editop(SpaceOutliner *soops, } } -/* Add Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Keying-Set Add Operator + * \{ */ static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op) { @@ -2145,7 +2232,11 @@ void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* Remove Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Keying-Set Remove Operator + * \{ */ static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2182,8 +2273,11 @@ void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ************************************************************** */ -/* ORPHANED DATABLOCKS */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Purge Orphan Data-Blocks Operator + * \{ */ static bool ed_operator_outliner_id_orphans_active(bContext *C) { @@ -2195,7 +2289,7 @@ static bool ed_operator_outliner_id_orphans_active(bContext *C) return true; } -/* Purge Orphans Operator --------------------------------------- */ +/** \} */ static void outliner_orphans_purge_tag(ID *id, int *num_tagged) { @@ -2313,3 +2407,5 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot) PropertyRNA *prop = RNA_def_int(ot->srna, "num_deleted", 0, 0, INT_MAX, "", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } + +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 90092817acc..f2b64bc2a4b 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -108,7 +108,8 @@ typedef struct TreeElementIcon { ID_LP, \ ID_HA, \ ID_PT, \ - ID_VO) || /* Only in 'blendfile' mode ... :/ */ \ + ID_VO, \ + ID_SIM) || /* Only in 'blendfile' mode ... :/ */ \ ELEM(GS((_id)->name), \ ID_SCR, \ ID_WM, \ @@ -430,6 +431,7 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot); void OUTLINER_OT_action_set(struct wmOperatorType *ot); void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot); void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot); +void OUTLINER_OT_delete(struct wmOperatorType *ot); /* ---------------------------------------------------------------- */ @@ -441,11 +443,16 @@ void outliner_keymap(struct wmKeyConfig *keyconf); bool outliner_is_collection_tree_element(const TreeElement *te); struct Collection *outliner_collection_from_tree_element(const TreeElement *te); +void outliner_collection_delete(struct bContext *C, + struct Main *bmain, + struct Scene *scene, + struct ReportList *reports, + bool hierarchy); void OUTLINER_OT_collection_new(struct wmOperatorType *ot); void OUTLINER_OT_collection_duplicate_linked(struct wmOperatorType *ot); void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot); -void OUTLINER_OT_collection_delete(struct wmOperatorType *ot); +void OUTLINER_OT_collection_hierarchy_delete(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot); void OUTLINER_OT_collection_link(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 9d7efc7fe46..af7d97b6950 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -66,6 +66,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_action_set); WM_operatortype_append(OUTLINER_OT_constraint_operation); WM_operatortype_append(OUTLINER_OT_modifier_operation); + WM_operatortype_append(OUTLINER_OT_delete); WM_operatortype_append(OUTLINER_OT_show_one_level); WM_operatortype_append(OUTLINER_OT_show_active); @@ -93,7 +94,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_collection_new); WM_operatortype_append(OUTLINER_OT_collection_duplicate_linked); WM_operatortype_append(OUTLINER_OT_collection_duplicate); - WM_operatortype_append(OUTLINER_OT_collection_delete); + WM_operatortype_append(OUTLINER_OT_collection_hierarchy_delete); WM_operatortype_append(OUTLINER_OT_collection_objects_select); WM_operatortype_append(OUTLINER_OT_collection_objects_deselect); WM_operatortype_append(OUTLINER_OT_collection_link); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 1c9998d256b..0ccf982fd29 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -39,6 +39,7 @@ #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_volume_types.h" #include "DNA_world_types.h" @@ -88,9 +89,9 @@ #include "outliner_intern.h" -/* ****************************************************** */ - -/* ************ SELECTION OPERATIONS ********* */ +/* -------------------------------------------------------------------- */ +/** \name ID/Library/Data Set/Un-link Utilities + * \{ */ static void set_operation_types(SpaceOutliner *soops, ListBase *lb, @@ -160,6 +161,7 @@ static void set_operation_types(SpaceOutliner *soops, case ID_HA: case ID_PT: case ID_VO: + case ID_SIM: is_standard_id = true; break; case ID_WM: @@ -412,7 +414,12 @@ static void outliner_do_libdata_operation(bContext *C, } } -/* ******************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Scene Menu Operator + * \{ */ + typedef enum eOutliner_PropSceneOps { OL_SCENE_OP_DELETE = 1, } eOutliner_PropSceneOps; @@ -500,7 +507,12 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_scene_op_types, 0, "Scene Operation", ""); } -/* ******************************************** */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Search Utilities + * \{ */ /** * Stores the parent and a child element of a merged icon-row icon for @@ -541,10 +553,10 @@ static void merged_element_search_cb_recursive( } /* Get a list of elements that match the search string */ -static void merged_element_search_cb(const bContext *UNUSED(C), - void *data, - const char *str, - uiSearchItems *items) +static void merged_element_search_update_fn(const bContext *UNUSED(C), + void *data, + const char *str, + uiSearchItems *items) { MergedSearchData *search_data = (MergedSearchData *)data; TreeElement *parent = search_data->parent_element; @@ -556,7 +568,7 @@ static void merged_element_search_cb(const bContext *UNUSED(C), } /* Activate an element from the merged element search menu */ -static void merged_element_search_call_cb(struct bContext *C, void *UNUSED(arg1), void *element) +static void merged_element_search_exec_fn(struct bContext *C, void *UNUSED(arg1), void *element) { SpaceOutliner *soops = CTX_wm_space_outliner(C); TreeElement *te = (TreeElement *)element; @@ -588,7 +600,7 @@ static uiBlock *merged_element_search_menu(bContext *C, ARegion *region, void *d but = uiDefSearchBut( block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, menu_width, UI_UNIT_Y, 0, 0, ""); UI_but_func_search_set( - but, NULL, merged_element_search_cb, data, NULL, merged_element_search_call_cb, NULL, NULL); + but, NULL, merged_element_search_update_fn, data, NULL, merged_element_search_exec_fn, NULL); UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); /* Fake button to hold space for search items */ @@ -641,6 +653,12 @@ static void object_select_cb(bContext *C, } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Callbacks (Selection, Users & Library) Utilities + * \{ */ + static void object_select_hierarchy_cb(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), @@ -671,13 +689,10 @@ static void object_deselect_cb(bContext *C, } } -static void object_delete_cb(bContext *C, - ReportList *reports, - Scene *scene, - TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, - void *UNUSED(user_data)) +static void outliner_object_delete(bContext *C, + ReportList *reports, + Scene *scene, + TreeStoreElem *tselem) { Object *ob = (Object *)tselem->id; if (ob) { @@ -883,7 +898,11 @@ void outliner_do_object_operation(bContext *C, outliner_do_object_operation_ex(C, reports, scene_act, soops, lb, operation_cb, NULL, true); } -/* ******************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Tagging Utilities + * \{ */ static void clear_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te), @@ -935,7 +954,11 @@ static void refreshdrivers_animdata_cb(int UNUSED(event), } } -/* --------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Operation Utilities + * \{ */ typedef enum eOutliner_PropDataOps { OL_DOP_SELECT = 1, @@ -1308,13 +1331,16 @@ static void object_batch_delete_hierarchy_cb(bContext *C, } } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Menu Operator + * \{ */ enum { OL_OP_SELECT = 1, OL_OP_DESELECT, OL_OP_SELECT_HIERARCHY, - OL_OP_DELETE, OL_OP_DELETE_HIERARCHY, OL_OP_REMAP, OL_OP_LOCALIZED, /* disabled, see below */ @@ -1330,7 +1356,6 @@ static const EnumPropertyItem prop_object_op_types[] = { {OL_OP_SELECT, "SELECT", ICON_RESTRICT_SELECT_OFF, "Select", ""}, {OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""}, {OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""}, - {OL_OP_DELETE, "DELETE", ICON_X, "Delete", ""}, {OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""}, {OL_OP_REMAP, "REMAP", @@ -1386,29 +1411,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) str = "Deselect Objects"; selection_changed = true; } - else if (event == OL_OP_DELETE) { - ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *basact_prev = BASACT(view_layer); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_delete_cb); - - /* XXX: tree management normally happens from draw_outliner(), but when - * you're clicking to fast on Delete object from context menu in - * outliner several mouse events can be handled in one cycle without - * handling notifiers/redraw which leads to deleting the same object twice. - * cleanup tree here to prevent such cases. */ - outliner_cleanup_tree(soops); - - DEG_relations_tag_update(bmain); - str = "Delete Objects"; - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - if (basact_prev != BASACT(view_layer)) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active); - } - selection_changed = true; - } else if (event == OL_OP_DELETE_HIERARCHY) { ViewLayer *view_layer = CTX_data_view_layer(C); const Base *basact_prev = BASACT(view_layer); @@ -1433,7 +1435,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) BKE_id_multi_tagged_delete(bmain); } - /* XXX: See OL_OP_DELETE comment above. */ + /* XXX: See outliner_delete_exec comment below. */ outliner_cleanup_tree(soops); DEG_relations_tag_update(bmain); @@ -1500,7 +1502,85 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", ""); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Object/Collection Operator + * \{ */ + +static void outliner_objects_delete( + bContext *C, Scene *scene, SpaceOutliner *soops, ReportList *reports, ListBase *lb) +{ + LISTBASE_FOREACH (TreeElement *, te, lb) { + TreeStoreElem *tselem = TREESTORE(te); + + if (tselem->flag & TSE_SELECTED) { + if (tselem->type == 0 && te->idcode == ID_OB) { + outliner_object_delete(C, reports, scene, tselem); + } + } + + if (TSELEM_OPEN(tselem, soops)) { + outliner_objects_delete(C, scene, soops, reports, &te->subtree); + } + } +} + +static int outliner_delete_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + SpaceOutliner *soops = CTX_wm_space_outliner(C); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + + ViewLayer *view_layer = CTX_data_view_layer(C); + const Base *basact_prev = BASACT(view_layer); + + outliner_collection_delete(C, bmain, scene, op->reports, false); + outliner_objects_delete(C, scene, soops, op->reports, &soops->tree); + + /* Tree management normally happens from draw_outliner(), but when + * you're clicking too fast on Delete object from context menu in + * outliner several mouse events can be handled in one cycle without + * handling notifiers/redraw which leads to deleting the same object twice. + * cleanup tree here to prevent such cases. */ + outliner_cleanup_tree(soops); + + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + + if (basact_prev != BASACT(view_layer)) { + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active); + } + + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete"; + ot->idname = "OUTLINER_OT_delete"; + ot->description = "Delete selected objects and collections"; + + /* callbacks */ + ot->exec = outliner_delete_exec; + ot->poll = ED_operator_outliner_active; + + /* flags */ + ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID-Data Menu Operator + * \{ */ typedef enum eOutlinerIdOpTypes { OUTLINER_IDOP_INVALID = 0, @@ -1800,7 +1880,11 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot) RNA_def_enum_funcs(ot->prop, outliner_id_operation_itemf); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Library Menu Operator + * \{ */ typedef enum eOutlinerLibOpTypes { OL_LIB_INVALID = 0, @@ -1901,7 +1985,11 @@ void OUTLINER_OT_lib_operation(wmOperatorType *ot) ot->srna, "type", outliner_lib_op_type_items, 0, "Library Operation", ""); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Outliner Set Active Action Operator + * \{ */ static void outliner_do_id_set_operation( SpaceOutliner *soops, @@ -1927,8 +2015,6 @@ static void outliner_do_id_set_operation( } } -/* ------------------------------------------ */ - static void actionset_id_cb(TreeElement *UNUSED(te), TreeStoreElem *tselem, TreeStoreElem *tsep, @@ -2026,7 +2112,11 @@ void OUTLINER_OT_action_set(wmOperatorType *ot) ot->prop = prop; } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Animation Menu Operator + * \{ */ typedef enum eOutliner_AnimDataOps { OUTLINER_ANIMOP_INVALID = 0, @@ -2142,7 +2232,11 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_animdata_op_types, 0, "Animation Operation", ""); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Constraint Menu Operator + * \{ */ static const EnumPropertyItem prop_constraint_op_types[] = { {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""}, @@ -2188,7 +2282,11 @@ void OUTLINER_OT_constraint_operation(wmOperatorType *ot) ot->srna, "type", prop_constraint_op_types, 0, "Constraint Operation", ""); } -/* ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Modifier Menu Operator + * \{ */ static const EnumPropertyItem prop_modifier_op_types[] = { {OL_MODIFIER_OP_TOGVIS, "TOGVIS", ICON_RESTRICT_VIEW_OFF, "Toggle viewport use", ""}, @@ -2233,7 +2331,11 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_modifier_op_types, 0, "Modifier Operation", ""); } -/* ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Data Menu Operator + * \{ */ // XXX: select linked is for RNA structs only static const EnumPropertyItem prop_data_op_types[] = { @@ -2326,7 +2428,11 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", ""); } -/* ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Context Menu Operator + * \{ */ static int outliner_operator_menu(bContext *C, const char *opname) { @@ -2491,4 +2597,4 @@ void OUTLINER_OT_operation(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* ****************************************************** */ +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index b226d291188..7bb62b0d1e2 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -46,6 +46,7 @@ #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_speaker_types.h" #include "DNA_volume_types.h" #include "DNA_world_types.h" @@ -58,7 +59,7 @@ #include "BLT_translation.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_idtype.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -773,6 +774,13 @@ static void outliner_add_id_contents(SpaceOutliner *soops, outliner_add_element(soops, &te->subtree, volume, te, TSE_ANIM_DATA, 0); break; } + case ID_SIM: { + Simulation *simulation = (Simulation *)id; + if (outliner_animdata_test(simulation->adt)) { + outliner_add_element(soops, &te->subtree, simulation, te, TSE_ANIM_DATA, 0); + } + break; + } default: break; } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index edbd52f4d53..d935f7dbb40 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2930,7 +2930,7 @@ static int sequencer_view_all_exec(bContext *C, wmOperator *op) void SEQUENCER_OT_view_all(wmOperatorType *ot) { /* Identifiers. */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "SEQUENCER_OT_view_all"; ot->description = "View all the strips in the sequencer"; @@ -3017,7 +3017,7 @@ static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op)) void SEQUENCER_OT_view_all_preview(wmOperatorType *ot) { /* Identifiers. */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "SEQUENCER_OT_view_all_preview"; ot->description = "Zoom preview to fit in the area"; diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index b06bc7ad8b7..243a6e193eb 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -447,7 +447,6 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col) typedef struct MakeHistogramViewData { const ImBuf *ibuf; - uint32_t (*bins)[HIS_STEPS]; } MakeHistogramViewData; static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata, @@ -469,17 +468,16 @@ static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata, } } -static void make_histogram_view_from_ibuf_finalize(void *__restrict userdata, - void *__restrict userdata_chunk) +static void make_histogram_view_from_ibuf_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - MakeHistogramViewData *data = userdata; - uint32_t(*bins)[HIS_STEPS] = data->bins; - - uint32_t(*cur_bins)[HIS_STEPS] = userdata_chunk; + uint32_t(*join_bins)[HIS_STEPS] = chunk_join; + uint32_t(*bins)[HIS_STEPS] = chunk; for (int j = 3; j--;) { for (int i = 0; i < HIS_STEPS; i++) { - bins[j][i] += cur_bins[j][i]; + join_bins[j][i] += bins[j][i]; } } } @@ -496,14 +494,13 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) MakeHistogramViewData data = { .ibuf = ibuf, - .bins = bins, }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; settings.userdata_chunk_size = sizeof(bins); - settings.func_finalize = make_histogram_view_from_ibuf_finalize; + settings.func_reduce = make_histogram_view_from_ibuf_reduce; BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_byte_fn, &settings); nr = nb = ng = 0; @@ -582,14 +579,13 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) MakeHistogramViewData data = { .ibuf = ibuf, - .bins = bins, }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; settings.userdata_chunk_size = sizeof(bins); - settings.func_finalize = make_histogram_view_from_ibuf_finalize; + settings.func_reduce = make_histogram_view_from_ibuf_reduce; BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_float_fn, &settings); nr = nb = ng = 0; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index e58559f4f6b..fac378ae104 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -63,6 +63,7 @@ #include "ED_armature.h" #include "ED_gpencil.h" +#include "ED_info.h" #include "ED_keyframing.h" #include "ED_screen.h" #include "ED_screen_types.h" @@ -101,6 +102,8 @@ #define M_GOLDEN_RATIO_CONJUGATE 0.618033988749895f +#define VIEW3D_OVERLAY_LINEHEIGHT (0.9f * U.widget_unit) + /* -------------------------------------------------------------------- */ /** \name General Functions * \{ */ @@ -1341,7 +1344,7 @@ static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *y UI_FontThemeColor(BLF_default(), TH_TEXT_HI); - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); @@ -1473,7 +1476,7 @@ static void draw_selected_name( BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); BLF_shadow_offset(font_id, 1, -1); - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); BLF_disable(font_id, BLF_SHADOW); @@ -1494,7 +1497,7 @@ static void draw_grid_unit_name( BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); } - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; BLF_enable(font_id, BLF_SHADOW); BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); BLF_shadow_offset(font_id, 1, -1); @@ -1515,6 +1518,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); #ifdef WITH_INPUT_NDOF if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) && @@ -1550,8 +1555,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) } } - int xoffset = rect->xmin + U.widget_unit; - int yoffset = rect->ymax; + int xoffset = rect->xmin + (0.5f * U.widget_unit); + int yoffset = rect->ymax - (0.1f * U.widget_unit); if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { @@ -1562,7 +1567,6 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) } if (U.uiflag & USER_DRAWVIEWINFO) { - ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); draw_selected_name(scene, view_layer, ob, xoffset, &yoffset); } @@ -1571,10 +1575,12 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) /* draw below the viewport name */ draw_grid_unit_name(scene, rv3d, v3d, xoffset, &yoffset); } + + DRW_draw_region_engine_info(xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT); } - if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { - DRW_draw_region_engine_info(xoffset, yoffset); + if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_STATS)) { + ED_info_draw_stats(bmain, scene, view_layer, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT); } BLF_batch_draw_end(); @@ -2493,7 +2499,7 @@ void ED_scene_draw_fps(const Scene *scene, int xoffset, int *yoffset) BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); BLF_shadow_offset(font_id, 1, -1); - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; #ifdef WITH_INTERNATIONAL BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 0a30336aed8..5cdf6ce28cb 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2980,7 +2980,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) void VIEW3D_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->description = "View all objects in scene"; ot->idname = "VIEW3D_OT_view_all"; @@ -5372,6 +5372,7 @@ void VIEW3D_OT_toggle_xray(wmOperatorType *ot) /* identifiers */ ot->name = "Toggle X-Ray"; ot->idname = "VIEW3D_OT_toggle_xray"; + ot->description = "Transparent scene display. Allow selecting through items"; /* api callbacks */ ot->exec = toggle_xray_exec; diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index d8e1c8c1c72..08e68c9174e 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -388,7 +388,7 @@ void mesh_foreachScreenFace( BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE); - if (modifiers_usesSubsurfFacedots(vc->scene, vc->obedit)) { + if (BKE_modifiers_uses_subsurf_facedots(vc->scene, vc->obedit)) { BKE_mesh_foreach_mapped_subdiv_face_center( me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP); } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 67c61b4ecac..2ce2edb98fe 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -408,8 +408,8 @@ typedef struct LassoSelectUserData { const rcti *rect; const rctf *rect_fl; rctf _rect_fl; - const int (*mcords)[2]; - int moves; + const int (*mcoords)[2]; + int mcoords_len; eSelectOp sel_op; /* runtime */ @@ -421,8 +421,8 @@ typedef struct LassoSelectUserData { static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, ViewContext *vc, const rcti *rect, - const int (*mcords)[2], - const int moves, + const int (*mcoords)[2], + const int mcoords_len, const eSelectOp sel_op) { r_data->vc = vc; @@ -431,8 +431,8 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, r_data->rect_fl = &r_data->_rect_fl; BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); - r_data->mcords = mcords; - r_data->moves = moves; + r_data->mcoords = mcoords; + r_data->mcoords_len = mcoords_len; r_data->sel_op = sel_op; /* runtime */ @@ -527,7 +527,8 @@ static void do_lasso_select_pose__do_tag(void *userData, if (screen_co_a[0] != IS_CLIPPED) { points_proj_tot++; if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { is_point_done = true; } } @@ -536,22 +537,28 @@ static void do_lasso_select_pose__do_tag(void *userData, if (screen_co_b[0] != IS_CLIPPED) { points_proj_tot++; if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { is_point_done = true; } } /* if one of points selected, we skip the bone itself */ - if ((is_point_done == true) || - ((is_point_done == false) && (points_proj_tot == 2) && - BLI_lasso_is_edge_inside( - data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX))) { + if ((is_point_done == true) || ((is_point_done == false) && (points_proj_tot == 2) && + BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + INT_MAX))) { pchan->bone->flag |= BONE_DONE; } data->is_changed |= is_point_done; } } -static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves) +static void do_lasso_tag_pose(ViewContext *vc, + Object *ob, + const int mcoords[][2], + const int mcoords_len) { ViewContext vc_tmp; LassoSelectUserData data; @@ -564,9 +571,9 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2] vc_tmp = *vc; vc_tmp.obact = ob; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, 0); ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); @@ -574,8 +581,8 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2] } static bool do_lasso_select_objects(ViewContext *vc, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { View3D *v3d = vc->v3d; @@ -591,7 +598,7 @@ static bool do_lasso_select_objects(ViewContext *vc, const bool is_select = base->flag & BASE_SELECTED; const bool is_inside = ((ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) && BLI_lasso_is_point_inside( - mcords, moves, base->sx, base->sy, IS_CLIPPED)); + mcoords, mcoords_len, base->sx, base->sy, IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT); @@ -685,8 +692,8 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const } static bool do_lasso_select_pose(ViewContext *vc, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { uint bases_len; @@ -695,7 +702,7 @@ static bool do_lasso_select_pose(ViewContext *vc, for (int i = 0; i < bases_len; i++) { Base *base_iter = bases[i]; Object *ob_iter = base_iter->object; - do_lasso_tag_pose(vc, ob_iter, mcords, moves); + do_lasso_tag_pose(vc, ob_iter, mcoords, mcoords_len); } const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); @@ -715,9 +722,10 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, { LassoSelectUserData *data = userData; const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_vert_select_set(data->vc->em->bm, eve, sel_op_result); @@ -746,8 +754,10 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED)); + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), IS_CLIPPED) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); @@ -770,8 +780,8 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, } const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords, - data->moves, + const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED)); @@ -789,9 +799,10 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, { LassoSelectUserData *data = userData; const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_face_select_set(data->vc->em->bm, efa, sel_op_result); @@ -801,8 +812,8 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, static bool do_lasso_select_mesh(ViewContext *vc, wmGenericUserData *wm_userdata, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; @@ -812,9 +823,9 @@ static bool do_lasso_select_mesh(ViewContext *vc, /* set editmesh */ vc->em = BKE_editmesh_from_object(vc->obedit); - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -836,7 +847,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); esel = wm_userdata->data; esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); } } @@ -897,7 +908,7 @@ static void do_lasso_select_curve__doSelect(void *userData, LassoSelectUserData *data = userData; const bool is_inside = BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED); + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED); if (bp) { const bool is_select = bp->f1 & SELECT; const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -930,16 +941,16 @@ static void do_lasso_select_curve__doSelect(void *userData, } static bool do_lasso_select_curve(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { Curve *curve = (Curve *)vc->obedit->data; @@ -958,9 +969,10 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const { LassoSelectUserData *data = userData; const bool is_select = bp->f1 & SELECT; - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); @@ -968,16 +980,16 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const } } static bool do_lasso_select_lattice(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); @@ -1002,7 +1014,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData, if (screen_co_a[0] != IS_CLIPPED) { if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { is_inside_flag |= BONESEL_ROOT; } } @@ -1012,7 +1025,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData, if (screen_co_b[0] != IS_CLIPPED) { if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { is_inside_flag |= BONESEL_TIP; } } @@ -1022,8 +1036,11 @@ static void do_lasso_select_armature__doSelectBone(void *userData, if (is_ignore_flag == 0) { if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) || - BLI_lasso_is_edge_inside( - data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) { + BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + INT_MAX)) { is_inside_flag |= BONESEL_BONE; } } @@ -1033,16 +1050,16 @@ static void do_lasso_select_armature__doSelectBone(void *userData, } static bool do_lasso_select_armature(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); @@ -1071,9 +1088,10 @@ static void do_lasso_select_mball__doSelectElem(void *userData, { LassoSelectUserData *data = userData; const bool is_select = ml->flag & SELECT; - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], INT_MAX)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT); @@ -1081,8 +1099,8 @@ static void do_lasso_select_mball__doSelectElem(void *userData, } } static bool do_lasso_select_meta(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; @@ -1090,9 +1108,9 @@ static bool do_lasso_select_meta(ViewContext *vc, MetaBall *mb = (MetaBall *)vc->obedit->data; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= BKE_mball_deselect_all(mb); @@ -1113,9 +1131,10 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, { LassoSelectUserData *data = userData; const bool is_select = mv->flag & SELECT; - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); @@ -1124,8 +1143,8 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, } static bool do_lasso_select_paintvert(ViewContext *vc, wmGenericUserData *wm_userdata, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { const bool use_zbuf = !XRAY_ENABLED(vc->v3d); @@ -1143,7 +1162,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); } - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); struct EditSelectBuf_Cache *esel = wm_userdata->data; if (use_zbuf) { @@ -1151,7 +1170,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); esel = wm_userdata->data; esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); } } @@ -1163,7 +1182,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, else { LassoSelectUserData data; - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); @@ -1185,8 +1204,8 @@ static bool do_lasso_select_paintvert(ViewContext *vc, } static bool do_lasso_select_paintface(ViewContext *vc, wmGenericUserData *wm_userdata, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { Object *ob = vc->obact; @@ -1203,14 +1222,14 @@ static bool do_lasso_select_paintface(ViewContext *vc, changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); struct EditSelectBuf_Cache *esel = wm_userdata->data; if (esel == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); esel = wm_userdata->data; esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); } if (esel->select_bitmap) { @@ -1224,7 +1243,7 @@ static bool do_lasso_select_paintface(ViewContext *vc, } #if 0 -static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op) +static void do_lasso_select_node(int mcoords[][2], const int mcoords_len, const eSelectOp sel_op) { SpaceNode *snode = area->spacedata.first; @@ -1234,7 +1253,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s float node_centf[2]; bool changed = false; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* store selection in temp test flag */ for (node = snode->edittree->nodes.first; node; node = node->next) { @@ -1244,7 +1263,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent); const bool is_select = node->flag & SELECT; const bool is_inside = (BLI_rcti_isect_pt_v(&rect, node_cent) && - BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])); + BLI_lasso_is_point_inside(mcoords, mcoords_len, node_cent[0], node_cent[1])); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT); @@ -1257,8 +1276,11 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s } #endif -static bool view3d_lasso_select( - bContext *C, ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool view3d_lasso_select(bContext *C, + ViewContext *vc, + const int mcoords[][2], + const int mcoords_len, + const eSelectOp sel_op) { Object *ob = CTX_data_active_object(C); bool changed_multi = false; @@ -1268,26 +1290,26 @@ static bool view3d_lasso_select( if (vc->obedit == NULL) { /* Object Mode */ if (BKE_paint_select_face_test(ob)) { - changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcoords, mcoords_len, sel_op); } else if (BKE_paint_select_vert_test(ob)) { - changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcoords, mcoords_len, sel_op); } else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { /* pass */ } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - changed_multi |= PE_lasso_select(C, mcords, moves, sel_op); + changed_multi |= PE_lasso_select(C, mcoords, mcoords_len, sel_op); } else if (ob && (ob->mode & OB_MODE_POSE)) { - changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_pose(vc, mcoords, mcoords_len, sel_op); if (changed_multi) { ED_outliner_select_sync_from_pose_bone_tag(C); } } else { - changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op); if (changed_multi) { ED_outliner_select_sync_from_object_tag(C); } @@ -1300,23 +1322,23 @@ static bool view3d_lasso_select( switch (vc->obedit->type) { case OB_MESH: - changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op); + changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op); break; case OB_CURVE: case OB_SURF: - changed = do_lasso_select_curve(vc, mcords, moves, sel_op); + changed = do_lasso_select_curve(vc, mcoords, mcoords_len, sel_op); break; case OB_LATTICE: - changed = do_lasso_select_lattice(vc, mcords, moves, sel_op); + changed = do_lasso_select_lattice(vc, mcoords, mcoords_len, sel_op); break; case OB_ARMATURE: - changed = do_lasso_select_armature(vc, mcords, moves, sel_op); + changed = do_lasso_select_armature(vc, mcoords, mcoords_len, sel_op); if (changed) { ED_outliner_select_sync_from_edit_bone_tag(C); } break; case OB_MBALL: - changed = do_lasso_select_meta(vc, mcords, moves, sel_op); + changed = do_lasso_select_meta(vc, mcoords, mcoords_len, sel_op); break; default: BLI_assert(!"lasso select on incorrect object type"); @@ -1342,10 +1364,10 @@ static bool view3d_lasso_select( static int view3d_lasso_select_exec(bContext *C, wmOperator *op) { ViewContext vc; - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); view3d_operator_needs_opengl(C); BKE_object_update_select_id(CTX_data_main(C)); @@ -1354,9 +1376,9 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) ED_view3d_viewcontext_init(C, &vc, depsgraph); eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op); + bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); if (changed_multi) { return OPERATOR_FINISHED; @@ -1982,7 +2004,7 @@ static bool ed_object_select_pick(bContext *C, /* setup view context for argument to callbacks */ ED_view3d_viewcontext_init(C, &vc, depsgraph); - ARegion *region = CTX_wm_region(C); + const ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index b90f7aa870e..fe77ca05a04 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1062,7 +1062,7 @@ int view3d_opengl_select(ViewContext *vc, * the number of items is nearly always 1, maybe 2..3 in rare cases. */ LinkNode *ob_pose_list = NULL; VirtualModifierData virtualModifierData; - const ModifierData *md = modifiers_getVirtualModifierList(obact, &virtualModifierData); + const ModifierData *md = BKE_modifiers_get_virtual_modifierlist(obact, &virtualModifierData); for (; md; md = md->next) { if (md->type == eModifierType_Armature) { ArmatureModifierData *amd = (ArmatureModifierData *)md; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d376c71d867..8e3ad55bae1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -778,9 +778,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) return keymap; } -static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cmode, bool is_plane) +static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is_plane) { if (!(t->flag & T_NO_CONSTRAINT)) { + char cmode = constraintModeToChar(t); int constraint_axis, constraint_plane; const bool edit_2d = (t->flag & T_2D_EDIT) != 0; const char *msg1 = "", *msg2 = "", *msg3 = ""; @@ -824,34 +825,22 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm } } else if (!edit_2d) { - if (cmode != axis) { - /* First press, constraint to an axis. */ - t->orientation.index = 0; - const short *orientation_ptr = t->orientation.types[t->orientation.index]; - const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; - if (is_plane == false) { - setUserConstraint(t, orientation, constraint_axis, msg2); - } - else { - setUserConstraint(t, orientation, constraint_plane, msg3); - } - } - else { + if (t->orientation.index == 0 || ELEM(cmode, '\0', axis)) { /* Successive presses on existing axis, cycle orientation modes. */ t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types); + initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]); + } - if (t->orientation.index == 0) { - stopConstraint(t); + if (t->orientation.index == 0) { + stopConstraint(t); + } + else { + const short orientation = t->orientation.types[t->orientation.index]; + if (is_plane == false) { + setUserConstraint(t, orientation, constraint_axis, msg2); } else { - const short *orientation_ptr = t->orientation.types[t->orientation.index]; - const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; - if (is_plane == false) { - setUserConstraint(t, orientation, constraint_axis, msg2); - } - else { - setUserConstraint(t, orientation, constraint_plane, msg3); - } + setUserConstraint(t, orientation, constraint_plane, msg3); } } } @@ -861,7 +850,6 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm int transformEvent(TransInfo *t, const wmEvent *event) { - char cmode = constraintModeToChar(t); bool handled = false; const int modifiers_prev = t->modifiers; const int mode_prev = t->mode; @@ -1047,42 +1035,42 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_AXIS_X: if (!(t->flag & T_NO_CONSTRAINT)) { - transform_event_xyz_constraint(t, EVT_XKEY, cmode, false); + transform_event_xyz_constraint(t, EVT_XKEY, false); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_AXIS_Y: if ((t->flag & T_NO_CONSTRAINT) == 0) { - transform_event_xyz_constraint(t, EVT_YKEY, cmode, false); + transform_event_xyz_constraint(t, EVT_YKEY, false); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_AXIS_Z: if ((t->flag & (T_NO_CONSTRAINT)) == 0) { - transform_event_xyz_constraint(t, EVT_ZKEY, cmode, false); + transform_event_xyz_constraint(t, EVT_ZKEY, false); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_PLANE_X: if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_XKEY, cmode, true); + transform_event_xyz_constraint(t, EVT_XKEY, true); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_PLANE_Y: if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_YKEY, cmode, true); + transform_event_xyz_constraint(t, EVT_YKEY, true); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_PLANE_Z: if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_ZKEY, cmode, true); + transform_event_xyz_constraint(t, EVT_ZKEY, true); t->redraw |= TREDRAW_HARD; handled = true; } @@ -1228,17 +1216,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) stopConstraint(t); } else { - if (event->shift) { - /* bit hackish... but it prevents mmb select to print the - * orientation from menu */ - float mati[3][3]; - strcpy(t->spacename, "global"); - unit_m3(mati); - initSelectConstraint(t, mati); - } - else { - initSelectConstraint(t, t->spacemtx); - } + initSelectConstraint(t, event->shift); postSelectConstraint(t); } } @@ -1699,18 +1677,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) ts->prop_mode = t->prop_mode; } } - - if (t->spacetype == SPACE_VIEW3D) { - if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && - !RNA_property_is_set(op->ptr, prop) && - (t->orientation.user != V3D_ORIENT_CUSTOM_MATRIX)) { - TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; - orient_slot->type = t->orientation.user; - BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) || - (BKE_scene_transform_orientation_get_index(t->scene, t->orientation.custom) == - orient_slot->index_custom)); - } - } } if (t->flag & T_MODAL) { @@ -1737,34 +1703,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0); } - /* Orientation used for redo. */ - const bool use_orient_axis = (t->orient_matrix_is_set && - (RNA_struct_find_property(op->ptr, "orient_axis") != NULL)); - short orientation; - if (t->con.mode & CON_APPLY) { - orientation = t->con.orientation; - if (orientation == V3D_ORIENT_CUSTOM) { - const int orientation_index_custom = BKE_scene_transform_orientation_get_index( - t->scene, t->orientation.custom); - /* Maybe we need a t->con.custom_orientation? - * Seems like it would always match t->orientation.custom. */ - orientation = V3D_ORIENT_CUSTOM + orientation_index_custom; - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - } - } - else if ((t->orientation.user == V3D_ORIENT_CUSTOM_MATRIX) && - (prop = RNA_struct_find_property(op->ptr, "orient_matrix_type"))) { - orientation = RNA_property_enum_get(op->ptr, prop); - } - else if (use_orient_axis) { - /* We're not using an orientation, use the fallback. */ - orientation = t->orientation.unset; - } - else { - orientation = V3D_ORIENT_GLOBAL; - unit_m3(t->spacemtx); - } - if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { if (t->flag & T_MODAL) { if (t->con.mode & CON_APPLY) { @@ -1784,56 +1722,40 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } - if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix"))) { - if (t->flag & T_MODAL) { - if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { - if (t->flag & T_MODAL) { - RNA_enum_set(op->ptr, "orient_matrix_type", orientation); - } - } - if (t->con.mode & CON_APPLY) { - RNA_float_set_array(op->ptr, "orient_matrix", &t->con.mtx[0][0]); - } - else if (use_orient_axis) { - RNA_float_set_array(op->ptr, "orient_matrix", &t->orient_matrix[0][0]); - } - else { - RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]); - } - } - } - if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) { - /* constraint orientation can be global, even if user selects something else - * so use the orientation in the constraint if set */ + short orient_set, orient_cur; + orient_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) : -1; + orient_cur = t->orientation.types[t->orientation.index]; - /* Use 'orient_matrix' instead. */ - if (t->flag & T_MODAL) { - if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { - RNA_property_enum_set(op->ptr, prop, orientation); - } + if (!ELEM(orient_cur, orient_set, V3D_ORIENT_CUSTOM_MATRIX)) { + RNA_property_enum_set(op->ptr, prop, orient_cur); + orient_set = orient_cur; + } + + if (((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) && + !RNA_property_is_set(op->ptr, prop))) { + /* Set the first time to register on redo. */ + RNA_property_enum_set(op->ptr, prop, orient_set); + RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]); } } if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { bool constraint_axis[3] = {false, false, false}; - if (t->flag & T_MODAL) { - /* Only set if needed, so we can hide in the UI when nothing is set. - * See 'transform_poll_property'. */ - if (t->con.mode & CON_APPLY) { - if (t->con.mode & CON_AXIS0) { - constraint_axis[0] = true; - } - if (t->con.mode & CON_AXIS1) { - constraint_axis[1] = true; - } - if (t->con.mode & CON_AXIS2) { - constraint_axis[2] = true; - } + if (t->con.mode & CON_APPLY) { + if (t->con.mode & CON_AXIS0) { + constraint_axis[0] = true; } - if (ELEM(true, UNPACK3(constraint_axis))) { - RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + if (t->con.mode & CON_AXIS1) { + constraint_axis[1] = true; } + if (t->con.mode & CON_AXIS2) { + constraint_axis[2] = true; + } + RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + } + else { + RNA_property_unset(op->ptr, prop); } } @@ -1959,7 +1881,13 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve unit_m3(t->spacemtx); initTransInfo(C, t, op, event); - initTransformOrientation(C, t); + + /* Use the custom orientation when it is set. */ + short orientation = t->orientation.types[0] == V3D_ORIENT_CUSTOM_MATRIX ? + V3D_ORIENT_CUSTOM_MATRIX : + t->orientation.types[t->orientation.index]; + + initTransformOrientation(C, t, orientation); if (t->spacetype == SPACE_VIEW3D) { t->draw_handle_apply = ED_region_draw_cb_activate( @@ -2084,33 +2012,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve calculatePropRatio(t); calculateCenter(t); - /* Overwrite initial values if operator supplied a non-null vector. - * - * Run before init functions so 'values_modal_offset' can be applied on mouse input. - */ - BLI_assert(is_zero_v4(t->values_modal_offset)); - if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { - float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ - - if (RNA_property_array_check(prop)) { - RNA_float_get_array(op->ptr, "value", values); - } - else { - values[0] = RNA_float_get(op->ptr, "value"); - } - - copy_v4_v4(t->values, values); - - if (t->flag & T_MODAL) { - copy_v4_v4(t->values_modal_offset, values); - t->redraw = TREDRAW_HARD; - } - else { - copy_v4_v4(t->values, values); - t->flag |= T_INPUT_IS_VALUES_FINAL; - } - } - if (event) { /* Initialize accurate transform to settings requested by keymap. */ bool use_accurate = false; @@ -2141,38 +2042,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } /* Constraint init from operator */ - if ((t->flag & T_MODAL) || - /* For mirror operator the constraint axes are effectively the values. */ - (RNA_struct_find_property(op->ptr, "value") == NULL)) { - if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) && - RNA_property_is_set(op->ptr, prop)) { - bool constraint_axis[3]; - - RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); - - if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { - t->con.mode |= CON_APPLY; - - if (constraint_axis[0]) { - t->con.mode |= CON_AXIS0; - } - if (constraint_axis[1]) { - t->con.mode |= CON_AXIS1; - } - if (constraint_axis[2]) { - t->con.mode |= CON_AXIS2; - } - - setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); - } - } - } - else { - /* So we can adjust in non global orientation. */ - if (t->orientation.user != V3D_ORIENT_GLOBAL) { - t->con.mode |= CON_APPLY | CON_AXIS0 | CON_AXIS1 | CON_AXIS2; - setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); - } + if (t->con.mode & CON_APPLY) { + setUserConstraint(t, t->orientation.types[t->orientation.index], t->con.mode, "%s"); } /* Don't write into the values when non-modal because they are already set from operator redo diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 701e068d3fa..503e7bd4691 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -531,17 +531,12 @@ typedef struct TransInfo { bool is_launch_event_tweak; struct { - /** Orientation type when when we're not constrained. - * nearly always global except for rotate which defaults to screen-space orientation. */ - short unset; - /** Orientation to use when a key is pressed. */ - short user; - /* Used when user is global. */ - short user_alt; short index; - short *types[2]; - /* this gets used when custom_orientation is V3D_ORIENT_CUSTOM */ + short types[3]; + /* this gets used when orientation.type[x] is V3D_ORIENT_CUSTOM */ struct TransformOrientation *custom; + /* this gets used when orientation.type[0] is V3D_ORIENT_CUSTOM_MATRIX */ + float custom_matrix[3][3]; } orientation; /** backup from view3d, to restore on end. */ short gizmo_flag; @@ -566,15 +561,6 @@ typedef struct TransInfo { /** Secondary axis, shear uses this. */ int orient_axis_ortho; - /** Often this matrix has similar usage to #TransInfo.spacemtx however this - * is used to define extra axes to operate on, not necessarily a space. - * - * For example, by default rotation operates on the view (`orient_matrix[2]`), - * even when the current space isn't set to the view. */ - float orient_matrix[3][3]; - /** Don't overwrite when set by operator redo defines the orientation axis. */ - bool orient_matrix_is_set; - /** remove elements if operator is canceled. */ bool remove_on_cancel; @@ -677,6 +663,10 @@ enum { T_MODAL_CURSOR_SET = 1 << 26, T_CLNOR_REBUILD = 1 << 27, + + /* Special Aftertrans. */ + T_AUTOMERGE = 1 << 28, + T_AUTOSPLIT = 1 << 29, }; /** #TransInfo.modifiers */ @@ -922,7 +912,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot); /*********************** Transform Orientations ******************************/ -void initTransformOrientation(struct bContext *C, TransInfo *t); +void initTransformOrientation(struct bContext *C, TransInfo *t, short orientation); /* Those two fill in mat and return non-zero on success */ bool createSpaceNormal(float mat[3][3], const float normal[3]); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index cdff9fdf750..b07eb6edf5a 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -713,7 +713,10 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte break; case V3D_ORIENT_VIEW: BLI_snprintf(text, sizeof(text), ftext, TIP_("view")); - setConstraint(t, t->spacemtx, mode, text); + float mtx[3][3]; + copy_m3_m3(mtx, t->spacemtx); + negate_v3(mtx[2]); + setConstraint(t, mtx, mode, text); break; case V3D_ORIENT_CURSOR: BLI_snprintf(text, sizeof(text), ftext, TIP_("cursor")); @@ -727,7 +730,9 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte BLI_snprintf(text, sizeof(text), ftext, TIP_("custom matrix")); setConstraint(t, t->spacemtx, mode, text); break; - case V3D_ORIENT_CUSTOM: { + case V3D_ORIENT_CUSTOM: + default: { + BLI_assert(orientation >= V3D_ORIENT_CUSTOM); char orientation_str[128]; BLI_snprintf(orientation_str, sizeof(orientation_str), @@ -984,17 +989,22 @@ void getConstraintMatrix(TransInfo *t) /*------------------------- MMB Select -------------------------------*/ -void initSelectConstraint(TransInfo *t, float mtx[3][3]) +void initSelectConstraint(TransInfo *t, bool force_global) { - copy_m3_m3(t->con.mtx, mtx); - t->con.mode |= CON_APPLY; - t->con.mode |= CON_SELECT; + short orientation; + if (force_global) { + orientation = V3D_ORIENT_GLOBAL; + } + else { + if (t->orientation.index == 0) { + t->orientation.index = 1; + initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]); + } + orientation = t->orientation.types[t->orientation.index]; + } + setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, ""); setNearestAxis(t); - t->con.drawExtra = NULL; - t->con.applyVec = applyAxisConstraintVec; - t->con.applySize = applyAxisConstraintSize; - t->con.applyRot = applyAxisConstraintRot; } void selectConstraint(TransInfo *t) diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index 8938ca93ad8..c98234c83da 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -36,7 +36,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t); void startConstraint(TransInfo *t); void stopConstraint(TransInfo *t); void getConstraintMatrix(TransInfo *t); -void initSelectConstraint(TransInfo *t, float mtx[3][3]); +void initSelectConstraint(TransInfo *t, bool force_global); void selectConstraint(TransInfo *t); void postSelectConstraint(TransInfo *t); void setNearestAxis(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 6744f7b6262..b2d87272203 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -447,12 +447,12 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb) } } -/* sets transform flags in the bones - * returns total number of bones with BONE_TRANSFORM */ -int count_set_pose_transflags(Object *ob, - const int mode, - const short around, - bool has_translate_rotate[2]) +/* Sets transform flags in the bones. + * Returns total number of bones with `BONE_TRANSFORM`. */ +int transform_convert_pose_transflags_update(Object *ob, + const int mode, + const short around, + bool has_translate_rotate[2]) { bArmature *arm = ob->data; bPoseChannel *pchan; @@ -1846,8 +1846,8 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t) static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) { - /* so automerge supports mirror */ - if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) { + bool use_automerge = (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0; + if (use_automerge && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); @@ -1873,14 +1873,12 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) hflag = BM_ELEM_SELECT; } - if (t->scene->toolsettings->automerge & AUTO_MERGE) { - if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) { - EDBM_automerge_and_split( - tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit); - } - else { - EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit); - } + if (t->flag & T_AUTOSPLIT) { + EDBM_automerge_and_split( + tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit); + } + else { + EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit); } /* Special case, this is needed or faces won't re-select. @@ -2288,7 +2286,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* set BONE_TRANSFORM flags for autokey, gizmo draw might have changed them */ if (!canceled && (t->mode != TFM_DUMMY)) { - count_set_pose_transflags(ob, t->mode, t->around, NULL); + transform_convert_pose_transflags_update(ob, t->mode, t->around, NULL); } /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */ @@ -2743,7 +2741,7 @@ void createTransData(bContext *C, TransInfo *t) /* important that ob_armature can be set even when its not selected [#23412] * lines below just check is also visible */ has_transform_context = false; - Object *ob_armature = modifiers_isDeformedByArmature(ob); + Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); if (base_arm) { diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index f975d320e62..fccaeb994e9 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -37,10 +37,10 @@ struct bKinematicConstraint; struct bPoseChannel; /* transform_convert.c */ -int count_set_pose_transflags(Object *ob, - const int mode, - const short around, - bool has_translate_rotate[2]); +int transform_convert_pose_transflags_update(Object *ob, + const int mode, + const short around, + bool has_translate_rotate[2]); void transform_autoik_update(TransInfo *t, short mode); void autokeyframe_object(struct bContext *C, struct Scene *scene, diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 779257ef671..35bb7e3f0d8 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -609,9 +609,9 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object * /* TODO(germano): Realitve Mirror support */ } data->flag |= CONSTRAINT_IK_AUTO; - /* Add a temporary auto IK constraint here, as we will only temporarly active this targetless - * bone during transform. (Targetless IK constraints are treated as if they are disabled - * unless they are transformed) */ + /* Add a temporary auto IK constraint here, as we will only temporarily active this + * target-less bone during transform. (Target-less IK constraints are treated as if they are + * disabled unless they are transformed) */ add_temporary_ik_constraint(pchan, data); Main *bmain = CTX_data_main(t->context); update_deg_with_temporary_ik(bmain, ob); @@ -669,7 +669,9 @@ void createTransPose(TransInfo *t) const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0); /* set flags and count total */ - tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate); + tc->data_len = transform_convert_pose_transflags_update( + ob, t->mode, t->around, has_translate_rotate); + if (tc->data_len == 0) { continue; } diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 7528f791130..24dda8c8464 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -781,9 +781,9 @@ void createTransEditVerts(TransInfo *t) } /* detect CrazySpace [tm] */ - if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) { + if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) { int totleft = -1; - if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) { + if (BKE_modifiers_is_correctable_deformed(t->scene, tc->obedit)) { BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); /* Use evaluated state because we need b-bone cache. */ diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 9b76db7f265..8deba0f7ad0 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -197,7 +197,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) /* NOTE: This is not really following copy-on-write design and we should not * be re-evaluating the evaluated object. But as the comment above mentioned * this is part of a hack. - * More proper solution would be to make a shallow copy of the object and + * More proper solution would be to make a shallow copy of the object and * evaluate that, and access matrix of that evaluated copy of the object. * Might be more tricky than it sounds, if some logic later on accesses the * object matrix via td->ob->obmat. */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 05318a5c1d3..4472facf183 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1187,7 +1187,6 @@ void recalcData(TransInfo *t) flushTransPaintCurve(t); } else if (t->options & CTX_GPENCIL_STROKES) { - /* set recalc triangle cache flag */ recalcData_gpencil_strokes(t); } else if (t->options & CTX_SCULPT) { @@ -1431,11 +1430,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve unit_m3(t->mat); - unit_m3(t->orient_matrix); - negate_m3(t->orient_matrix); - /* Leave 't->orient_matrix_is_set' to false, - * so we overwrite it when we have a useful value. */ - /* Default to rotate on the Z axis. */ t->orient_axis = 2; t->orient_axis_ortho = 1; @@ -1513,22 +1507,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->around = V3D_AROUND_CURSOR; } - TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; - t->orientation.unset = V3D_ORIENT_GLOBAL; - t->orientation.user = orient_slot->type; - t->orientation.custom = BKE_scene_transform_orientation_find(t->scene, - orient_slot->index_custom); - - t->orientation.index = 0; - ARRAY_SET_ITEMS(t->orientation.types, &t->orientation.user, NULL); - - /* Make second orientation local if both are global. */ - if (t->orientation.user == V3D_ORIENT_GLOBAL) { - t->orientation.user_alt = V3D_ORIENT_LOCAL; - t->orientation.types[0] = &t->orientation.user_alt; - SWAP(short *, t->orientation.types[0], t->orientation.types[1]); - } - /* exceptional case */ if (t->around == V3D_AROUND_LOCAL_ORIGINS) { if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { @@ -1617,48 +1595,138 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->around = V3D_AROUND_CENTER_BOUNDS; } - if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { - t->orient_axis = RNA_property_enum_get(op->ptr, prop); - } - if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { - t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); - } + BLI_assert(is_zero_v4(t->values_modal_offset)); + bool t_values_set_is_array = false; + if (op && (prop = RNA_struct_find_property(op->ptr, "value")) && + RNA_property_is_set(op->ptr, prop)) { + float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ + if (RNA_property_array_check(prop)) { + RNA_float_get_array(op->ptr, "value", values); + t_values_set_is_array = true; + } + else { + values[0] = RNA_float_get(op->ptr, "value"); + } - if (op && - ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) && - RNA_property_is_set(op->ptr, prop)) && - ((t->flag & T_MODAL) || - /* When using redo, don't use the custom constraint matrix - * if the user selects a different orientation. */ - (RNA_enum_get(op->ptr, "orient_type") == RNA_enum_get(op->ptr, "orient_matrix_type")))) { - RNA_property_float_get_array(op->ptr, prop, &t->orient_matrix[0][0]); - copy_m3_m3(t->spacemtx, t->orient_matrix); - /* Some transform modes use this to operate on an axis. */ - t->orient_matrix_is_set = true; - t->orientation.user = V3D_ORIENT_CUSTOM_MATRIX; - t->orientation.custom = 0; + copy_v4_v4(t->values, values); if (t->flag & T_MODAL) { - RNA_enum_set(op->ptr, "orient_matrix_type", RNA_enum_get(op->ptr, "orient_type")); + /* Run before init functions so 'values_modal_offset' can be applied on mouse input. */ + copy_v4_v4(t->values_modal_offset, values); + } + else { + copy_v4_v4(t->values, values); + t->flag |= T_INPUT_IS_VALUES_FINAL; } } - else if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && - RNA_property_is_set(op->ptr, prop))) { - short orientation = RNA_property_enum_get(op->ptr, prop); + + if (op && (prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { + bool constraint_axis[3] = {false, false, false}; + if (RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); + } + + if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) { + /* For operators whose `t->values` is array, set contrain so that the + * orientation is more intuitive in the Redo Panel. */ + for (int i = 3; i--;) { + constraint_axis[i] |= t->values[i] != 0.0f; + } + } + + if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { + t->con.mode |= CON_APPLY; + + if (constraint_axis[0]) { + t->con.mode |= CON_AXIS0; + } + if (constraint_axis[1]) { + t->con.mode |= CON_AXIS1; + } + if (constraint_axis[2]) { + t->con.mode |= CON_AXIS2; + } + } + } + + { + TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; TransformOrientation *custom_orientation = NULL; + short orient_type_set = -1; + short orient_type_matrix_set = -1; + short orient_type_scene = orient_slot->type; + if (orient_type_scene == V3D_ORIENT_CUSTOM) { + const int index_custom = orient_slot->index_custom; + custom_orientation = BKE_scene_transform_orientation_find(t->scene, index_custom); + orient_type_scene += index_custom; + } - if (orientation >= V3D_ORIENT_CUSTOM) { - if (orientation >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) { - orientation = V3D_ORIENT_GLOBAL; + short orient_type_default = V3D_ORIENT_GLOBAL; + short orient_type_constraint[2]; + + if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { + t->orient_axis = RNA_property_enum_get(op->ptr, prop); + + /* For transfor modes that require "orient_axis" use + * `V3D_ORIENT_VIEW` as default. */ + orient_type_default = V3D_ORIENT_VIEW; + } + if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { + t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); + } + + if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && + RNA_property_is_set(op->ptr, prop))) { + orient_type_set = RNA_property_enum_get(op->ptr, prop); + if (orient_type_set >= V3D_ORIENT_CUSTOM) { + if (orient_type_set >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) { + orient_type_set = V3D_ORIENT_GLOBAL; + } + else { + custom_orientation = BKE_scene_transform_orientation_find( + t->scene, orient_type_default - V3D_ORIENT_CUSTOM); + } + } + + /* Change the default orientation to be used when redoing. */ + orient_type_default = orient_type_set; + orient_type_constraint[0] = orient_type_set; + orient_type_constraint[1] = orient_type_scene; + } + else { + orient_type_constraint[0] = orient_type_scene; + orient_type_constraint[1] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL : + V3D_ORIENT_LOCAL; + } + + if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) && + RNA_property_is_set(op->ptr, prop))) { + RNA_property_float_get_array(op->ptr, prop, &t->orientation.custom_matrix[0][0]); + + if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) && + RNA_property_is_set(op->ptr, prop)) { + orient_type_matrix_set = RNA_property_enum_get(op->ptr, prop); + } + else if (orient_type_set != -1) { + orient_type_matrix_set = orient_type_set; } else { - custom_orientation = BKE_scene_transform_orientation_find(t->scene, - orientation - V3D_ORIENT_CUSTOM); - orientation = V3D_ORIENT_CUSTOM; + orient_type_matrix_set = orient_type_set = V3D_ORIENT_GLOBAL; + } + + if (orient_type_matrix_set == orient_type_set) { + /* Constraints are forced to use the custom matrix when redoing. */ + orient_type_default = V3D_ORIENT_CUSTOM_MATRIX; } } - t->orientation.user = orientation; + t->orientation.types[0] = orient_type_default; + t->orientation.types[1] = orient_type_constraint[0]; + t->orientation.types[2] = orient_type_constraint[1]; t->orientation.custom = custom_orientation; + + if (t->con.mode & CON_APPLY) { + t->orientation.index = 1; + } } if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && @@ -1763,6 +1831,24 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->options |= CTX_NO_PET; } + if (t->obedit_type == OB_MESH) { + if (op && (prop = RNA_struct_find_property(op->ptr, "use_automerge_and_split")) && + RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + t->flag |= T_AUTOMERGE | T_AUTOSPLIT; + } + } + else { + char automerge = t->scene->toolsettings->automerge; + if (automerge & AUTO_MERGE) { + t->flag |= T_AUTOMERGE; + if (automerge & AUTO_MERGE_AND_SPLIT) { + t->flag |= T_AUTOSPLIT; + } + } + } + } + // Mirror is not supported with PET, turn it off. #if 0 if (t->flag & T_PROP_EDIT) { diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index aa298b04d1a..7a9be86624e 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -713,7 +713,9 @@ void ED_transform_calc_orientation_from_type_ex(const bContext *C, ok = true; break; } - case V3D_ORIENT_CUSTOM: { + case V3D_ORIENT_CUSTOM: + default: { + BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM); TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find( scene, orientation_index_custom); if (applyTransformOrientation(custom_orientation, r_mat, NULL)) { @@ -1033,7 +1035,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, /* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */ const int mode = TFM_ROTATION; - const int totsel_iter = count_set_pose_transflags( + const int totsel_iter = transform_convert_pose_transflags_update( ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL); if (totsel_iter) { @@ -1402,7 +1404,7 @@ void drawDial3d(const TransInfo *t) } else { axis_idx = MAN_AXIS_ROT_C; - negate_v3_v3(mat_basis[2], t->orient_matrix[t->orient_axis]); + negate_v3_v3(mat_basis[2], t->spacemtx[t->orient_axis]); scale *= 1.2f; line_with -= 1.0f; } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index a2b3a891031..4c14c3aebd7 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -529,7 +529,7 @@ void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) void postInputRotation(TransInfo *t, float values[3]) { float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, values); } diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c index 18149a09f20..fde0d5b187e 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c @@ -81,7 +81,7 @@ static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2])) char str[UI_MAX_DRAW_STR]; float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, NULL); diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index 6c2b3dc77d2..f52bfda0d14 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -146,7 +146,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) snapGridIncrement(t, &final); float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, NULL); diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c index ba79f5f3c7b..da34bf50ba3 100644 --- a/source/blender/editors/transform/transform_mode_shear.c +++ b/source/blender/editors/transform/transform_mode_shear.c @@ -53,17 +53,17 @@ static void initShear_mouseInputMode(TransInfo *t) { float dir[3]; bool dir_flip = false; - copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]); + copy_v3_v3(dir, t->spacemtx[t->orient_axis_ortho]); /* Needed for axis aligned view gizmo. */ - if (t->orientation.user == V3D_ORIENT_VIEW) { + if (t->orientation.types[t->orientation.index] == V3D_ORIENT_VIEW) { if (t->orient_axis_ortho == 0) { - if (t->center2d[1] > t->mouse.imval[1]) { + if (t->center2d[1] < t->mouse.imval[1]) { dir_flip = !dir_flip; } } else if (t->orient_axis_ortho == 1) { - if (t->center2d[0] > t->mouse.imval[0]) { + if (t->center2d[0] < t->mouse.imval[0]) { dir_flip = !dir_flip; } } @@ -154,8 +154,8 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) unit_m3(smat); smat[1][0] = value; - copy_v3_v3(axismat_inv[0], t->orient_matrix[t->orient_axis_ortho]); - copy_v3_v3(axismat_inv[2], t->orient_matrix[t->orient_axis]); + copy_v3_v3(axismat_inv[0], t->spacemtx[t->orient_axis_ortho]); + copy_v3_v3(axismat_inv[2], t->spacemtx[t->orient_axis]); cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]); invert_m3_m3(axismat, axismat_inv); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 36f42992573..d643244e6ca 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -716,6 +716,15 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation"); RNA_def_property_flag(prop, PROP_HIDDEN); } + + if (flags & P_POST_TRANSFORM) { + prop = RNA_def_boolean(ot->srna, + "use_automerge_and_split", + 0, + "Auto Merge & Split", + "Forces the use of Auto Merge & Split"); + RNA_def_property_flag(prop, PROP_HIDDEN); + } } static void TRANSFORM_OT_translate(struct wmOperatorType *ot) @@ -741,7 +750,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | - P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT); + P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_POST_TRANSFORM); } static void TRANSFORM_OT_resize(struct wmOperatorType *ot) diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 76823adfd20..81c63278366 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -407,14 +407,19 @@ bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3] return true; } -static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it) +/* Updates all `BONE_TRANSFORM` flags. + * Returns total number of bones with `BONE_TRANSFORM`. + * 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) { Bone *bone; bool do_next; int total = 0; for (bone = lb->first; bone; bone = bone->next) { - bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR); + bone->flag &= ~BONE_TRANSFORM; do_next = do_it; if (do_it) { if (bone->layer & arm->layer) { @@ -427,18 +432,18 @@ static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it) } } } - total += count_bone_select(arm, &bone->childbase, do_next); + total += armature_bone_transflags_update_recursive(arm, &bone->childbase, do_next); } return total; } -void initTransformOrientation(bContext *C, TransInfo *t) +void initTransformOrientation(bContext *C, TransInfo *t, short orientation) { Object *ob = CTX_data_active_object(C); Object *obedit = CTX_data_active_object(C); - switch (t->orientation.user) { + switch (orientation) { case V3D_ORIENT_GLOBAL: unit_m3(t->spacemtx); BLI_strncpy(t->spacename, TIP_("global"), sizeof(t->spacename)); @@ -471,32 +476,33 @@ void initTransformOrientation(bContext *C, TransInfo *t) break; - case V3D_ORIENT_VIEW: + case V3D_ORIENT_VIEW: { + float mat[3][3]; if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - RegionView3D *rv3d = t->region->regiondata; - float mat[3][3]; - BLI_strncpy(t->spacename, TIP_("view"), sizeof(t->spacename)); - copy_m3_m4(mat, rv3d->viewinv); + copy_m3_m4(mat, t->viewinv); normalize_m3(mat); - copy_m3_m3(t->spacemtx, mat); } else { - unit_m3(t->spacemtx); + unit_m3(mat); } + negate_v3(mat[2]); + copy_m3_m3(t->spacemtx, mat); break; + } case V3D_ORIENT_CURSOR: { BLI_strncpy(t->spacename, TIP_("cursor"), sizeof(t->spacename)); BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, t->spacemtx); break; } case V3D_ORIENT_CUSTOM_MATRIX: - /* Already set. */ BLI_strncpy(t->spacename, TIP_("custom"), sizeof(t->spacename)); + copy_m3_m3(t->spacemtx, t->orientation.custom_matrix); break; case V3D_ORIENT_CUSTOM: + default: + BLI_assert(orientation >= V3D_ORIENT_CUSTOM); BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename)); - if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) { /* pass */ } @@ -505,20 +511,6 @@ void initTransformOrientation(bContext *C, TransInfo *t) } break; } - - if (t->orient_matrix_is_set == false) { - t->orient_matrix_is_set = true; - if (t->flag & T_MODAL) { - /* Rotate for example defaults to operating on the view plane. */ - t->orientation.unset = V3D_ORIENT_VIEW; - copy_m3_m4(t->orient_matrix, t->viewinv); - normalize_m3(t->orient_matrix); - negate_m3(t->orient_matrix); - } - else { - copy_m3_m3(t->orient_matrix, t->spacemtx); - } - } } /** @@ -1072,10 +1064,9 @@ int getTransformOrientation_ex(const bContext *C, ok = true; } else { - int totsel; - - totsel = count_bone_select(arm, &arm->bonebase, true); - if (totsel) { + int transformed_len; + transformed_len = armature_bone_transflags_update_recursive(arm, &arm->bonebase, true); + if (transformed_len) { /* use channels to get stats */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index d2ba9ab9591..b40b82c50fb 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC uvedit_draw.c uvedit_ops.c uvedit_parametrizer.c + uvedit_select.c uvedit_smart_stitch.c uvedit_unwrap_ops.c diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 6ea1bbbcc10..959ca1eeef1 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -306,6 +306,7 @@ static void draw_uvs(SpaceImage *sima, Object *ob_eval = batch->ob_eval; const ToolSettings *ts = scene->toolsettings; float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float overlay_alpha = sima->uv_opacity; if (sima->flag & SI_DRAWSHADOW) { bool is_cage_like_final_meshes = false; @@ -346,7 +347,11 @@ static void draw_uvs(SpaceImage *sima, UI_GetThemeColor4fv(TH_FACE, col1); UI_GetThemeColor4fv(TH_FACE_SELECT, col2); UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3); - col3[3] *= 0.2; /* Simulate dithering */ + + col1[3] *= overlay_alpha; + col2[3] *= overlay_alpha; + col3[3] *= overlay_alpha; + GPU_batch_uniform_4fv(batch->faces, "faceColor", col1); GPU_batch_uniform_4fv(batch->faces, "selectColor", col2); GPU_batch_uniform_4fv(batch->faces, "activeColor", col3); @@ -372,9 +377,16 @@ static void draw_uvs(SpaceImage *sima, GPU_line_smooth(true); GPU_blend(true); } + else if (overlay_alpha < 1.0f) { + GPU_blend(true); + } + switch (sima->dt_uv) { case SI_UVDT_DASH: { - float dash_colors[2][4] = {{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}; + float dash_colors[2][4] = { + {0.56f, 0.56f, 0.56f, overlay_alpha}, + {0.07f, 0.07f, 0.07f, overlay_alpha}, + }; float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -398,7 +410,8 @@ static void draw_uvs(SpaceImage *sima, * instead of modifying the provoking vert. */ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - UI_GetThemeColor4fv(TH_EDGE_SELECT, col2); + UI_GetThemeColor3fv(TH_EDGE_SELECT, col2); + col2[3] = overlay_alpha; GPU_batch_program_set_builtin( batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); @@ -406,18 +419,19 @@ static void draw_uvs(SpaceImage *sima, if (sima->dt_uv == SI_UVDT_OUTLINE) { /* Black Outline. */ GPU_line_width(3.0f); - GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f); - GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f); + GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha); + GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha); GPU_batch_draw(batch->edges); - UI_GetThemeColor4fv(TH_WIRE_EDIT, col1); + UI_GetThemeColor3fv(TH_WIRE_EDIT, col1); } else if (sima->dt_uv == SI_UVDT_WHITE) { - copy_v4_fl4(col1, 1.0f, 1.0f, 1.0f, 1.0f); + copy_v3_fl3(col1, 1.0f, 1.0f, 1.0f); } else { - copy_v4_fl4(col1, 0.0f, 0.0f, 0.0f, 1.0f); + copy_v3_fl3(col1, 0.0f, 0.0f, 0.0f); } + col1[3] = overlay_alpha; /* Inner Line. Use depth test to insure selection is drawn on top. */ GPU_depth_test(true); @@ -435,6 +449,9 @@ static void draw_uvs(SpaceImage *sima, GPU_line_smooth(false); GPU_blend(false); } + else if (overlay_alpha < 1.0f) { + GPU_blend(false); + } } if (batch->verts || batch->facedots) { UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 7bc6b048585..ffab5bd094f 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -99,6 +99,7 @@ bool uv_find_nearest_face_multi(struct Scene *scene, void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit); +void uvedit_pixel_to_float(struct SpaceImage *sima, float pixeldist, float r_dist[2]); /* operators */ @@ -113,4 +114,31 @@ void UV_OT_sphere_project(struct wmOperatorType *ot); void UV_OT_unwrap(struct wmOperatorType *ot); void UV_OT_stitch(struct wmOperatorType *ot); +/* uvedit_select.c */ + +bool uvedit_select_is_any_selected(struct Scene *scene, struct Image *ima, struct Object *obedit); +bool uvedit_select_is_any_selected_multi(struct Scene *scene, + struct Image *ima, + struct Object **objects, + const uint objects_len); +const float *uvedit_first_selected_uv_from_vertex(struct Scene *scene, + struct Object *obedit, + struct Image *ima, + struct BMVert *eve, + const int cd_loop_uv_offset); + +void UV_OT_select_all(struct wmOperatorType *ot); +void UV_OT_select(struct wmOperatorType *ot); +void UV_OT_select_loop(struct wmOperatorType *ot); +void UV_OT_select_linked(struct wmOperatorType *ot); +void UV_OT_select_linked_pick(struct wmOperatorType *ot); +void UV_OT_select_split(struct wmOperatorType *ot); +void UV_OT_select_pinned(struct wmOperatorType *ot); +void UV_OT_select_box(struct wmOperatorType *ot); +void UV_OT_select_lasso(struct wmOperatorType *ot); +void UV_OT_select_circle(struct wmOperatorType *ot); +void UV_OT_select_more(struct wmOperatorType *ot); +void UV_OT_select_less(struct wmOperatorType *ot); +void UV_OT_select_overlap(struct wmOperatorType *ot); + #endif /* __UVEDIT_INTERN_H__ */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index e169222380e..a99e05cb52b 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -36,15 +36,9 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" -#include "BLI_alloca.h" #include "BLI_array.h" -#include "BLI_blenlib.h" -#include "BLI_hash.h" -#include "BLI_kdopbvh.h" #include "BLI_kdtree.h" -#include "BLI_lasso_2d.h" #include "BLI_math.h" -#include "BLI_polyfill_2d.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -52,31 +46,22 @@ #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" -#include "BKE_image.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" -#include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_node.h" -#include "BKE_report.h" -#include "BKE_scene.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "ED_image.h" #include "ED_mesh.h" #include "ED_node.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "ED_uvedit.h" #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_message.h" @@ -88,26 +73,6 @@ #include "uvedit_intern.h" -static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit); -static bool uv_select_is_any_selected_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len); -static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action); -static void uv_select_all_perform_multi( - Scene *scene, Image *ima, Object **objects, const uint objects_len, int action); -static void uv_select_flush_from_tag_face(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select); -static void uv_select_flush_from_tag_loop(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select); -static void uv_select_tag_update_for_object(Depsgraph *depsgraph, - const ToolSettings *ts, - Object *obedit); - /* -------------------------------------------------------------------- */ /** \name State Testing * \{ */ @@ -225,7 +190,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i /** \name Space Conversion * \{ */ -static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist) +void uvedit_pixel_to_float(SpaceImage *sima, float pixeldist, float r_dist[2]) { int width, height; @@ -237,351 +202,8 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist height = IMG_SIZE_FALLBACK; } - dist[0] = pixeldist / width; - dist[1] = pixeldist / height; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Visibility and Selection Utilities - * \{ */ - -static void uvedit_vertex_select_tagged(BMEditMesh *em, - Scene *scene, - bool select, - int cd_loop_uv_offset) -{ - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } -} - -bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0); - } - else { - return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT)); - } -} -bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa) -{ - return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa); -} - -bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa) -{ - if (ts->uv_flag & UV_SHOW_SAME_IMAGE) { - Image *face_image; - ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL); - return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false; - } - else { - return uvedit_face_visible_nolocal_ex(ts, efa); - } -} -bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa) -{ - return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa); -} - -bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - return (BM_elem_flag_test(efa, BM_ELEM_SELECT)); - } - else { - BMLoop *l; - MLoopUV *luv; - BMIter liter; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (!(luv->flag & MLOOPUV_VERTSEL)) { - return false; - } - } - - return true; - } -} -bool uvedit_face_select_test(const Scene *scene, BMFace *efa, const int cd_loop_uv_offset) -{ - return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset); -} - -bool uvedit_face_select_set(const struct Scene *scene, - struct BMEditMesh *em, - struct BMFace *efa, - const bool select, - const bool do_history, - const int cd_loop_uv_offset) -{ - if (select) { - return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset); - } - else { - return uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); - } -} - -bool uvedit_face_select_enable(const Scene *scene, - BMEditMesh *em, - BMFace *efa, - const bool do_history, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - BM_face_select_set(em->bm, efa, true); - if (do_history) { - BM_select_history_store(em->bm, (BMElem *)efa); - } - } - else { - BMLoop *l; - MLoopUV *luv; - BMIter liter; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; - } - - return true; - } - - return false; -} - -bool uvedit_face_select_disable(const Scene *scene, - BMEditMesh *em, - BMFace *efa, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - BM_face_select_set(em->bm, efa, false); - } - else { - BMLoop *l; - MLoopUV *luv; - BMIter liter; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag &= ~MLOOPUV_VERTSEL; - } - - return true; - } - - return false; -} - -bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - return BM_elem_flag_test(l->f, BM_ELEM_SELECT); - } - else if (ts->selectmode == SCE_SELECT_EDGE) { - return BM_elem_flag_test(l->e, BM_ELEM_SELECT); - } - else { - return BM_elem_flag_test(l->v, BM_ELEM_SELECT) && - BM_elem_flag_test(l->next->v, BM_ELEM_SELECT); - } - } - else { - MLoopUV *luv1, *luv2; - - luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL); - } -} -bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) -{ - return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); -} - -void uvedit_edge_select_set(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool select, - const bool do_history, - const int cd_loop_uv_offset) - -{ - if (select) { - uvedit_edge_select_enable(em, scene, l, do_history, cd_loop_uv_offset); - } - else { - uvedit_edge_select_disable(em, scene, l, cd_loop_uv_offset); - } -} - -void uvedit_edge_select_enable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool do_history, - const int cd_loop_uv_offset) - -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, true); - } - else if (ts->selectmode & SCE_SELECT_EDGE) { - BM_edge_select_set(em->bm, l->e, true); - } - else { - BM_vert_select_set(em->bm, l->e->v1, true); - BM_vert_select_set(em->bm, l->e->v2, true); - } - - if (do_history) { - BM_select_history_store(em->bm, (BMElem *)l->e); - } - } - else { - MLoopUV *luv1, *luv2; - - luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - luv1->flag |= MLOOPUV_VERTSEL; - luv2->flag |= MLOOPUV_VERTSEL; - } -} - -void uvedit_edge_select_disable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const int cd_loop_uv_offset) - -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, false); - } - else if (ts->selectmode & SCE_SELECT_EDGE) { - BM_edge_select_set(em->bm, l->e, false); - } - else { - BM_vert_select_set(em->bm, l->e->v1, false); - BM_vert_select_set(em->bm, l->e->v2, false); - } - } - else { - MLoopUV *luv1, *luv2; - - luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - luv1->flag &= ~MLOOPUV_VERTSEL; - luv2->flag &= ~MLOOPUV_VERTSEL; - } -} - -bool uvedit_uv_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - return BM_elem_flag_test_bool(l->f, BM_ELEM_SELECT); - } - else { - return BM_elem_flag_test_bool(l->v, BM_ELEM_SELECT); - } - } - else { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - return (luv->flag & MLOOPUV_VERTSEL) != 0; - } -} -bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) -{ - return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); -} - -void uvedit_uv_select_set(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool select, - const bool do_history, - const int cd_loop_uv_offset) -{ - if (select) { - uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset); - } - else { - uvedit_uv_select_disable(em, scene, l, cd_loop_uv_offset); - } -} - -void uvedit_uv_select_enable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool do_history, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, true); - } - else { - BM_vert_select_set(em->bm, l->v, true); - } - - if (do_history) { - BM_select_history_remove(em->bm, (BMElem *)l->v); - } - } - else { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; - } -} - -void uvedit_uv_select_disable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, false); - } - else { - BM_vert_select_set(em->bm, l->v, false); - } - } - else { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag &= ~MLOOPUV_VERTSEL; - } + r_dist[0] = pixeldist / width; + r_dist[1] = pixeldist / height; } /** \} */ @@ -770,7 +392,8 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima, uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - *r_has_select = uv_select_is_any_selected_multi(scene, sima->image, objects, objects_len); + *r_has_select = uvedit_select_is_any_selected_multi( + scene, sima->image, objects, objects_len); MEM_freeN(objects); } break; @@ -799,877 +422,6 @@ bool ED_uvedit_center_from_pivot( /** \} */ /* -------------------------------------------------------------------- */ -/** \name Find Nearest Elements - * \{ */ - -bool uv_find_nearest_edge( - Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv, *luv_next; - int i; - bool found = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); - - if (dist_test_sq < hit->dist_sq) { - hit->efa = efa; - - hit->l = l; - hit->luv = luv; - hit->luv_next = luv_next; - hit->lindex = i; - - hit->dist_sq = dist_test_sq; - found = true; - } - } - } - return found; -} - -bool uv_find_nearest_edge_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float co[2], - UvNearestHit *hit_final) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) { - hit_final->ob = obedit; - found = true; - } - } - return found; -} - -bool uv_find_nearest_face( - Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - bool found = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* this will fill in hit.vert1 and hit.vert2 */ - float dist_sq_init = hit_final->dist_sq; - UvNearestHit hit = *hit_final; - if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { - hit.dist_sq = dist_sq_init; - hit.l = NULL; - hit.luv = hit.luv_next = NULL; - - BMIter iter; - BMFace *efa; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); - - const float dist_test_sq = len_squared_v2v2(co, cent); - - if (dist_test_sq < hit.dist_sq) { - hit.efa = efa; - hit.dist_sq = dist_test_sq; - found = true; - } - } - } - if (found) { - *hit_final = hit; - } - return found; -} - -bool uv_find_nearest_face_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float co[2], - UvNearestHit *hit_final) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) { - hit_final->ob = obedit; - found = true; - } - } - return found; -} - -static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset) -{ - const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv; - const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv; - const float *uv_next = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset))->uv; - - return ((line_point_side_v2(uv_prev, uv_curr, co) > 0.0f) && - (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f)); -} - -bool uv_find_nearest_vert(Scene *scene, - Image *ima, - Object *obedit, - float const co[2], - const float penalty_dist, - UvNearestHit *hit_final) -{ - bool found = false; - - /* this will fill in hit.vert1 and hit.vert2 */ - float dist_sq_init = hit_final->dist_sq; - UvNearestHit hit = *hit_final; - if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { - hit.dist_sq = dist_sq_init; - - hit.l = NULL; - hit.luv = hit.luv_next = NULL; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMIter iter; - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BMIter liter; - BMLoop *l; - int i; - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - float dist_test_sq; - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist; - dist_test_sq = square_f(dist_test_sq); - } - else { - dist_test_sq = len_squared_v2v2(co, luv->uv); - } - - if (dist_test_sq <= hit.dist_sq) { - if (dist_test_sq == hit.dist_sq) { - if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { - continue; - } - } - - hit.dist_sq = dist_test_sq; - - hit.l = l; - hit.luv = luv; - hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - hit.efa = efa; - hit.lindex = i; - found = true; - } - } - } - } - - if (found) { - *hit_final = hit; - } - - return found; -} - -bool uv_find_nearest_vert_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - float const co[2], - const float penalty_dist, - UvNearestHit *hit_final) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) { - hit_final->ob = obedit; - found = true; - } - } - return found; -} - -bool ED_uvedit_nearest_uv(const Scene *scene, - Object *obedit, - Image *ima, - const float co[2], - float *dist_sq, - float r_uv[2]) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMIter iter; - BMFace *efa; - const float *uv_best = NULL; - float dist_best = *dist_sq; - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv; - const float dist_test = len_squared_v2v2(co, uv); - if (dist_best > dist_test) { - dist_best = dist_test; - uv_best = uv; - } - } while ((l_iter = l_iter->next) != l_first); - } - - if (uv_best != NULL) { - copy_v2_v2(r_uv, uv_best); - *dist_sq = dist_best; - return true; - } - else { - return false; - } -} - -bool ED_uvedit_nearest_uv_multi(const Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float co[2], - float *dist_sq, - float r_uv[2]) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) { - found = true; - } - } - return found; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Loop Select - * \{ */ - -static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first) -{ - UvMapVert *iterv; - int count = 0; - - for (iterv = first; iterv; iterv = iterv->next) { - if (iterv->separate && iterv != first) { - break; - } - - count++; - } - - if (count < 5) { - first->flag = 1; - } -} - -static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l) -{ - UvMapVert *iterv, *first; - first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); - - for (iterv = first; iterv; iterv = iterv->next) { - if (iterv->separate) { - first = iterv; - } - if (iterv->poly_index == BM_elem_index_get(efa)) { - return first; - } - } - - return NULL; -} - -static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, - UvMapVert *first1, - UvMapVert *first2, - int *totface) -{ - UvMapVert *iterv1, *iterv2; - BMFace *efa; - int tot = 0; - - /* count number of faces this edge has */ - for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { - if (iterv1->separate && iterv1 != first1) { - break; - } - - for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { - if (iterv2->separate && iterv2 != first2) { - break; - } - - if (iterv1->poly_index == iterv2->poly_index) { - /* if face already tagged, don't do this edge */ - efa = BM_face_at_index(em->bm, iterv1->poly_index); - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - return false; - } - - tot++; - break; - } - } - } - - if (*totface == 0) { /* start edge */ - *totface = tot; - } - else if (tot != *totface) { /* check for same number of faces as start edge */ - return false; - } - - /* tag the faces */ - for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { - if (iterv1->separate && iterv1 != first1) { - break; - } - - for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { - if (iterv2->separate && iterv2 != first2) { - break; - } - - if (iterv1->poly_index == iterv2->poly_index) { - efa = BM_face_at_index(em->bm, iterv1->poly_index); - BM_elem_flag_enable(efa, BM_ELEM_TAG); - break; - } - } - } - - return true; -} - -static int uv_select_edgeloop(Scene *scene, - Image *ima, - Object *obedit, - UvNearestHit *hit, - const float limit[2], - const bool extend) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMIter iter, liter; - BMLoop *l; - UvVertMap *vmap; - UvMapVert *iterv_curr; - UvMapVert *iterv_next; - int starttotf; - bool looking, select; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* setup */ - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, limit, false, false); - - BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); - - if (!extend) { - uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); - } - - BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - - /* set flags for first face and verts */ - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); - iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); - uv_select_edgeloop_vertex_loop_flag(iterv_curr); - uv_select_edgeloop_vertex_loop_flag(iterv_next); - - starttotf = 0; - uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf); - - /* sorry, first edge isn't even ok */ - looking = !(iterv_curr->flag == 0 && iterv_next->flag == 0); - - /* iterate */ - while (looking) { - looking = false; - - /* find correct valence edges which are not tagged yet, but connect to tagged one */ - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && - uvedit_face_visible_test(scene, obedit, ima, efa)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - /* check face not hidden and not tagged */ - if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) { - continue; - } - if (!(iterv_next = uv_select_edgeloop_vertex_map_get(vmap, efa, l->next))) { - continue; - } - - /* check if vertex is tagged and has right valence */ - if (iterv_curr->flag || iterv_next->flag) { - if (uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf)) { - looking = true; - BM_elem_flag_enable(efa, BM_ELEM_TAG); - - uv_select_edgeloop_vertex_loop_flag(iterv_curr); - uv_select_edgeloop_vertex_loop_flag(iterv_next); - break; - } - } - } - } - } - } - - /* do the actual select/deselect */ - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); - iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); - iterv_curr->flag = 1; - iterv_next->flag = 1; - - if (extend) { - select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset)); - } - else { - select = true; - } - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l); - - if (iterv_curr->flag) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - - /* cleanup */ - BM_uv_vert_map_free(vmap); - - return (select) ? 1 : -1; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Linked - * \{ */ - -static void uv_select_linked_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float limit[2], - UvNearestHit *hit_final, - bool extend, - bool deselect, - bool toggle, - bool select_faces) -{ - /* loop over objects, or just use hit_final->ob */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - if (hit_final && ob_index != 0) { - break; - } - Object *obedit = hit_final ? hit_final->ob : objects[ob_index]; - - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - UvVertMap *vmap; - UvMapVert *vlist, *iterv, *startv; - int i, stacksize = 0, *stack; - uint a; - char *flag; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - 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 - * this made *every* projection split the island into front/back islands. - * Keep 'use_winding' to false, see: T50970. - * - * Better solve this by having a delimit option for select-linked operator, - * keeping island-select working as is. */ - vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false); - - if (vmap == NULL) { - continue; - } - - stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack"); - flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag"); - - if (hit_final == NULL) { - /* Use existing selection */ - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - if (select_faces) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - stack[stacksize] = a; - stacksize++; - flag[a] = 1; - } - } - else { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { - stack[stacksize] = a; - stacksize++; - flag[a] = 1; - - break; - } - } - } - } - } - } - else { - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (efa == hit_final->efa) { - stack[stacksize] = a; - stacksize++; - flag[a] = 1; - break; - } - } - } - - while (stacksize > 0) { - - stacksize--; - a = stack[stacksize]; - - efa = BM_face_at_index(em->bm, a); - - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - - /* make_uv_vert_map_EM sets verts tmp.l to the indices */ - vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); - - startv = vlist; - - for (iterv = vlist; iterv; iterv = iterv->next) { - if (iterv->separate) { - startv = iterv; - } - if (iterv->poly_index == a) { - break; - } - } - - for (iterv = startv; iterv; iterv = iterv->next) { - if ((startv != iterv) && (iterv->separate)) { - break; - } - else if (!flag[iterv->poly_index]) { - flag[iterv->poly_index] = 1; - stack[stacksize] = iterv->poly_index; - stacksize++; - } - } - } - } - - /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */ - if ((toggle == true) && (extend == false) && (deselect == false)) { - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - bool found_selected = false; - if (!flag[a]) { - continue; - } - - if (select_faces) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - found_selected = true; - } - } - else { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { - found_selected = true; - } - } - - if (found_selected) { - deselect = true; - break; - } - } - } - } - -#define SET_SELECTION(value) \ - if (select_faces) { \ - BM_face_select_set(em->bm, efa, value); \ - } \ - else { \ - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \ - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \ - luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \ - } \ - } \ - (void)0 - - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (!flag[a]) { - if (!extend && !deselect && !toggle) { - SET_SELECTION(false); - } - continue; - } - - if (!deselect) { - SET_SELECTION(true); - } - else { - SET_SELECTION(false); - } - } - -#undef SET_SELECTION - - MEM_freeN(stack); - MEM_freeN(flag); - BM_uv_vert_map_free(vmap); - } -} - -/* WATCH IT: this returns first selected UV, - * not ideal in many cases since there could be multiple */ -static float *uv_sel_co_from_eve( - Scene *scene, Object *obedit, Image *ima, BMEditMesh *em, BMVert *eve) -{ - BMIter liter; - BMLoop *l; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) { - continue; - } - - if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - return luv->uv; - } - } - - return NULL; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select More/Less Operator - * \{ */ - -static int uv_select_more_less(bContext *C, const bool select) -{ - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - SpaceImage *sima = CTX_wm_space_image(C); - - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - const ToolSettings *ts = scene->toolsettings; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - const bool is_uv_face_selectmode = (ts->uv_selectmode == UV_SELECT_FACE); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (select) { - EDBM_select_more(em, true); - } - else { - EDBM_select_less(em, true); - } - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - continue; - } - - if (is_uv_face_selectmode) { - - /* clear tags */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - - /* mark loops to be selected */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - -#define IS_SEL 1 -#define IS_UNSEL 2 - - int sel_state = 0; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (luv->flag & MLOOPUV_VERTSEL) { - sel_state |= IS_SEL; - } - else { - sel_state |= IS_UNSEL; - } - - /* if we have a mixed selection, tag to grow it */ - if (sel_state == (IS_SEL | IS_UNSEL)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - break; - } - } - -#undef IS_SEL -#undef IS_UNSEL - } - } - } - else { - - /* clear tags */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - BM_elem_flag_disable(l, BM_ELEM_TAG); - } - } - - /* mark loops to be selected */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (((luv->flag & MLOOPUV_VERTSEL) != 0) == select) { - BM_elem_flag_enable(l->next, BM_ELEM_TAG); - BM_elem_flag_enable(l->prev, BM_ELEM_TAG); - changed = true; - } - } - } - } - } - - if (changed) { - if (is_uv_face_selectmode) { - /* Select tagged faces. */ - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - else { - /* Select tagged loops. */ - uv_select_flush_from_tag_loop(sima, scene, obedit, select); - } - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - } - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static int uv_select_more_exec(bContext *C, wmOperator *UNUSED(op)) -{ - return uv_select_more_less(C, true); -} - -static void UV_OT_select_more(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select More"; - ot->description = "Select more UV vertices connected to initial selection"; - ot->idname = "UV_OT_select_more"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_more_exec; - ot->poll = ED_operator_uvedit_space_image; -} - -static int uv_select_less_exec(bContext *C, wmOperator *UNUSED(op)) -{ - return uv_select_more_less(C, false); -} - -static void UV_OT_select_less(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Less"; - ot->description = "Deselect UV vertices at the boundary of each selection region"; - ot->idname = "UV_OT_select_less"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_less_exec; - ot->poll = ED_operator_uvedit_space_image; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Weld Align Operator * \{ */ @@ -1866,9 +618,10 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) if (BLI_array_len(eve_line) > 2) { /* we know the returns from these must be valid */ - const float *uv_start = uv_sel_co_from_eve(scene, obedit, ima, em, eve_line[0]); - const float *uv_end = uv_sel_co_from_eve( - scene, obedit, ima, em, eve_line[BLI_array_len(eve_line) - 1]); + const float *uv_start = uvedit_first_selected_uv_from_vertex( + scene, obedit, ima, eve_line[0], cd_loop_uv_offset); + const float *uv_end = uvedit_first_selected_uv_from_vertex( + scene, obedit, ima, eve_line[BLI_array_len(eve_line) - 1], cd_loop_uv_offset); /* For UV_STRAIGHTEN_X & UV_STRAIGHTEN_Y modes */ float a = 0.0f; eUVWeldAlign tool_local = tool; @@ -2316,1665 +1069,6 @@ static void UV_OT_weld(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name (De)Select All Operator - * \{ */ - -static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit) -{ - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - return (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel); - } - else { - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (luv->flag & MLOOPUV_VERTSEL) { - return true; - } - } - } - } - return false; -} - -static bool uv_select_is_any_selected_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_select_is_any_selected(scene, ima, obedit)) { - found = true; - break; - } - } - return found; -} - -static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action) -{ - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if (action == SEL_TOGGLE) { - action = uv_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT; - } - - if (ts->uv_flag & UV_SYNC_SELECTION) { - switch (action) { - case SEL_TOGGLE: - EDBM_select_toggle_all(em); - break; - case SEL_SELECT: - EDBM_flag_enable_all(em, BM_ELEM_SELECT); - break; - case SEL_DESELECT: - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - break; - case SEL_INVERT: - EDBM_select_swap(em); - EDBM_selectmode_flush(em); - break; - } - } - else { - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - switch (action) { - case SEL_SELECT: - luv->flag |= MLOOPUV_VERTSEL; - break; - case SEL_DESELECT: - luv->flag &= ~MLOOPUV_VERTSEL; - break; - case SEL_INVERT: - luv->flag ^= MLOOPUV_VERTSEL; - break; - } - } - } - } -} - -static void uv_select_all_perform_multi( - Scene *scene, Image *ima, Object **objects, const uint objects_len, int action) -{ - if (action == SEL_TOGGLE) { - action = uv_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT : - SEL_SELECT; - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - uv_select_all_perform(scene, ima, obedit, action); - } -} - -static int uv_select_all_exec(bContext *C, wmOperator *op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - - int action = RNA_enum_get(op->ptr, "action"); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - uv_select_all_perform_multi(scene, ima, objects, objects_len, action); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static void UV_OT_select_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "(De)select All"; - ot->description = "Change selection of all UV vertices"; - ot->idname = "UV_OT_select_all"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_all_exec; - ot->poll = ED_operator_uvedit; - - WM_operator_properties_select_all(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Mouse Select Operator - * \{ */ - -static bool uv_sticky_select( - float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen) -{ - int i; - - /* this function test if some vertex needs to selected - * in addition to the existing ones due to sticky select */ - if (sticky == SI_STICKY_DISABLE) { - return false; - } - - for (i = 0; i < hitlen; i++) { - if (hitv[i] == v) { - if (sticky == SI_STICKY_LOC) { - if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1]) { - return true; - } - } - else if (sticky == SI_STICKY_VERTEX) { - return true; - } - } - } - - return false; -} - -static int uv_mouse_select_multi(bContext *C, - Object **objects, - uint objects_len, - const float co[2], - const bool extend, - const bool deselect_all, - const bool loop) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - UvNearestHit hit = UV_NEAREST_HIT_INIT; - int i, selectmode, sticky, sync, *hitv = NULL; - bool select = true; - bool found_item = false; - /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ - int flush = 0; - int hitlen = 0; - float limit[2], **hituv = NULL; - - /* notice 'limit' is the same no matter the zoom level, since this is like - * remove doubles and could annoying if it joined points when zoomed out. - * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and - * shift-selecting can consider an adjacent point close enough to add to - * the selection rather than de-selecting the closest. */ - - float penalty_dist; - { - float penalty[2]; - uvedit_pixel_to_float(sima, limit, 0.05f); - uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f)); - penalty_dist = len_v2(penalty); - } - - /* retrieve operation mode */ - if (ts->uv_flag & UV_SYNC_SELECTION) { - sync = 1; - - if (ts->selectmode & SCE_SELECT_FACE) { - selectmode = UV_SELECT_FACE; - } - else if (ts->selectmode & SCE_SELECT_EDGE) { - selectmode = UV_SELECT_EDGE; - } - else { - selectmode = UV_SELECT_VERTEX; - } - - sticky = SI_STICKY_DISABLE; - } - else { - sync = 0; - selectmode = ts->uv_selectmode; - sticky = (sima) ? sima->sticky : 1; - } - - /* find nearest element */ - if (loop) { - /* find edge */ - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); - } - else if (selectmode == UV_SELECT_VERTEX) { - /* find vertex */ - found_item = uv_find_nearest_vert_multi( - scene, ima, objects, objects_len, co, penalty_dist, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - - if (found_item) { - /* mark 1 vertex as being hit */ - hitv = BLI_array_alloca(hitv, hit.efa->len); - hituv = BLI_array_alloca(hituv, hit.efa->len); - copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); - - hitv[hit.lindex] = BM_elem_index_get(hit.l->v); - hituv[hit.lindex] = hit.luv->uv; - - hitlen = hit.efa->len; - } - } - else if (selectmode == UV_SELECT_EDGE) { - /* find edge */ - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - - if (found_item) { - /* mark 2 edge vertices as being hit */ - hitv = BLI_array_alloca(hitv, hit.efa->len); - hituv = BLI_array_alloca(hituv, hit.efa->len); - copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); - - hitv[hit.lindex] = BM_elem_index_get(hit.l->v); - hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v); - hituv[hit.lindex] = hit.luv->uv; - hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv; - - hitlen = hit.efa->len; - } - } - else if (selectmode == UV_SELECT_FACE) { - /* find face */ - found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - - if (found_item) { - BMEditMesh *em = BKE_editmesh_from_object(hit.ob); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* make active */ - BM_mesh_active_face_set(em->bm, hit.efa); - - /* mark all face vertices as being hit */ - - hitv = BLI_array_alloca(hitv, hit.efa->len); - hituv = BLI_array_alloca(hituv, hit.efa->len); - BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - hituv[i] = luv->uv; - hitv[i] = BM_elem_index_get(l->v); - } - - hitlen = hit.efa->len; - } - } - else if (selectmode == UV_SELECT_ISLAND) { - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - } - - if (!found_item) { - if (deselect_all) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - - return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; - } - return OPERATOR_CANCELLED; - } - - Object *obedit = hit.ob; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* do selection */ - if (loop) { - if (!extend) { - /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend); - } - else if (selectmode == UV_SELECT_ISLAND) { - if (!extend) { - /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - /* Current behavior of 'extend' - * is actually toggling, so pass extend flag as 'toggle' here */ - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, false, false, extend, false); - } - else if (extend) { - if (selectmode == UV_SELECT_VERTEX) { - /* (de)select uv vertex */ - select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset); - uvedit_uv_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_EDGE) { - /* (de)select edge */ - select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset)); - uvedit_edge_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_FACE) { - /* (de)select face */ - select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset)); - uvedit_face_select_set(scene, em, hit.efa, select, true, cd_loop_uv_offset); - flush = -1; - } - - /* de-selecting an edge may deselect a face too - validate */ - if (sync) { - if (select == false) { - BM_select_history_validate(em->bm); - } - } - - /* (de)select sticky uv nodes */ - if (sticky != SI_STICKY_DISABLE) { - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (uv_sticky_select( - limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - - flush = select ? 1 : -1; - } - } - else { - /* deselect all */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - - if (selectmode == UV_SELECT_VERTEX) { - /* select vertex */ - uvedit_uv_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_EDGE) { - /* select edge */ - uvedit_edge_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_FACE) { - /* select face */ - uvedit_face_select_enable(scene, em, hit.efa, true, cd_loop_uv_offset); - } - - /* select sticky uvs */ - if (sticky != SI_STICKY_DISABLE) { - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (sticky == SI_STICKY_DISABLE) { - continue; - } - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (uv_sticky_select( - limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { - uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); - } - - flush = 1; - } - } - } - } - - if (sync) { - /* flush for mesh selection */ - - /* before bmesh */ -#if 0 - if (ts->selectmode != SCE_SELECT_FACE) { - if (flush == 1) { - EDBM_select_flush(em); - } - else if (flush == -1) { - EDBM_deselect_flush(em); - } - } -#else - if (flush != 0) { - if (loop) { - /* push vertex -> edge selection */ - if (select) { - EDBM_select_flush(em); - } - else { - EDBM_deselect_flush(em); - } - } - else { - EDBM_selectmode_flush(em); - } - } -#endif - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obiter = objects[ob_index]; - uv_select_tag_update_for_object(depsgraph, ts, obiter); - } - - return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; -} -static int uv_mouse_select( - bContext *C, const float co[2], const bool extend, const bool deselect_all, const bool loop) -{ - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all, loop); - MEM_freeN(objects); - return ret; -} - -static int uv_select_exec(bContext *C, wmOperator *op) -{ - float co[2]; - - RNA_float_get_array(op->ptr, "location", co); - const bool extend = RNA_boolean_get(op->ptr, "extend"); - const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); - const bool loop = false; - - return uv_mouse_select(C, co, extend, deselect_all, loop); -} - -static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - ARegion *region = CTX_wm_region(C); - float co[2]; - - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); - RNA_float_set_array(op->ptr, "location", co); - - return uv_select_exec(C, op); -} - -static void UV_OT_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select"; - ot->description = "Select UV vertices"; - ot->idname = "UV_OT_select"; - ot->flag = OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_exec; - ot->invoke = uv_select_invoke; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* properties */ - PropertyRNA *prop; - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); - prop = RNA_def_boolean(ot->srna, - "deselect_all", - false, - "Deselect On Nothing", - "Deselect all when nothing under the cursor"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - RNA_def_float_vector( - ot->srna, - "location", - 2, - NULL, - -FLT_MAX, - FLT_MAX, - "Location", - "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", - -100.0f, - 100.0f); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Loop Select Operator - * \{ */ - -static int uv_select_loop_exec(bContext *C, wmOperator *op) -{ - float co[2]; - - RNA_float_get_array(op->ptr, "location", co); - const bool extend = RNA_boolean_get(op->ptr, "extend"); - const bool deselect_all = false; - const bool loop = true; - - return uv_mouse_select(C, co, extend, deselect_all, loop); -} - -static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - ARegion *region = CTX_wm_region(C); - float co[2]; - - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); - RNA_float_set_array(op->ptr, "location", co); - - return uv_select_loop_exec(C, op); -} - -static void UV_OT_select_loop(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Loop Select"; - ot->description = "Select a loop of connected UV vertices"; - ot->idname = "UV_OT_select_loop"; - ot->flag = OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_loop_exec; - ot->invoke = uv_select_loop_invoke; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* properties */ - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); - RNA_def_float_vector( - ot->srna, - "location", - 2, - NULL, - -FLT_MAX, - FLT_MAX, - "Location", - "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", - -100.0f, - 100.0f); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Linked Operator - * \{ */ - -static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick) -{ - SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - float limit[2]; - bool extend = true; - bool deselect = false; - bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE); - - UvNearestHit hit = UV_NEAREST_HIT_INIT; - - if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) { - BKE_report(op->reports, - RPT_ERROR, - "Select linked only works in face select mode when sync selection is enabled"); - return OPERATOR_CANCELLED; - } - - if (pick) { - extend = RNA_boolean_get(op->ptr, "extend"); - deselect = RNA_boolean_get(op->ptr, "deselect"); - } - uvedit_pixel_to_float(sima, limit, 0.05f); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - if (pick) { - float co[2]; - - if (event) { - /* invoke */ - ARegion *region = CTX_wm_region(C); - - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); - RNA_float_set_array(op->ptr, "location", co); - } - else { - /* exec */ - RNA_float_get_array(op->ptr, "location", co); - } - - if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) { - MEM_freeN(objects); - return OPERATOR_CANCELLED; - } - } - - if (!extend) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - uv_select_linked_multi(scene, - ima, - objects, - objects_len, - limit, - pick ? &hit : NULL, - extend, - deselect, - false, - select_faces); - - /* weak!, but works */ - Object **objects_free = objects; - if (pick) { - objects = &hit.ob; - objects_len = 1; - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - - MEM_SAFE_FREE(objects_free); - - return OPERATOR_FINISHED; -} - -static int uv_select_linked_exec(bContext *C, wmOperator *op) -{ - return uv_select_linked_internal(C, op, NULL, false); -} - -static void UV_OT_select_linked(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Linked"; - ot->description = "Select all UV vertices linked to the active UV map"; - ot->idname = "UV_OT_select_linked"; - - /* api callbacks */ - ot->exec = uv_select_linked_exec; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Linked (Cursor Pick) Operator - * \{ */ - -static int uv_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - return uv_select_linked_internal(C, op, event, true); -} - -static int uv_select_linked_pick_exec(bContext *C, wmOperator *op) -{ - return uv_select_linked_internal(C, op, NULL, true); -} - -static void UV_OT_select_linked_pick(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Linked Pick"; - ot->description = "Select all UV vertices linked under the mouse"; - ot->idname = "UV_OT_select_linked_pick"; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->invoke = uv_select_linked_pick_invoke; - ot->exec = uv_select_linked_pick_exec; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* properties */ - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); - RNA_def_boolean(ot->srna, - "deselect", - 0, - "Deselect", - "Deselect linked UV vertices rather than selecting them"); - RNA_def_float_vector( - ot->srna, - "location", - 2, - NULL, - -FLT_MAX, - FLT_MAX, - "Location", - "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", - -100.0f, - 100.0f); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Split Operator - * \{ */ - -/** - * \note This is based on similar use case to #MESH_OT_split(), which has a similar effect - * but in this case they are not joined to begin with (only having the behavior of being joined) - * so its best to call this #uv_select_split() instead of just split(), but assigned to the same - * key as #MESH_OT_split - Campbell. - */ -static int uv_select_split_exec(bContext *C, wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); - - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); - return OPERATOR_CANCELLED; - } - - bool changed_multi = false; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMesh *bm = BKE_editmesh_from_object(obedit)->bm; - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - bool is_sel = false; - bool is_unsel = false; - - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - /* are we all selected? */ - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { - is_sel = true; - } - else { - is_unsel = true; - } - - /* we have mixed selection, bail out */ - if (is_sel && is_unsel) { - break; - } - } - - if (is_sel && is_unsel) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag &= ~MLOOPUV_VERTSEL; - } - - changed = true; - } - } - - if (changed) { - changed_multi = true; - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL); - } - } - MEM_freeN(objects); - - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; -} - -static void UV_OT_select_split(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Split"; - ot->description = "Select only entirely selected faces"; - ot->idname = "UV_OT_select_split"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_split_exec; - ot->poll = ED_operator_uvedit; /* requires space image */ -} - -static void uv_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const short select) -{ - /* bmesh API handles flushing but not on de-select */ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode != SCE_SELECT_FACE) { - if (select == false) { - EDBM_deselect_flush(em); - } - else { - EDBM_select_flush(em); - } - } - - if (select == false) { - BM_select_history_validate(em->bm); - } - } -} - -static void uv_select_tag_update_for_object(Depsgraph *depsgraph, - const ToolSettings *ts, - Object *obedit) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); - } - else { - Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); - BKE_mesh_batch_cache_dirty_tag(obedit_eval->data, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT); - /* Only for region redraw. */ - WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select/Tag Flushing Utils - * - * Utility functions to flush the uv-selection from tags. - * \{ */ - -/** - * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face - */ -static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, - BMEditMesh *em, - UvVertMap *vmap, - const uint efa_index, - BMLoop *l, - const bool select, - const int cd_loop_uv_offset) -{ - UvMapVert *start_vlist = NULL, *vlist_iter; - BMFace *efa_vlist; - - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - - vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); - - while (vlist_iter) { - if (vlist_iter->separate) { - start_vlist = vlist_iter; - } - - if (efa_index == vlist_iter->poly_index) { - break; - } - - vlist_iter = vlist_iter->next; - } - - vlist_iter = start_vlist; - while (vlist_iter) { - - if (vlist_iter != start_vlist && vlist_iter->separate) { - break; - } - - if (efa_index != vlist_iter->poly_index) { - BMLoop *l_other; - efa_vlist = BM_face_at_index(em->bm, vlist_iter->poly_index); - /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */ - - l_other = BM_iter_at_index( - em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index); - - uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset); - } - vlist_iter = vlist_iter->next; - } -} - -/** - * Flush the selection from face tags based on sticky and selection modes. - * - * needed because settings the selection a face is done in a number of places but it also - * needs to respect the sticky modes for the UV verts, so dealing with the sticky modes - * is best done in a separate function. - * - * \note This function is very similar to #uv_select_flush_from_tag_loop, - * be sure to update both upon changing. - */ -static void uv_select_flush_from_tag_face(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select) -{ - /* Selecting UV Faces with some modes requires us to change - * the selection in other faces (depending on the sticky mode). - * - * This only needs to be done when the Mesh is not used for - * selection (so for sticky modes, vertex or location based). */ - - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { - /* Tag all verts as untouched, then touch the ones that have a face center - * in the loop and select all MLoopUV's that use a touched vert. */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - } - } - } - - /* now select tagged verts */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - } - else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { - struct UvVertMap *vmap; - float limit[2]; - uint efa_index; - - uvedit_pixel_to_float(sima, limit, 0.05); - - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, limit, false, false); - if (vmap == NULL) { - return; - } - - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - uv_select_flush_from_tag_sticky_loc_internal( - scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); - } - } - } - BM_uv_vert_map_free(vmap); - } - else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - uvedit_face_select_set(scene, em, efa, select, false, cd_loop_uv_offset); - } - } - } -} - -/** - * Flush the selection from loop tags based on sticky and selection modes. - * - * needed because settings the selection a face is done in a number of places but it also needs - * to respect the sticky modes for the UV verts, so dealing with the sticky modes is best done - * in a separate function. - * - * \note This function is very similar to #uv_select_flush_from_tag_loop, - * be sure to update both upon changing. - */ -static void uv_select_flush_from_tag_loop(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select) -{ - /* Selecting UV Loops with some modes requires us to change - * the selection in other faces (depending on the sticky mode). - * - * This only needs to be done when the Mesh is not used for - * selection (so for sticky modes, vertex or location based). */ - - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { - /* Tag all verts as untouched, then touch the ones that have a face center - * in the loop and select all MLoopUV's that use a touched vert. */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - } - } - } - - /* now select tagged verts */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - } - else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { - struct UvVertMap *vmap; - float limit[2]; - uint efa_index; - - uvedit_pixel_to_float(sima, limit, 0.05); - - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, limit, false, false); - if (vmap == NULL) { - return; - } - - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - uv_select_flush_from_tag_sticky_loc_internal( - scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); - } - } - } - BM_uv_vert_map_free(vmap); - } - else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - } -} - -/** \} */ - -#define UV_SELECT_ISLAND_LIMIT \ - float limit[2]; \ - uvedit_pixel_to_float(sima, limit, 0.05f) - -/* -------------------------------------------------------------------- */ -/** \name Box Select Operator - * \{ */ - -static int uv_box_select_exec(bContext *C, wmOperator *op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - ARegion *region = CTX_wm_region(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - rctf rectf; - bool pinned; - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); - - /* get rectangle from operator */ - WM_operator_properties_border_to_rctf(op, &rectf); - UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); - - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - const bool select = (sel_op != SEL_OP_SUB); - const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); - - pinned = RNA_boolean_get(op->ptr, "pinned"); - - UV_SELECT_ISLAND_LIMIT; - - bool changed_multi = false; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - /* don't indent to avoid diff noise! */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* do actual selection */ - if (use_face_center && !pinned) { - /* handle face selection mode */ - float cent[2]; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* assume not touched */ - BM_elem_flag_disable(efa, BM_ELEM_TAG); - - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - uv_poly_center(efa, cent, cd_loop_uv_offset); - if (BLI_rctf_isect_pt_v(&rectf, cent)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } - } - - /* (de)selects all tagged faces and deals with sticky modes */ - if (changed) { - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - } - else { - /* other selection modes */ - changed = true; - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - bool has_selected = false; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { - if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) { - /* UV_SYNC_SELECTION - can't do pinned selection */ - if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - has_selected = true; - } - } - else if (pinned) { - if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - } - } - } - } - if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { - UvNearestHit hit = { - .ob = obedit, - .efa = efa, - }; - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); - } - } - - if (sima->sticky == SI_STICKY_VERTEX) { - uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); - } - } - - if (changed || use_pre_deselect) { - changed_multi = true; - - uv_select_sync_flush(ts, em, select); - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - - MEM_freeN(objects); - - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; -} - -static void UV_OT_select_box(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Box Select"; - ot->description = "Select UV vertices using box selection"; - ot->idname = "UV_OT_select_box"; - - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = uv_box_select_exec; - ot->modal = WM_gesture_box_modal; - ot->poll = ED_operator_uvedit_space_image; /* requires space image */ - ot->cancel = WM_gesture_box_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only"); - - WM_operator_properties_gesture_box(ot); - WM_operator_properties_select_operation_simple(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Circle Select Operator - * \{ */ - -static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2]) -{ - /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ - float x, y; - x = (uv[0] - offset[0]) * ellipse[0]; - y = (uv[1] - offset[1]) * ellipse[1]; - return ((x * x + y * y) < 1.0f); -} - -static int uv_circle_select_exec(bContext *C, wmOperator *op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - const ToolSettings *ts = scene->toolsettings; - ARegion *region = CTX_wm_region(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - int x, y, radius, width, height; - float zoomx, zoomy, offset[2], ellipse[2]; - - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); - - /* get operator properties */ - x = RNA_int_get(op->ptr, "x"); - y = RNA_int_get(op->ptr, "y"); - radius = RNA_int_get(op->ptr, "radius"); - - /* compute ellipse size and location, not a circle since we deal - * with non square image. ellipse is normalized, r = 1.0. */ - ED_space_image_get_size(sima, &width, &height); - ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); - - ellipse[0] = width * zoomx / radius; - ellipse[1] = height * zoomy / radius; - - UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); - - UV_SELECT_ISLAND_LIMIT; - - bool changed_multi = false; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), - WM_gesture_is_modal_first(op->customdata)); - const bool select = (sel_op != SEL_OP_SUB); - const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); - - if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* do selection */ - if (use_face_center) { - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(efa, BM_ELEM_TAG); - /* assume not touched */ - if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { - float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); - if (uv_inside_circle(cent, offset, ellipse)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } - } - - /* (de)selects all tagged faces and deals with sticky modes */ - if (changed) { - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - } - else { - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - bool has_selected = false; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (uv_inside_circle(luv->uv, offset, ellipse)) { - changed = true; - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - has_selected = true; - } - } - } - if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { - UvNearestHit hit = { - .ob = obedit, - .efa = efa, - }; - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); - } - } - - if (sima->sticky == SI_STICKY_VERTEX) { - uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); - } - } - - if (changed || use_pre_deselect) { - changed_multi = true; - - uv_select_sync_flush(ts, em, select); - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - MEM_freeN(objects); - - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; -} - -static void UV_OT_select_circle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Circle Select"; - ot->description = "Select UV vertices using circle selection"; - ot->idname = "UV_OT_select_circle"; - - /* api callbacks */ - ot->invoke = WM_gesture_circle_invoke; - ot->modal = WM_gesture_circle_modal; - ot->exec = uv_circle_select_exec; - ot->poll = ED_operator_uvedit_space_image; /* requires space image */ - ot->cancel = WM_gesture_circle_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_gesture_circle(ot); - WM_operator_properties_select_operation_simple(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Lasso Select Operator - * \{ */ - -static bool do_lasso_select_mesh_uv(bContext *C, - const int mcords[][2], - short moves, - const eSelectOp sel_op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); - ARegion *region = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); - const bool select = (sel_op != SEL_OP_SUB); - const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); - - BMIter iter, liter; - - BMFace *efa; - BMLoop *l; - int screen_uv[2]; - bool changed_multi = false; - rcti rect; - - UV_SELECT_ISLAND_LIMIT; - - BLI_lasso_boundbox(&rect, mcords, moves); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - /* don't indent to avoid diff noise! */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - - bool changed = false; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if (use_face_center) { /* Face Center Sel */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(efa, BM_ELEM_TAG); - /* assume not touched */ - if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { - float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); - - if (UI_view2d_view_to_region_clip( - ®ion->v2d, cent[0], cent[1], &screen_uv[0], &screen_uv[1]) && - BLI_rcti_isect_pt_v(&rect, screen_uv) && - BLI_lasso_is_point_inside( - mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } - } - - /* (de)selects all tagged faces and deals with sticky modes */ - if (changed) { - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - } - else { /* Vert Sel */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - bool has_selected = false; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (UI_view2d_view_to_region_clip( - ®ion->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]) && - BLI_rcti_isect_pt_v(&rect, screen_uv) && - BLI_lasso_is_point_inside( - mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - changed = true; - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - has_selected = true; - } - } - } - if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { - UvNearestHit hit = { - .ob = obedit, - .efa = efa, - }; - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); - } - } - - if (sima->sticky == SI_STICKY_VERTEX) { - uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); - } - } - - if (changed || use_pre_deselect) { - changed_multi = true; - - uv_select_sync_flush(ts, em, select); - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - MEM_freeN(objects); - - return changed_multi; -} - -static int uv_lasso_select_exec(bContext *C, wmOperator *op) -{ - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); - - if (mcords) { - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - bool changed = do_lasso_select_mesh_uv(C, mcords, mcords_tot, sel_op); - MEM_freeN((void *)mcords); - - return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; - } - - return OPERATOR_PASS_THROUGH; -} - -static void UV_OT_select_lasso(wmOperatorType *ot) -{ - ot->name = "Lasso Select UV"; - ot->description = "Select UVs using lasso selection"; - ot->idname = "UV_OT_select_lasso"; - - ot->invoke = WM_gesture_lasso_invoke; - ot->modal = WM_gesture_lasso_modal; - ot->exec = uv_lasso_select_exec; - ot->poll = ED_operator_uvedit_space_image; - ot->cancel = WM_gesture_lasso_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_gesture_lasso(ot); - WM_operator_properties_select_operation_simple(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Snap Cursor Operator * \{ */ @@ -4379,314 +1473,6 @@ static void UV_OT_pin(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Select Pinned UV's Operator - * \{ */ - -static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - bool changed = false; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_PINNED) { - uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); - changed = true; - } - } - } - - if (changed) { - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static void UV_OT_select_pinned(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Selected Pinned"; - ot->description = "Select all pinned UV vertices"; - ot->idname = "UV_OT_select_pinned"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_pinned_exec; - ot->poll = ED_operator_uvedit; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Overlap Operator - * \{ */ - -BLI_INLINE uint overlap_hash(const void *overlap_v) -{ - const BVHTreeOverlap *overlap = overlap_v; - - /* Designed to treat (A,B) and (B,A) as the same. */ - int x = overlap->indexA; - int y = overlap->indexB; - if (x > y) { - SWAP(int, x, y); - } - return BLI_hash_int_2d(x, y); -} - -BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v) -{ - const BVHTreeOverlap *a = a_v; - const BVHTreeOverlap *b = b_v; - return !((a->indexA == b->indexA && a->indexB == b->indexB) || - (a->indexA == b->indexB && a->indexB == b->indexA)); -} - -struct UVOverlapData { - int ob_index; - int face_index; - float tri[3][2]; -}; - -static int uv_select_overlap(bContext *C, const bool extend) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - /* Calculate maximum number of tree nodes and prepare initial selection. */ - uint uv_tri_len = 0; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); - BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - if (!extend) { - uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); - } - - BMIter iter; - BMFace *efa; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { - continue; - } - uv_tri_len += efa->len - 2; - } - } - - struct UVOverlapData *overlap_data = MEM_mallocN(sizeof(struct UVOverlapData) * uv_tri_len, - "UvOverlapData"); - BVHTree *uv_tree = BLI_bvhtree_new(uv_tri_len, 0.0f, 4, 6); - - /* Use a global data index when inserting into the BVH. */ - int data_index = 0; - - int face_len_alloc = 3; - float(*uv_verts)[2] = MEM_mallocN(sizeof(*uv_verts) * face_len_alloc, "UvOverlapCoords"); - uint(*indices)[3] = MEM_mallocN(sizeof(*indices) * (face_len_alloc - 2), "UvOverlapTris"); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMIter iter, liter; - BMFace *efa; - BMLoop *l; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* Triangulate each UV face and store it inside the BVH. */ - int face_index; - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) { - - if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { - continue; - } - - const uint face_len = efa->len; - const uint tri_len = face_len - 2; - - if (face_len_alloc < face_len) { - MEM_freeN(uv_verts); - MEM_freeN(indices); - uv_verts = MEM_mallocN(sizeof(*uv_verts) * face_len, "UvOverlapCoords"); - indices = MEM_mallocN(sizeof(*indices) * tri_len, "UvOverlapTris"); - face_len_alloc = face_len; - } - - int vert_index; - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, vert_index) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - copy_v2_v2(uv_verts[vert_index], luv->uv); - } - - BLI_polyfill_calc(uv_verts, face_len, 0, indices); - - for (int t = 0; t < tri_len; t++) { - overlap_data[data_index].ob_index = ob_index; - overlap_data[data_index].face_index = face_index; - - /* BVH needs 3D, overlap data uses 2D. */ - const float tri[3][3] = { - {UNPACK2(uv_verts[indices[t][0]]), 0.0f}, - {UNPACK2(uv_verts[indices[t][1]]), 0.0f}, - {UNPACK2(uv_verts[indices[t][2]]), 0.0f}, - }; - - copy_v2_v2(overlap_data[data_index].tri[0], tri[0]); - copy_v2_v2(overlap_data[data_index].tri[1], tri[1]); - copy_v2_v2(overlap_data[data_index].tri[2], tri[2]); - - BLI_bvhtree_insert(uv_tree, data_index, &tri[0][0], 3); - data_index++; - } - } - } - BLI_assert(data_index == uv_tri_len); - - MEM_freeN(uv_verts); - MEM_freeN(indices); - - BLI_bvhtree_balance(uv_tree); - - uint tree_overlap_len; - BVHTreeOverlap *overlap = BLI_bvhtree_overlap(uv_tree, uv_tree, &tree_overlap_len, NULL, NULL); - - if (overlap != NULL) { - GSet *overlap_set = BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, tree_overlap_len); - - for (int i = 0; i < tree_overlap_len; i++) { - /* Skip overlaps against yourself. */ - if (overlap[i].indexA == overlap[i].indexB) { - continue; - } - - /* Skip overlaps that have already been tested. */ - if (!BLI_gset_add(overlap_set, &overlap[i])) { - continue; - } - - const struct UVOverlapData *o_a = &overlap_data[overlap[i].indexA]; - const struct UVOverlapData *o_b = &overlap_data[overlap[i].indexB]; - Object *obedit_a = objects[o_a->ob_index]; - Object *obedit_b = objects[o_b->ob_index]; - BMEditMesh *em_a = BKE_editmesh_from_object(obedit_a); - BMEditMesh *em_b = BKE_editmesh_from_object(obedit_b); - BMFace *face_a = em_a->bm->ftable[o_a->face_index]; - BMFace *face_b = em_b->bm->ftable[o_b->face_index]; - const int cd_loop_uv_offset_a = CustomData_get_offset(&em_a->bm->ldata, CD_MLOOPUV); - const int cd_loop_uv_offset_b = CustomData_get_offset(&em_b->bm->ldata, CD_MLOOPUV); - - /* Skip if both faces are already selected. */ - if (uvedit_face_select_test(scene, face_a, cd_loop_uv_offset_a) && - uvedit_face_select_test(scene, face_b, cd_loop_uv_offset_b)) { - continue; - } - - /* Main tri-tri overlap test. */ - const float endpoint_bias = -1e-4f; - const float(*t1)[2] = o_a->tri; - const float(*t2)[2] = o_b->tri; - float vi[2]; - bool result = ( - /* Don't use 'isect_tri_tri_v2' here - * because it's important to ignore overlap at end-points. */ - isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[0], t2[1], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[1], t2[2], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[2], t2[0], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[0], t2[1], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[1], t2[2], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[2], t2[0], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[0], t2[1], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[1], t2[2], endpoint_bias, vi) == 1 || - isect_point_tri_v2(t1[0], t2[0], t2[1], t2[2]) != 0 || - isect_point_tri_v2(t2[0], t1[0], t1[1], t1[2]) != 0); - - if (result) { - uvedit_face_select_enable(scene, em_a, face_a, false, cd_loop_uv_offset_a); - uvedit_face_select_enable(scene, em_b, face_b, false, cd_loop_uv_offset_b); - } - } - - BLI_gset_free(overlap_set, NULL); - MEM_freeN(overlap); - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - uv_select_tag_update_for_object(depsgraph, scene->toolsettings, objects[ob_index]); - } - - BLI_bvhtree_free(uv_tree); - - MEM_freeN(overlap_data); - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static int uv_select_overlap_exec(bContext *C, wmOperator *op) -{ - bool extend = RNA_boolean_get(op->ptr, "extend"); - return uv_select_overlap(C, extend); -} - -static void UV_OT_select_overlap(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Overlap"; - ot->description = "Select all UV faces which overlap each other"; - ot->idname = "UV_OT_select_overlap"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_overlap_exec; - ot->poll = ED_operator_uvedit; - - /* properties */ - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Hide Operator * \{ */ @@ -5334,6 +2120,7 @@ static void UV_OT_mark_seam(wmOperatorType *ot) void ED_operatortypes_uvedit(void) { + /* uvedit_select.c */ WM_operatortype_append(UV_OT_select_all); WM_operatortype_append(UV_OT_select); WM_operatortype_append(UV_OT_select_loop); diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h index 2b80241e6e3..53188ea42bb 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.h +++ b/source/blender/editors/uvedit/uvedit_parametrizer.h @@ -21,12 +21,12 @@ * \ingroup eduv */ +#include "BLI_sys_types.h" // for intptr_t support + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" // for intptr_t support - typedef void ParamHandle; /* handle to a set of charts */ typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */ typedef enum ParamBool { diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c new file mode 100644 index 00000000000..6e931b56a85 --- /dev/null +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -0,0 +1,3415 @@ +/* + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup eduv + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_image_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" + +#include "BLI_alloca.h" +#include "BLI_blenlib.h" +#include "BLI_hash.h" +#include "BLI_kdopbvh.h" +#include "BLI_lasso_2d.h" +#include "BLI_math.h" +#include "BLI_polyfill_2d.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_editmesh.h" +#include "BKE_layer.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" +#include "BKE_report.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "ED_image.h" +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_select_utils.h" +#include "ED_uvedit.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_view2d.h" + +#include "uvedit_intern.h" + +static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action); +static void uv_select_all_perform_multi( + Scene *scene, Image *ima, Object **objects, const uint objects_len, int action); +static void uv_select_flush_from_tag_face(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select); +static void uv_select_flush_from_tag_loop(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select); +static void uv_select_tag_update_for_object(Depsgraph *depsgraph, + const ToolSettings *ts, + Object *obedit); + +/* -------------------------------------------------------------------- */ +/** \name Visibility and Selection Utilities + * \{ */ + +static void uv_select_island_limit_default(SpaceImage *sima, float r_limit[2]) +{ + uvedit_pixel_to_float(sima, 0.05f, r_limit); +} + +static void uvedit_vertex_select_tagged(BMEditMesh *em, + Scene *scene, + bool select, + int cd_loop_uv_offset) +{ + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } +} + +bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0); + } + else { + return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT)); + } +} +bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa) +{ + return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa); +} + +bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa) +{ + if (ts->uv_flag & UV_SHOW_SAME_IMAGE) { + Image *face_image; + ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL); + return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false; + } + else { + return uvedit_face_visible_nolocal_ex(ts, efa); + } +} +bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa) +{ + return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa); +} + +bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + return (BM_elem_flag_test(efa, BM_ELEM_SELECT)); + } + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (!(luv->flag & MLOOPUV_VERTSEL)) { + return false; + } + } + + return true; + } +} +bool uvedit_face_select_test(const Scene *scene, BMFace *efa, const int cd_loop_uv_offset) +{ + return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset); +} + +bool uvedit_face_select_set(const struct Scene *scene, + struct BMEditMesh *em, + struct BMFace *efa, + const bool select, + const bool do_history, + const int cd_loop_uv_offset) +{ + if (select) { + return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset); + } + else { + return uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); + } +} + +bool uvedit_face_select_enable(const Scene *scene, + BMEditMesh *em, + BMFace *efa, + const bool do_history, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + BM_face_select_set(em->bm, efa, true); + if (do_history) { + BM_select_history_store(em->bm, (BMElem *)efa); + } + } + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag |= MLOOPUV_VERTSEL; + } + + return true; + } + + return false; +} + +bool uvedit_face_select_disable(const Scene *scene, + BMEditMesh *em, + BMFace *efa, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + BM_face_select_set(em->bm, efa, false); + } + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag &= ~MLOOPUV_VERTSEL; + } + + return true; + } + + return false; +} + +bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + return BM_elem_flag_test(l->f, BM_ELEM_SELECT); + } + else if (ts->selectmode == SCE_SELECT_EDGE) { + return BM_elem_flag_test(l->e, BM_ELEM_SELECT); + } + else { + return BM_elem_flag_test(l->v, BM_ELEM_SELECT) && + BM_elem_flag_test(l->next->v, BM_ELEM_SELECT); + } + } + else { + MLoopUV *luv1, *luv2; + + luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL); + } +} +bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) +{ + return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); +} + +void uvedit_edge_select_set(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool select, + const bool do_history, + const int cd_loop_uv_offset) + +{ + if (select) { + uvedit_edge_select_enable(em, scene, l, do_history, cd_loop_uv_offset); + } + else { + uvedit_edge_select_disable(em, scene, l, cd_loop_uv_offset); + } +} + +void uvedit_edge_select_enable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool do_history, + const int cd_loop_uv_offset) + +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, true); + } + else if (ts->selectmode & SCE_SELECT_EDGE) { + BM_edge_select_set(em->bm, l->e, true); + } + else { + BM_vert_select_set(em->bm, l->e->v1, true); + BM_vert_select_set(em->bm, l->e->v2, true); + } + + if (do_history) { + BM_select_history_store(em->bm, (BMElem *)l->e); + } + } + else { + MLoopUV *luv1, *luv2; + + luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + luv1->flag |= MLOOPUV_VERTSEL; + luv2->flag |= MLOOPUV_VERTSEL; + } +} + +void uvedit_edge_select_disable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const int cd_loop_uv_offset) + +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, false); + } + else if (ts->selectmode & SCE_SELECT_EDGE) { + BM_edge_select_set(em->bm, l->e, false); + } + else { + BM_vert_select_set(em->bm, l->e->v1, false); + BM_vert_select_set(em->bm, l->e->v2, false); + } + } + else { + MLoopUV *luv1, *luv2; + + luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + luv1->flag &= ~MLOOPUV_VERTSEL; + luv2->flag &= ~MLOOPUV_VERTSEL; + } +} + +bool uvedit_uv_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + return BM_elem_flag_test_bool(l->f, BM_ELEM_SELECT); + } + else { + return BM_elem_flag_test_bool(l->v, BM_ELEM_SELECT); + } + } + else { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + return (luv->flag & MLOOPUV_VERTSEL) != 0; + } +} +bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) +{ + return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); +} + +void uvedit_uv_select_set(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool select, + const bool do_history, + const int cd_loop_uv_offset) +{ + if (select) { + uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset); + } + else { + uvedit_uv_select_disable(em, scene, l, cd_loop_uv_offset); + } +} + +void uvedit_uv_select_enable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool do_history, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, true); + } + else { + BM_vert_select_set(em->bm, l->v, true); + } + + if (do_history) { + BM_select_history_remove(em->bm, (BMElem *)l->v); + } + } + else { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag |= MLOOPUV_VERTSEL; + } +} + +void uvedit_uv_select_disable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, false); + } + else { + BM_vert_select_set(em->bm, l->v, false); + } + } + else { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag &= ~MLOOPUV_VERTSEL; + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Find Nearest Elements + * \{ */ + +bool uv_find_nearest_edge( + Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv, *luv_next; + int i; + bool found = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); + + if (dist_test_sq < hit->dist_sq) { + hit->efa = efa; + + hit->l = l; + hit->luv = luv; + hit->luv_next = luv_next; + hit->lindex = i; + + hit->dist_sq = dist_test_sq; + found = true; + } + } + } + return found; +} + +bool uv_find_nearest_edge_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float co[2], + UvNearestHit *hit_final) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) { + hit_final->ob = obedit; + found = true; + } + } + return found; +} + +bool uv_find_nearest_face( + Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + bool found = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { + hit.dist_sq = dist_sq_init; + hit.l = NULL; + hit.luv = hit.luv_next = NULL; + + BMIter iter; + BMFace *efa; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); + + const float dist_test_sq = len_squared_v2v2(co, cent); + + if (dist_test_sq < hit.dist_sq) { + hit.efa = efa; + hit.dist_sq = dist_test_sq; + found = true; + } + } + } + if (found) { + *hit_final = hit; + } + return found; +} + +bool uv_find_nearest_face_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float co[2], + UvNearestHit *hit_final) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) { + hit_final->ob = obedit; + found = true; + } + } + return found; +} + +static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset) +{ + const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv; + const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv; + const float *uv_next = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset))->uv; + + return ((line_point_side_v2(uv_prev, uv_curr, co) > 0.0f) && + (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f)); +} + +bool uv_find_nearest_vert(Scene *scene, + Image *ima, + Object *obedit, + float const co[2], + const float penalty_dist, + UvNearestHit *hit_final) +{ + bool found = false; + + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { + hit.dist_sq = dist_sq_init; + + hit.l = NULL; + hit.luv = hit.luv_next = NULL; + + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMIter iter; + + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMIter liter; + BMLoop *l; + int i; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + float dist_test_sq; + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist; + dist_test_sq = square_f(dist_test_sq); + } + else { + dist_test_sq = len_squared_v2v2(co, luv->uv); + } + + if (dist_test_sq <= hit.dist_sq) { + if (dist_test_sq == hit.dist_sq) { + if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { + continue; + } + } + + hit.dist_sq = dist_test_sq; + + hit.l = l; + hit.luv = luv; + hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + hit.efa = efa; + hit.lindex = i; + found = true; + } + } + } + } + + if (found) { + *hit_final = hit; + } + + return found; +} + +bool uv_find_nearest_vert_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + float const co[2], + const float penalty_dist, + UvNearestHit *hit_final) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) { + hit_final->ob = obedit; + found = true; + } + } + return found; +} + +bool ED_uvedit_nearest_uv(const Scene *scene, + Object *obedit, + Image *ima, + const float co[2], + float *dist_sq, + float r_uv[2]) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMIter iter; + BMFace *efa; + const float *uv_best = NULL; + float dist_best = *dist_sq; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv; + const float dist_test = len_squared_v2v2(co, uv); + if (dist_best > dist_test) { + dist_best = dist_test; + uv_best = uv; + } + } while ((l_iter = l_iter->next) != l_first); + } + + if (uv_best != NULL) { + copy_v2_v2(r_uv, uv_best); + *dist_sq = dist_best; + return true; + } + else { + return false; + } +} + +bool ED_uvedit_nearest_uv_multi(const Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float co[2], + float *dist_sq, + float r_uv[2]) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) { + found = true; + } + } + return found; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop Select + * \{ */ + +static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first) +{ + UvMapVert *iterv; + int count = 0; + + for (iterv = first; iterv; iterv = iterv->next) { + if (iterv->separate && iterv != first) { + break; + } + + count++; + } + + if (count < 5) { + first->flag = 1; + } +} + +static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l) +{ + UvMapVert *iterv, *first; + first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); + + for (iterv = first; iterv; iterv = iterv->next) { + if (iterv->separate) { + first = iterv; + } + if (iterv->poly_index == BM_elem_index_get(efa)) { + return first; + } + } + + return NULL; +} + +static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, + UvMapVert *first1, + UvMapVert *first2, + int *totface) +{ + UvMapVert *iterv1, *iterv2; + BMFace *efa; + int tot = 0; + + /* count number of faces this edge has */ + for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { + if (iterv1->separate && iterv1 != first1) { + break; + } + + for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { + if (iterv2->separate && iterv2 != first2) { + break; + } + + if (iterv1->poly_index == iterv2->poly_index) { + /* if face already tagged, don't do this edge */ + efa = BM_face_at_index(em->bm, iterv1->poly_index); + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + return false; + } + + tot++; + break; + } + } + } + + if (*totface == 0) { /* start edge */ + *totface = tot; + } + else if (tot != *totface) { /* check for same number of faces as start edge */ + return false; + } + + /* tag the faces */ + for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { + if (iterv1->separate && iterv1 != first1) { + break; + } + + for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { + if (iterv2->separate && iterv2 != first2) { + break; + } + + if (iterv1->poly_index == iterv2->poly_index) { + efa = BM_face_at_index(em->bm, iterv1->poly_index); + BM_elem_flag_enable(efa, BM_ELEM_TAG); + break; + } + } + } + + return true; +} + +static int uv_select_edgeloop(Scene *scene, + Image *ima, + Object *obedit, + UvNearestHit *hit, + const float limit[2], + const bool extend) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMIter iter, liter; + BMLoop *l; + UvVertMap *vmap; + UvMapVert *iterv_curr; + UvMapVert *iterv_next; + int starttotf; + bool looking, select; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* setup */ + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); + + BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); + + if (!extend) { + uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); + } + + BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); + + /* set flags for first face and verts */ + iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); + iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); + uv_select_edgeloop_vertex_loop_flag(iterv_curr); + uv_select_edgeloop_vertex_loop_flag(iterv_next); + + starttotf = 0; + uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf); + + /* sorry, first edge isn't even ok */ + looking = !(iterv_curr->flag == 0 && iterv_next->flag == 0); + + /* iterate */ + while (looking) { + looking = false; + + /* find correct valence edges which are not tagged yet, but connect to tagged one */ + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && + uvedit_face_visible_test(scene, obedit, ima, efa)) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + /* check face not hidden and not tagged */ + if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) { + continue; + } + if (!(iterv_next = uv_select_edgeloop_vertex_map_get(vmap, efa, l->next))) { + continue; + } + + /* check if vertex is tagged and has right valence */ + if (iterv_curr->flag || iterv_next->flag) { + if (uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf)) { + looking = true; + BM_elem_flag_enable(efa, BM_ELEM_TAG); + + uv_select_edgeloop_vertex_loop_flag(iterv_curr); + uv_select_edgeloop_vertex_loop_flag(iterv_next); + break; + } + } + } + } + } + } + + /* do the actual select/deselect */ + iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); + iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); + iterv_curr->flag = 1; + iterv_next->flag = 1; + + if (extend) { + select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset)); + } + else { + select = true; + } + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l); + + if (iterv_curr->flag) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + + /* cleanup */ + BM_uv_vert_map_free(vmap); + + return (select) ? 1 : -1; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked + * \{ */ + +static void uv_select_linked_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float limit[2], + UvNearestHit *hit_final, + bool extend, + bool deselect, + bool toggle, + bool select_faces) +{ + /* loop over objects, or just use hit_final->ob */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + if (hit_final && ob_index != 0) { + break; + } + Object *obedit = hit_final ? hit_final->ob : objects[ob_index]; + + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + UvVertMap *vmap; + UvMapVert *vlist, *iterv, *startv; + int i, stacksize = 0, *stack; + uint a; + char *flag; + + BMEditMesh *em = BKE_editmesh_from_object(obedit); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + 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 + * this made *every* projection split the island into front/back islands. + * Keep 'use_winding' to false, see: T50970. + * + * Better solve this by having a delimit option for select-linked operator, + * keeping island-select working as is. */ + vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false); + + if (vmap == NULL) { + continue; + } + + stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack"); + flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag"); + + if (hit_final == NULL) { + /* Use existing selection */ + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (select_faces) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + } + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_VERTSEL) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + + break; + } + } + } + } + } + } + else { + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + if (efa == hit_final->efa) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + break; + } + } + } + + while (stacksize > 0) { + + stacksize--; + a = stack[stacksize]; + + efa = BM_face_at_index(em->bm, a); + + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + + /* make_uv_vert_map_EM sets verts tmp.l to the indices */ + vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); + + startv = vlist; + + for (iterv = vlist; iterv; iterv = iterv->next) { + if (iterv->separate) { + startv = iterv; + } + if (iterv->poly_index == a) { + break; + } + } + + for (iterv = startv; iterv; iterv = iterv->next) { + if ((startv != iterv) && (iterv->separate)) { + break; + } + else if (!flag[iterv->poly_index]) { + flag[iterv->poly_index] = 1; + stack[stacksize] = iterv->poly_index; + stacksize++; + } + } + } + } + + /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */ + if ((toggle == true) && (extend == false) && (deselect == false)) { + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + bool found_selected = false; + if (!flag[a]) { + continue; + } + + if (select_faces) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + found_selected = true; + } + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_VERTSEL) { + found_selected = true; + } + } + + if (found_selected) { + deselect = true; + break; + } + } + } + } + +#define SET_SELECTION(value) \ + if (select_faces) { \ + BM_face_select_set(em->bm, efa, value); \ + } \ + else { \ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \ + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \ + luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \ + } \ + } \ + (void)0 + + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + if (!flag[a]) { + if (!extend && !deselect && !toggle) { + SET_SELECTION(false); + } + continue; + } + + if (!deselect) { + SET_SELECTION(true); + } + else { + SET_SELECTION(false); + } + } + +#undef SET_SELECTION + + MEM_freeN(stack); + MEM_freeN(flag); + BM_uv_vert_map_free(vmap); + } +} + +/** + * \warning This returns first selected UV, + * not ideal in many cases since there could be multiple. + */ +const float *uvedit_first_selected_uv_from_vertex( + Scene *scene, Object *obedit, Image *ima, BMVert *eve, const int cd_loop_uv_offset) +{ + BMIter liter; + BMLoop *l; + + BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { + if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) { + continue; + } + + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + return luv->uv; + } + } + + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More/Less Operator + * \{ */ + +static int uv_select_more_less(bContext *C, const bool select) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + SpaceImage *sima = CTX_wm_space_image(C); + + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + const ToolSettings *ts = scene->toolsettings; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + const bool is_uv_face_selectmode = (ts->uv_selectmode == UV_SELECT_FACE); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (select) { + EDBM_select_more(em, true); + } + else { + EDBM_select_less(em, true); + } + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + continue; + } + + if (is_uv_face_selectmode) { + + /* clear tags */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); + + /* mark loops to be selected */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + +#define IS_SEL 1 +#define IS_UNSEL 2 + + int sel_state = 0; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (luv->flag & MLOOPUV_VERTSEL) { + sel_state |= IS_SEL; + } + else { + sel_state |= IS_UNSEL; + } + + /* if we have a mixed selection, tag to grow it */ + if (sel_state == (IS_SEL | IS_UNSEL)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + break; + } + } + +#undef IS_SEL +#undef IS_UNSEL + } + } + } + else { + + /* clear tags */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + BM_elem_flag_disable(l, BM_ELEM_TAG); + } + } + + /* mark loops to be selected */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (((luv->flag & MLOOPUV_VERTSEL) != 0) == select) { + BM_elem_flag_enable(l->next, BM_ELEM_TAG); + BM_elem_flag_enable(l->prev, BM_ELEM_TAG); + changed = true; + } + } + } + } + } + + if (changed) { + if (is_uv_face_selectmode) { + /* Select tagged faces. */ + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + else { + /* Select tagged loops. */ + uv_select_flush_from_tag_loop(sima, scene, obedit, select); + } + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + } + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +static int uv_select_more_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return uv_select_more_less(C, true); +} + +void UV_OT_select_more(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->description = "Select more UV vertices connected to initial selection"; + ot->idname = "UV_OT_select_more"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_more_exec; + ot->poll = ED_operator_uvedit_space_image; +} + +static int uv_select_less_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return uv_select_more_less(C, false); +} + +void UV_OT_select_less(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->description = "Deselect UV vertices at the boundary of each selection region"; + ot->idname = "UV_OT_select_less"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_less_exec; + ot->poll = ED_operator_uvedit_space_image; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name (De)Select All Operator + * \{ */ + +bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit) +{ + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + return (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel); + } + else { + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (luv->flag & MLOOPUV_VERTSEL) { + return true; + } + } + } + } + return false; +} + +bool uvedit_select_is_any_selected_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uvedit_select_is_any_selected(scene, ima, obedit)) { + found = true; + break; + } + } + return found; +} + +static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action) +{ + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if (action == SEL_TOGGLE) { + action = uvedit_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT; + } + + if (ts->uv_flag & UV_SYNC_SELECTION) { + switch (action) { + case SEL_TOGGLE: + EDBM_select_toggle_all(em); + break; + case SEL_SELECT: + EDBM_flag_enable_all(em, BM_ELEM_SELECT); + break; + case SEL_DESELECT: + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + break; + case SEL_INVERT: + EDBM_select_swap(em); + EDBM_selectmode_flush(em); + break; + } + } + else { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + switch (action) { + case SEL_SELECT: + luv->flag |= MLOOPUV_VERTSEL; + break; + case SEL_DESELECT: + luv->flag &= ~MLOOPUV_VERTSEL; + break; + case SEL_INVERT: + luv->flag ^= MLOOPUV_VERTSEL; + break; + } + } + } + } +} + +static void uv_select_all_perform_multi( + Scene *scene, Image *ima, Object **objects, const uint objects_len, int action) +{ + if (action == SEL_TOGGLE) { + action = uvedit_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT : + SEL_SELECT; + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + uv_select_all_perform(scene, ima, obedit, action); + } +} + +static int uv_select_all_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + Image *ima = CTX_data_edit_image(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + int action = RNA_enum_get(op->ptr, "action"); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + uv_select_all_perform_multi(scene, ima, objects, objects_len, action); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +void UV_OT_select_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "(De)select All"; + ot->description = "Change selection of all UV vertices"; + ot->idname = "UV_OT_select_all"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_all_exec; + ot->poll = ED_operator_uvedit; + + WM_operator_properties_select_all(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mouse Select Operator + * \{ */ + +static bool uv_sticky_select( + float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen) +{ + int i; + + /* this function test if some vertex needs to selected + * in addition to the existing ones due to sticky select */ + if (sticky == SI_STICKY_DISABLE) { + return false; + } + + for (i = 0; i < hitlen; i++) { + if (hitv[i] == v) { + if (sticky == SI_STICKY_LOC) { + if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1]) { + return true; + } + } + else if (sticky == SI_STICKY_VERTEX) { + return true; + } + } + } + + return false; +} + +static int uv_mouse_select_multi(bContext *C, + Object **objects, + uint objects_len, + const float co[2], + const bool extend, + const bool deselect_all, + const bool loop) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + Image *ima = CTX_data_edit_image(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + UvNearestHit hit = UV_NEAREST_HIT_INIT; + int i, selectmode, sticky, sync, *hitv = NULL; + bool select = true; + bool found_item = false; + /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ + int flush = 0; + int hitlen = 0; + float limit[2], **hituv = NULL; + + /* notice 'limit' is the same no matter the zoom level, since this is like + * remove doubles and could annoying if it joined points when zoomed out. + * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and + * shift-selecting can consider an adjacent point close enough to add to + * the selection rather than de-selecting the closest. */ + + float penalty_dist; + { + float penalty[2]; + uvedit_pixel_to_float(sima, 0.05f, limit); + uvedit_pixel_to_float(sima, 5.0f / (sima ? sima->zoom : 1.0f), penalty); + penalty_dist = len_v2(penalty); + } + + /* retrieve operation mode */ + if (ts->uv_flag & UV_SYNC_SELECTION) { + sync = 1; + + if (ts->selectmode & SCE_SELECT_FACE) { + selectmode = UV_SELECT_FACE; + } + else if (ts->selectmode & SCE_SELECT_EDGE) { + selectmode = UV_SELECT_EDGE; + } + else { + selectmode = UV_SELECT_VERTEX; + } + + sticky = SI_STICKY_DISABLE; + } + else { + sync = 0; + selectmode = ts->uv_selectmode; + sticky = (sima) ? sima->sticky : 1; + } + + /* find nearest element */ + if (loop) { + /* find edge */ + found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + } + else if (selectmode == UV_SELECT_VERTEX) { + /* find vertex */ + found_item = uv_find_nearest_vert_multi( + scene, ima, objects, objects_len, co, penalty_dist, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + + if (found_item) { + /* mark 1 vertex as being hit */ + hitv = BLI_array_alloca(hitv, hit.efa->len); + hituv = BLI_array_alloca(hituv, hit.efa->len); + copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); + + hitv[hit.lindex] = BM_elem_index_get(hit.l->v); + hituv[hit.lindex] = hit.luv->uv; + + hitlen = hit.efa->len; + } + } + else if (selectmode == UV_SELECT_EDGE) { + /* find edge */ + found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + + if (found_item) { + /* mark 2 edge vertices as being hit */ + hitv = BLI_array_alloca(hitv, hit.efa->len); + hituv = BLI_array_alloca(hituv, hit.efa->len); + copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); + + hitv[hit.lindex] = BM_elem_index_get(hit.l->v); + hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v); + hituv[hit.lindex] = hit.luv->uv; + hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv; + + hitlen = hit.efa->len; + } + } + else if (selectmode == UV_SELECT_FACE) { + /* find face */ + found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + + if (found_item) { + BMEditMesh *em = BKE_editmesh_from_object(hit.ob); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* make active */ + BM_mesh_active_face_set(em->bm, hit.efa); + + /* mark all face vertices as being hit */ + + hitv = BLI_array_alloca(hitv, hit.efa->len); + hituv = BLI_array_alloca(hituv, hit.efa->len); + BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + hituv[i] = luv->uv; + hitv[i] = BM_elem_index_get(l->v); + } + + hitlen = hit.efa->len; + } + } + else if (selectmode == UV_SELECT_ISLAND) { + found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + } + + if (!found_item) { + if (deselect_all) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + + return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; + } + + Object *obedit = hit.ob; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* do selection */ + if (loop) { + if (!extend) { + /* TODO(MULTI_EDIT): We only need to de-select non-active */ + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend); + } + else if (selectmode == UV_SELECT_ISLAND) { + if (!extend) { + /* TODO(MULTI_EDIT): We only need to de-select non-active */ + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + /* Current behavior of 'extend' + * is actually toggling, so pass extend flag as 'toggle' here */ + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, false, false, extend, false); + } + else if (extend) { + if (selectmode == UV_SELECT_VERTEX) { + /* (de)select uv vertex */ + select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_EDGE) { + /* (de)select edge */ + select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset)); + uvedit_edge_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_FACE) { + /* (de)select face */ + select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset)); + uvedit_face_select_set(scene, em, hit.efa, select, true, cd_loop_uv_offset); + flush = -1; + } + + /* de-selecting an edge may deselect a face too - validate */ + if (sync) { + if (select == false) { + BM_select_history_validate(em->bm); + } + } + + /* (de)select sticky uv nodes */ + if (sticky != SI_STICKY_DISABLE) { + + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (uv_sticky_select( + limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + + flush = select ? 1 : -1; + } + } + else { + /* deselect all */ + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + + if (selectmode == UV_SELECT_VERTEX) { + /* select vertex */ + uvedit_uv_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_EDGE) { + /* select edge */ + uvedit_edge_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_FACE) { + /* select face */ + uvedit_face_select_enable(scene, em, hit.efa, true, cd_loop_uv_offset); + } + + /* select sticky uvs */ + if (sticky != SI_STICKY_DISABLE) { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (sticky == SI_STICKY_DISABLE) { + continue; + } + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (uv_sticky_select( + limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { + uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); + } + + flush = 1; + } + } + } + } + + if (sync) { + /* flush for mesh selection */ + + /* before bmesh */ +#if 0 + if (ts->selectmode != SCE_SELECT_FACE) { + if (flush == 1) { + EDBM_select_flush(em); + } + else if (flush == -1) { + EDBM_deselect_flush(em); + } + } +#else + if (flush != 0) { + if (loop) { + /* push vertex -> edge selection */ + if (select) { + EDBM_select_flush(em); + } + else { + EDBM_deselect_flush(em); + } + } + else { + EDBM_selectmode_flush(em); + } + } +#endif + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obiter = objects[ob_index]; + uv_select_tag_update_for_object(depsgraph, ts, obiter); + } + + return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; +} +static int uv_mouse_select( + bContext *C, const float co[2], const bool extend, const bool deselect_all, const bool loop) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all, loop); + MEM_freeN(objects); + return ret; +} + +static int uv_select_exec(bContext *C, wmOperator *op) +{ + float co[2]; + + RNA_float_get_array(op->ptr, "location", co); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); + const bool loop = false; + + return uv_mouse_select(C, co, extend, deselect_all, loop); +} + +static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + const ARegion *region = CTX_wm_region(C); + float co[2]; + + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); + RNA_float_set_array(op->ptr, "location", co); + + return uv_select_exec(C, op); +} + +void UV_OT_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->description = "Select UV vertices"; + ot->idname = "UV_OT_select"; + ot->flag = OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_exec; + ot->invoke = uv_select_invoke; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* properties */ + PropertyRNA *prop; + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); + prop = RNA_def_boolean(ot->srna, + "deselect_all", + false, + "Deselect On Nothing", + "Deselect all when nothing under the cursor"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + RNA_def_float_vector( + ot->srna, + "location", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", + -100.0f, + 100.0f); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop Select Operator + * \{ */ + +static int uv_select_loop_exec(bContext *C, wmOperator *op) +{ + float co[2]; + + RNA_float_get_array(op->ptr, "location", co); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + const bool deselect_all = false; + const bool loop = true; + + return uv_mouse_select(C, co, extend, deselect_all, loop); +} + +static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + const ARegion *region = CTX_wm_region(C); + float co[2]; + + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); + RNA_float_set_array(op->ptr, "location", co); + + return uv_select_loop_exec(C, op); +} + +void UV_OT_select_loop(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Loop Select"; + ot->description = "Select a loop of connected UV vertices"; + ot->idname = "UV_OT_select_loop"; + ot->flag = OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_loop_exec; + ot->invoke = uv_select_loop_invoke; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* properties */ + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); + RNA_def_float_vector( + ot->srna, + "location", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", + -100.0f, + 100.0f); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked Operator + * \{ */ + +static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + float limit[2]; + bool extend = true; + bool deselect = false; + bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE); + + UvNearestHit hit = UV_NEAREST_HIT_INIT; + + if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) { + BKE_report(op->reports, + RPT_ERROR, + "Select linked only works in face select mode when sync selection is enabled"); + return OPERATOR_CANCELLED; + } + + if (pick) { + extend = RNA_boolean_get(op->ptr, "extend"); + deselect = RNA_boolean_get(op->ptr, "deselect"); + } + uv_select_island_limit_default(sima, limit); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + if (pick) { + float co[2]; + + if (event) { + /* invoke */ + const ARegion *region = CTX_wm_region(C); + + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); + RNA_float_set_array(op->ptr, "location", co); + } + else { + /* exec */ + RNA_float_get_array(op->ptr, "location", co); + } + + if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) { + MEM_freeN(objects); + return OPERATOR_CANCELLED; + } + } + + if (!extend) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + uv_select_linked_multi(scene, + ima, + objects, + objects_len, + limit, + pick ? &hit : NULL, + extend, + deselect, + false, + select_faces); + + /* weak!, but works */ + Object **objects_free = objects; + if (pick) { + objects = &hit.ob; + objects_len = 1; + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + + MEM_SAFE_FREE(objects_free); + + return OPERATOR_FINISHED; +} + +static int uv_select_linked_exec(bContext *C, wmOperator *op) +{ + return uv_select_linked_internal(C, op, NULL, false); +} + +void UV_OT_select_linked(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked"; + ot->description = "Select all UV vertices linked to the active UV map"; + ot->idname = "UV_OT_select_linked"; + + /* api callbacks */ + ot->exec = uv_select_linked_exec; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked (Cursor Pick) Operator + * \{ */ + +static int uv_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + return uv_select_linked_internal(C, op, event, true); +} + +static int uv_select_linked_pick_exec(bContext *C, wmOperator *op) +{ + return uv_select_linked_internal(C, op, NULL, true); +} + +void UV_OT_select_linked_pick(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked Pick"; + ot->description = "Select all UV vertices linked under the mouse"; + ot->idname = "UV_OT_select_linked_pick"; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->invoke = uv_select_linked_pick_invoke; + ot->exec = uv_select_linked_pick_exec; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* properties */ + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); + RNA_def_boolean(ot->srna, + "deselect", + 0, + "Deselect", + "Deselect linked UV vertices rather than selecting them"); + RNA_def_float_vector( + ot->srna, + "location", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", + -100.0f, + 100.0f); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Split Operator + * \{ */ + +/** + * \note This is based on similar use case to #MESH_OT_split(), which has a similar effect + * but in this case they are not joined to begin with (only having the behavior of being joined) + * so its best to call this #uv_select_split() instead of just split(), but assigned to the same + * key as #MESH_OT_split - Campbell. + */ +static int uv_select_split_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const ToolSettings *ts = scene->toolsettings; + Image *ima = CTX_data_edit_image(C); + + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); + return OPERATOR_CANCELLED; + } + + bool changed_multi = false; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMesh *bm = BKE_editmesh_from_object(obedit)->bm; + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + bool is_sel = false; + bool is_unsel = false; + + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + /* are we all selected? */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_VERTSEL) { + is_sel = true; + } + else { + is_unsel = true; + } + + /* we have mixed selection, bail out */ + if (is_sel && is_unsel) { + break; + } + } + + if (is_sel && is_unsel) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag &= ~MLOOPUV_VERTSEL; + } + + changed = true; + } + } + + if (changed) { + changed_multi = true; + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL); + } + } + MEM_freeN(objects); + + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void UV_OT_select_split(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Split"; + ot->description = "Select only entirely selected faces"; + ot->idname = "UV_OT_select_split"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_split_exec; + ot->poll = ED_operator_uvedit; /* requires space image */ +} + +static void uv_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const short select) +{ + /* bmesh API handles flushing but not on de-select */ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode != SCE_SELECT_FACE) { + if (select == false) { + EDBM_deselect_flush(em); + } + else { + EDBM_select_flush(em); + } + } + + if (select == false) { + BM_select_history_validate(em->bm); + } + } +} + +static void uv_select_tag_update_for_object(Depsgraph *depsgraph, + const ToolSettings *ts, + Object *obedit) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); + } + else { + Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); + BKE_mesh_batch_cache_dirty_tag(obedit_eval->data, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT); + /* Only for region redraw. */ + WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select/Tag Flushing Utils + * + * Utility functions to flush the uv-selection from tags. + * \{ */ + +/** + * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face + */ +static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, + BMEditMesh *em, + UvVertMap *vmap, + const uint efa_index, + BMLoop *l, + const bool select, + const int cd_loop_uv_offset) +{ + UvMapVert *start_vlist = NULL, *vlist_iter; + BMFace *efa_vlist; + + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + + vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); + + while (vlist_iter) { + if (vlist_iter->separate) { + start_vlist = vlist_iter; + } + + if (efa_index == vlist_iter->poly_index) { + break; + } + + vlist_iter = vlist_iter->next; + } + + vlist_iter = start_vlist; + while (vlist_iter) { + + if (vlist_iter != start_vlist && vlist_iter->separate) { + break; + } + + if (efa_index != vlist_iter->poly_index) { + BMLoop *l_other; + efa_vlist = BM_face_at_index(em->bm, vlist_iter->poly_index); + /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */ + + l_other = BM_iter_at_index( + em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index); + + uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset); + } + vlist_iter = vlist_iter->next; + } +} + +/** + * Flush the selection from face tags based on sticky and selection modes. + * + * needed because settings the selection a face is done in a number of places but it also + * needs to respect the sticky modes for the UV verts, so dealing with the sticky modes + * is best done in a separate function. + * + * \note This function is very similar to #uv_select_flush_from_tag_loop, + * be sure to update both upon changing. + */ +static void uv_select_flush_from_tag_face(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select) +{ + /* Selecting UV Faces with some modes requires us to change + * the selection in other faces (depending on the sticky mode). + * + * This only needs to be done when the Mesh is not used for + * selection (so for sticky modes, vertex or location based). */ + + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { + /* Tag all verts as untouched, then touch the ones that have a face center + * in the loop and select all MLoopUV's that use a touched vert. */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } + } + } + + /* now select tagged verts */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + } + else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { + struct UvVertMap *vmap; + float limit[2]; + uint efa_index; + + uv_select_island_limit_default(sima, limit); + + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); + if (vmap == NULL) { + return; + } + + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + uv_select_flush_from_tag_sticky_loc_internal( + scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); + } + } + } + BM_uv_vert_map_free(vmap); + } + else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + uvedit_face_select_set(scene, em, efa, select, false, cd_loop_uv_offset); + } + } + } +} + +/** + * Flush the selection from loop tags based on sticky and selection modes. + * + * needed because settings the selection a face is done in a number of places but it also needs + * to respect the sticky modes for the UV verts, so dealing with the sticky modes is best done + * in a separate function. + * + * \note This function is very similar to #uv_select_flush_from_tag_loop, + * be sure to update both upon changing. + */ +static void uv_select_flush_from_tag_loop(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select) +{ + /* Selecting UV Loops with some modes requires us to change + * the selection in other faces (depending on the sticky mode). + * + * This only needs to be done when the Mesh is not used for + * selection (so for sticky modes, vertex or location based). */ + + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { + /* Tag all verts as untouched, then touch the ones that have a face center + * in the loop and select all MLoopUV's that use a touched vert. */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l, BM_ELEM_TAG)) { + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } + } + } + + /* now select tagged verts */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + } + else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { + struct UvVertMap *vmap; + float limit[2]; + uint efa_index; + + uv_select_island_limit_default(sima, limit); + + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); + if (vmap == NULL) { + return; + } + + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l, BM_ELEM_TAG)) { + uv_select_flush_from_tag_sticky_loc_internal( + scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); + } + } + } + BM_uv_vert_map_free(vmap); + } + else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Box Select Operator + * \{ */ + +static int uv_box_select_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + const ARegion *region = CTX_wm_region(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + rctf rectf; + bool pinned; + float limit[2]; + const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); + + /* get rectangle from operator */ + WM_operator_properties_border_to_rctf(op, &rectf); + UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); + + const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + const bool select = (sel_op != SEL_OP_SUB); + const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); + + pinned = RNA_boolean_get(op->ptr, "pinned"); + + uv_select_island_limit_default(sima, limit); + + bool changed_multi = false; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + if (use_pre_deselect) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + /* don't indent to avoid diff noise! */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* do actual selection */ + if (use_face_center && !pinned) { + /* handle face selection mode */ + float cent[2]; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + /* assume not touched */ + BM_elem_flag_disable(efa, BM_ELEM_TAG); + + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + uv_poly_center(efa, cent, cd_loop_uv_offset); + if (BLI_rctf_isect_pt_v(&rectf, cent)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (changed) { + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + } + else if (use_edge && !pinned) { + changed = true; + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (BLI_rctf_isect_pt_v(&rectf, luv->uv) && + BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + else { + /* other selection modes */ + changed = true; + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + bool has_selected = false; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { + if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) { + /* UV_SYNC_SELECTION - can't do pinned selection */ + if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } + } + else if (pinned) { + if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } + } + } + } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + + if (changed || use_pre_deselect) { + changed_multi = true; + + uv_select_sync_flush(ts, em, select); + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + + MEM_freeN(objects); + + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void UV_OT_select_box(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Box Select"; + ot->description = "Select UV vertices using box selection"; + ot->idname = "UV_OT_select_box"; + + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = uv_box_select_exec; + ot->modal = WM_gesture_box_modal; + ot->poll = ED_operator_uvedit_space_image; /* requires space image */ + ot->cancel = WM_gesture_box_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only"); + + WM_operator_properties_gesture_box(ot); + WM_operator_properties_select_operation_simple(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Circle Select Operator + * \{ */ + +static int uv_circle_select_is_point_inside(const float uv[2], + const float offset[2], + const float ellipse[2]) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + const float co[2] = { + (uv[0] - offset[0]) * ellipse[0], + (uv[1] - offset[1]) * ellipse[1], + }; + return len_squared_v2(co) < 1.0f; +} + +static int uv_circle_select_is_edge_inside(const float uv_a[2], + const float uv_b[2], + const float offset[2], + const float ellipse[2]) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + const float co_a[2] = { + (uv_a[0] - offset[0]) * ellipse[0], + (uv_a[1] - offset[1]) * ellipse[1], + }; + const float co_b[2] = { + (uv_b[0] - offset[0]) * ellipse[0], + (uv_b[1] - offset[1]) * ellipse[1], + }; + return dist_squared_to_line_segment_v2((const float[2]){0.0f, 0.0f}, co_a, co_b) < 1.0f; +} + +static int uv_circle_select_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const ToolSettings *ts = scene->toolsettings; + const ARegion *region = CTX_wm_region(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + int x, y, radius, width, height; + float zoomx, zoomy; + float limit[2], offset[2], ellipse[2]; + + const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); + + /* get operator properties */ + x = RNA_int_get(op->ptr, "x"); + y = RNA_int_get(op->ptr, "y"); + radius = RNA_int_get(op->ptr, "radius"); + + /* compute ellipse size and location, not a circle since we deal + * with non square image. ellipse is normalized, r = 1.0. */ + ED_space_image_get_size(sima, &width, &height); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); + + ellipse[0] = width * zoomx / radius; + ellipse[1] = height * zoomy / radius; + + UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); + + uv_select_island_limit_default(sima, limit); + + bool changed_multi = false; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), + WM_gesture_is_modal_first(op->customdata)); + const bool select = (sel_op != SEL_OP_SUB); + const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); + + if (use_pre_deselect) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* do selection */ + if (use_face_center) { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); + /* assume not touched */ + if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); + if (uv_circle_select_is_point_inside(cent, offset, ellipse)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (changed) { + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + } + else if (use_edge) { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) { + changed = true; + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + else { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + bool has_selected = false; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (uv_circle_select_is_point_inside(luv->uv, offset, ellipse)) { + changed = true; + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } + } + } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + + if (changed || use_pre_deselect) { + changed_multi = true; + + uv_select_sync_flush(ts, em, select); + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + MEM_freeN(objects); + + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void UV_OT_select_circle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Circle Select"; + ot->description = "Select UV vertices using circle selection"; + ot->idname = "UV_OT_select_circle"; + + /* api callbacks */ + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->exec = uv_circle_select_exec; + ot->poll = ED_operator_uvedit_space_image; /* requires space image */ + ot->cancel = WM_gesture_circle_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_circle(ot); + WM_operator_properties_select_operation_simple(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Lasso Select Operator + * \{ */ + +static bool do_lasso_select_mesh_uv_is_point_inside(const ARegion *region, + const rcti *clip_rect, + const int mcoords[][2], + const int mcoords_len, + const float co_test[2]) +{ + int co_screen[2]; + if (UI_view2d_view_to_region_clip( + ®ion->v2d, co_test[0], co_test[1], &co_screen[0], &co_screen[1]) && + BLI_rcti_isect_pt_v(clip_rect, co_screen) && + BLI_lasso_is_point_inside( + mcoords, mcoords_len, co_screen[0], co_screen[1], V2D_IS_CLIPPED)) { + return true; + } + return false; +} + +static bool do_lasso_select_mesh_uv(bContext *C, + const int mcoords[][2], + const int mcoords_len, + const eSelectOp sel_op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + const ARegion *region = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); + + const bool select = (sel_op != SEL_OP_SUB); + const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); + + BMIter iter, liter; + + BMFace *efa; + BMLoop *l; + float limit[2]; + bool changed_multi = false; + rcti rect; + + uv_select_island_limit_default(sima, limit); + + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + if (use_pre_deselect) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + /* don't indent to avoid diff noise! */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + + bool changed = false; + + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if (use_face_center) { /* Face Center Sel */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); + /* assume not touched */ + if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); + if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcoords, mcoords_len, cent)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (changed) { + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + } + else if (use_edge) { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (do_lasso_select_mesh_uv_is_point_inside( + region, &rect, mcoords, mcoords_len, luv->uv) && + do_lasso_select_mesh_uv_is_point_inside( + region, &rect, mcoords, mcoords_len, luv_prev->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + changed = true; + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + else { /* Vert Sel */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + bool has_selected = false; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (do_lasso_select_mesh_uv_is_point_inside( + region, &rect, mcoords, mcoords_len, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + changed = true; + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } + } + } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + + if (changed || use_pre_deselect) { + changed_multi = true; + + uv_select_sync_flush(ts, em, select); + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + MEM_freeN(objects); + + return changed_multi; +} + +static int uv_lasso_select_exec(bContext *C, wmOperator *op) +{ + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); + + if (mcoords) { + const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + bool changed = do_lasso_select_mesh_uv(C, mcoords, mcoords_len, sel_op); + MEM_freeN((void *)mcoords); + + return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + } + + return OPERATOR_PASS_THROUGH; +} + +void UV_OT_select_lasso(wmOperatorType *ot) +{ + ot->name = "Lasso Select UV"; + ot->description = "Select UVs using lasso selection"; + ot->idname = "UV_OT_select_lasso"; + + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = uv_lasso_select_exec; + ot->poll = ED_operator_uvedit_space_image; + ot->cancel = WM_gesture_lasso_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_lasso(ot); + WM_operator_properties_select_operation_simple(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Pinned UV's Operator + * \{ */ + +static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + bool changed = false; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_PINNED) { + uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); + changed = true; + } + } + } + + if (changed) { + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +void UV_OT_select_pinned(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Selected Pinned"; + ot->description = "Select all pinned UV vertices"; + ot->idname = "UV_OT_select_pinned"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_pinned_exec; + ot->poll = ED_operator_uvedit; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Overlap Operator + * \{ */ + +BLI_INLINE uint overlap_hash(const void *overlap_v) +{ + const BVHTreeOverlap *overlap = overlap_v; + + /* Designed to treat (A,B) and (B,A) as the same. */ + int x = overlap->indexA; + int y = overlap->indexB; + if (x > y) { + SWAP(int, x, y); + } + return BLI_hash_int_2d(x, y); +} + +BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v) +{ + const BVHTreeOverlap *a = a_v; + const BVHTreeOverlap *b = b_v; + return !((a->indexA == b->indexA && a->indexB == b->indexB) || + (a->indexA == b->indexB && a->indexB == b->indexA)); +} + +struct UVOverlapData { + int ob_index; + int face_index; + float tri[3][2]; +}; + +static int uv_select_overlap(bContext *C, const bool extend) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + /* Calculate maximum number of tree nodes and prepare initial selection. */ + uint uv_tri_len = 0; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); + BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); + if (!extend) { + uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); + } + + BMIter iter; + BMFace *efa; + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { + continue; + } + uv_tri_len += efa->len - 2; + } + } + + struct UVOverlapData *overlap_data = MEM_mallocN(sizeof(struct UVOverlapData) * uv_tri_len, + "UvOverlapData"); + BVHTree *uv_tree = BLI_bvhtree_new(uv_tri_len, 0.0f, 4, 6); + + /* Use a global data index when inserting into the BVH. */ + int data_index = 0; + + int face_len_alloc = 3; + float(*uv_verts)[2] = MEM_mallocN(sizeof(*uv_verts) * face_len_alloc, "UvOverlapCoords"); + uint(*indices)[3] = MEM_mallocN(sizeof(*indices) * (face_len_alloc - 2), "UvOverlapTris"); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMIter iter, liter; + BMFace *efa; + BMLoop *l; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* Triangulate each UV face and store it inside the BVH. */ + int face_index; + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) { + + if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { + continue; + } + + const uint face_len = efa->len; + const uint tri_len = face_len - 2; + + if (face_len_alloc < face_len) { + MEM_freeN(uv_verts); + MEM_freeN(indices); + uv_verts = MEM_mallocN(sizeof(*uv_verts) * face_len, "UvOverlapCoords"); + indices = MEM_mallocN(sizeof(*indices) * tri_len, "UvOverlapTris"); + face_len_alloc = face_len; + } + + int vert_index; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, vert_index) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + copy_v2_v2(uv_verts[vert_index], luv->uv); + } + + BLI_polyfill_calc(uv_verts, face_len, 0, indices); + + for (int t = 0; t < tri_len; t++) { + overlap_data[data_index].ob_index = ob_index; + overlap_data[data_index].face_index = face_index; + + /* BVH needs 3D, overlap data uses 2D. */ + const float tri[3][3] = { + {UNPACK2(uv_verts[indices[t][0]]), 0.0f}, + {UNPACK2(uv_verts[indices[t][1]]), 0.0f}, + {UNPACK2(uv_verts[indices[t][2]]), 0.0f}, + }; + + copy_v2_v2(overlap_data[data_index].tri[0], tri[0]); + copy_v2_v2(overlap_data[data_index].tri[1], tri[1]); + copy_v2_v2(overlap_data[data_index].tri[2], tri[2]); + + BLI_bvhtree_insert(uv_tree, data_index, &tri[0][0], 3); + data_index++; + } + } + } + BLI_assert(data_index == uv_tri_len); + + MEM_freeN(uv_verts); + MEM_freeN(indices); + + BLI_bvhtree_balance(uv_tree); + + uint tree_overlap_len; + BVHTreeOverlap *overlap = BLI_bvhtree_overlap(uv_tree, uv_tree, &tree_overlap_len, NULL, NULL); + + if (overlap != NULL) { + GSet *overlap_set = BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, tree_overlap_len); + + for (int i = 0; i < tree_overlap_len; i++) { + /* Skip overlaps against yourself. */ + if (overlap[i].indexA == overlap[i].indexB) { + continue; + } + + /* Skip overlaps that have already been tested. */ + if (!BLI_gset_add(overlap_set, &overlap[i])) { + continue; + } + + const struct UVOverlapData *o_a = &overlap_data[overlap[i].indexA]; + const struct UVOverlapData *o_b = &overlap_data[overlap[i].indexB]; + Object *obedit_a = objects[o_a->ob_index]; + Object *obedit_b = objects[o_b->ob_index]; + BMEditMesh *em_a = BKE_editmesh_from_object(obedit_a); + BMEditMesh *em_b = BKE_editmesh_from_object(obedit_b); + BMFace *face_a = em_a->bm->ftable[o_a->face_index]; + BMFace *face_b = em_b->bm->ftable[o_b->face_index]; + const int cd_loop_uv_offset_a = CustomData_get_offset(&em_a->bm->ldata, CD_MLOOPUV); + const int cd_loop_uv_offset_b = CustomData_get_offset(&em_b->bm->ldata, CD_MLOOPUV); + + /* Skip if both faces are already selected. */ + if (uvedit_face_select_test(scene, face_a, cd_loop_uv_offset_a) && + uvedit_face_select_test(scene, face_b, cd_loop_uv_offset_b)) { + continue; + } + + /* Main tri-tri overlap test. */ + const float endpoint_bias = -1e-4f; + const float(*t1)[2] = o_a->tri; + const float(*t2)[2] = o_b->tri; + float vi[2]; + bool result = ( + /* Don't use 'isect_tri_tri_v2' here + * because it's important to ignore overlap at end-points. */ + isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[0], t2[1], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[1], t2[2], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[2], t2[0], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[0], t2[1], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[1], t2[2], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[2], t2[0], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[0], t2[1], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[1], t2[2], endpoint_bias, vi) == 1 || + isect_point_tri_v2(t1[0], t2[0], t2[1], t2[2]) != 0 || + isect_point_tri_v2(t2[0], t1[0], t1[1], t1[2]) != 0); + + if (result) { + uvedit_face_select_enable(scene, em_a, face_a, false, cd_loop_uv_offset_a); + uvedit_face_select_enable(scene, em_b, face_b, false, cd_loop_uv_offset_b); + } + } + + BLI_gset_free(overlap_set, NULL); + MEM_freeN(overlap); + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + uv_select_tag_update_for_object(depsgraph, scene->toolsettings, objects[ob_index]); + } + + BLI_bvhtree_free(uv_tree); + + MEM_freeN(overlap_data); + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +static int uv_select_overlap_exec(bContext *C, wmOperator *op) +{ + bool extend = RNA_boolean_get(op->ptr, "extend"); + return uv_select_overlap(C, extend); +} + +void UV_OT_select_overlap(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Overlap"; + ot->description = "Select all UV faces which overlap each other"; + ot->idname = "UV_OT_select_overlap"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_overlap_exec; + ot->poll = ED_operator_uvedit; + + /* properties */ + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); +} + +/** \} */ diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index ca956dfbbbf..68b5b4baeca 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -25,9 +25,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_map.h" - -extern "C" { #include "RNA_access.h" #include "RNA_types.h" @@ -66,7 +63,6 @@ extern "C" { #include "RE_pipeline.h" #include "render_types.h" -} #include <limits.h> diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h index 9c94228414d..ee29519c849 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h @@ -21,7 +21,7 @@ * \ingroup freestyle */ -#include "BLI_map.h" +#include "BLI_map.hh" #include "../stroke/StrokeRenderer.h" #include "../system/FreestyleConfig.h" diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h index a4beb1c119c..95612a42722 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h @@ -24,11 +24,9 @@ #include "../stroke/StyleModule.h" #include "../system/PythonInterpreter.h" -extern "C" { #include "BLI_utildefines.h" // BLI_assert() struct Text; -} namespace Freestyle { diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h index 0a9fa5dc85a..c1a8dcdb370 100644 --- a/source/blender/freestyle/intern/geometry/Grid.h +++ b/source/blender/freestyle/intern/geometry/Grid.h @@ -33,9 +33,7 @@ #include "../system/FreestyleConfig.h" -extern "C" { #include "BLI_utildefines.h" -} #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" diff --git a/source/blender/freestyle/intern/image/GaussianFilter.h b/source/blender/freestyle/intern/image/GaussianFilter.h index f8e2524fa4f..625e357eddf 100644 --- a/source/blender/freestyle/intern/image/GaussianFilter.h +++ b/source/blender/freestyle/intern/image/GaussianFilter.h @@ -27,9 +27,7 @@ #include "../system/FreestyleConfig.h" -extern "C" { #include "BLI_math.h" -} #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" diff --git a/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h index f220bbfd6f1..2339abe9aed 100644 --- a/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h +++ b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h @@ -24,9 +24,7 @@ #include "Node.h" -extern "C" { #include "DNA_scene_types.h" /* for Scene and ViewLayer */ -} using namespace std; diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp index 7d04a55c5d9..4386e64345f 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.cpp +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -41,10 +41,8 @@ // soc #include <qimage.h> // soc #include <QString> -extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} using namespace std; diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h index b2bfb805ee6..d6ee1d01279 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.h +++ b/source/blender/freestyle/intern/stroke/StrokeRep.h @@ -30,10 +30,8 @@ # include "MEM_guardedalloc.h" #endif -extern "C" { #include "DNA_material_types.h" // for MAX_MTEX struct bNodeTree; -} namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp index a6a72bfa314..efda4b7fd2a 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp @@ -33,10 +33,8 @@ #include "BKE_global.h" #include "BLI_math.h" -extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} namespace Freestyle { diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp index 591d6518741..96b313d4e01 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -105,16 +105,16 @@ static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2) } /*! gts_vertex_mean_curvature_normal: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kh: the Mean Curvature Normal at @v. + * \param v: a #WVertex. + * \param s: a #GtsSurface. + * \param Kh: the Mean Curvature Normal at \a v. * - * Computes the Discrete Mean Curvature Normal approximation at @v. - * The mean curvature at @v is half the magnitude of the vector @Kh. + * 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, - * depending on the curvature at @v. It is the responsibility of the caller of the function to use - * the mean curvature normal appropriately. + * depending on the curvature at \a v. It is the responsibility of the caller of the function to + * use the mean curvature normal appropriately. * * This approximation is from the paper: * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds @@ -176,11 +176,11 @@ bool gts_vertex_mean_curvature_normal(WVertex *v, Vec3r &Kh) } /*! gts_vertex_gaussian_curvature: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kg: the Discrete Gaussian Curvature approximation at @v. + * \param v: a #WVertex. + * \param s: a #GtsSurface. + * \param Kg: the Discrete Gaussian Curvature approximation at \a v. * - * Computes the Discrete Gaussian Curvature approximation at @v. + * Computes the Discrete Gaussian Curvature approximation at \a v. * * This approximation is from the paper: * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds @@ -280,16 +280,16 @@ static void eigenvector(real a, real b, real c, Vec3r e) } /*! gts_vertex_principal_directions: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kh: mean curvature normal (a #Vec3r). - * @Kg: Gaussian curvature (a real). - * @e1: first principal curvature direction (direction of largest curvature). - * @e2: second principal curvature direction. + * \param v: a #WVertex. + * \param s: a #GtsSurface. + * \param Kh: mean curvature normal (a #Vec3r). + * \param Kg: Gaussian curvature (a real). + * \param e1: first principal curvature direction (direction of largest curvature). + * \param e2: second principal curvature direction. * - * Computes the principal curvature directions at a point given @Kh and @Kg, the mean curvature - * normal and Gaussian curvatures at that point, computed with gts_vertex_mean_curvature_normal() - * and gts_vertex_gaussian_curvature(), respectively. + * Computes the principal curvature directions at a point given \a Kh and \a Kg, + * the mean curvature normal and Gaussian curvatures at that point, computed with + * gts_vertex_mean_curvature_normal() and gts_vertex_gaussian_curvature(), respectively. * * Note that this computation is very approximate and tends to be unstable. Smoothing of the * surface or the principal directions may be necessary to achieve reasonable results. diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index 87743911add..d3c85b891c6 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -56,6 +56,7 @@ set(SRC intern/MOD_gpencilsimplify.c intern/MOD_gpencilsmooth.c intern/MOD_gpencilsubdiv.c + intern/MOD_gpenciltexture.c intern/MOD_gpencilthick.c intern/MOD_gpenciltime.c intern/MOD_gpenciltint.c diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h index f5c064c1c07..a7a4333d82e 100644 --- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h +++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h @@ -43,6 +43,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Offset; extern GpencilModifierTypeInfo modifierType_Gpencil_Armature; extern GpencilModifierTypeInfo modifierType_Gpencil_Time; extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply; +extern GpencilModifierTypeInfo modifierType_Gpencil_Texture; /* MOD_gpencil_util.c */ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index 7df0440aa85..f7929b58650 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -72,13 +72,14 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]) INIT_GP_TYPE(Armature); INIT_GP_TYPE(Time); INIT_GP_TYPE(Multiply); + INIT_GP_TYPE(Texture); #undef INIT_GP_TYPE } /* verify if valid layer, material and pass index */ bool is_stroke_affected_by_modifier(Object *ob, char *mlayername, - char *mmaterialname, + Material *material, const int mpassindex, const int gpl_passindex, const int minpoints, @@ -105,15 +106,15 @@ bool is_stroke_affected_by_modifier(Object *ob, } } } - /* omit if filter by material */ - if (mmaterialname[0] != '\0') { + /* Omit if filter by material. */ + if (material != NULL) { if (inv4 == false) { - if (!STREQ(mmaterialname, ma->id.name + 2)) { + if (material != ma) { return false; } } else { - if (STREQ(mmaterialname, ma->id.name + 2)) { + if (material == ma) { return false; } } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h index fc4522bc028..5cc3750639b 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h @@ -34,7 +34,7 @@ struct bGPDstroke; bool is_stroke_affected_by_modifier(struct Object *ob, char *mlayername, - char *mmaterialname, + struct Material *material, const int mpassindex, const int gpl_passindex, const int minpoints, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c index 59a41901a48..2d5e01ced94 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -63,7 +63,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void gpencil_deform_verts(ArmatureGpencilModifierData *mmd, Object *target, bGPDstroke *gps) @@ -127,7 +127,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData Scene *scene = DEG_get_evaluated_scene(depsgraph); Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md; - GpencilModifierData *md_eval = BKE_gpencil_modifiers_findByName(object_eval, md->name); + GpencilModifierData *md_eval = BKE_gpencil_modifiers_findby_name(object_eval, md->name); bGPdata *gpd = (bGPdata *)ob->data; int oldframe = (int)DEG_get_ctime(depsgraph); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index 314879927ff..da4c1f71f44 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -77,11 +77,12 @@ static void initData(GpencilModifierData *md) gpmd->object = NULL; gpmd->flag |= GP_ARRAY_USE_RELATIVE; gpmd->seed = 1; + gpmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } /* -------------------------------- */ @@ -163,7 +164,7 @@ static void generate_geometry(GpencilModifierData *md, LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -320,6 +321,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Array = { /* name */ "Array", /* structName */ "ArrayGpencilModifierData", @@ -340,6 +350,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Array = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c index 435559f4881..71a051629d8 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -63,7 +63,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static bool dependsOnTime(GpencilModifierData *UNUSED(md)) @@ -406,6 +406,7 @@ static void generate_geometry(GpencilModifierData *md, { BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md; const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW); + const bool is_percentage = (mmd->flag & GP_BUILD_PERCENTAGE); const float ctime = DEG_get_ctime(depsgraph); @@ -462,8 +463,8 @@ static void generate_geometry(GpencilModifierData *md, } /* Early exit if current frame is outside start/end bounds */ - /* NOTE: If we're beyond the next/prev frames (if existent), then we wouldn't have this problem - * anyway... */ + /* NOTE: If we're beyond the next/previous frames (if existent), + * then we wouldn't have this problem anyway... */ if (ctime < start_frame) { /* Before Start - Animation hasn't started. Display initial state. */ if (reverse) { @@ -500,7 +501,8 @@ static void generate_geometry(GpencilModifierData *md, } /* Determine how far along we are between the keyframes */ - float fac = (ctime - start_frame) / (end_frame - start_frame); + float fac = is_percentage ? mmd->percentage_fac : + (ctime - start_frame) / (end_frame - start_frame); /* Time management mode */ switch (mmd->mode) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c index d311e77b9e3..14125d5c8d4 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -37,8 +37,10 @@ #include "BKE_colortools.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -50,8 +52,7 @@ static void initData(GpencilModifierData *md) ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md; gpmd->pass_index = 0; ARRAY_SET_ITEMS(gpmd->hsv, 0.5f, 1.0f, 1.0f); - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; gpmd->modify_color = GP_MODIFY_COLOR_BOTH; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -71,7 +72,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -91,7 +92,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -178,6 +179,13 @@ static void freeData(GpencilModifierData *md) } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Color = { /* name */ "Hue/Saturation", /* structName */ "ColorGpencilModifierData", @@ -198,6 +206,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Color = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c index 76f22fc9a36..d39c94e06d5 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -77,9 +77,7 @@ static void initData(GpencilModifierData *md) { HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->force = 0.5f; gpmd->falloff_type = eGPHook_Falloff_Smooth; @@ -99,7 +97,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curfalloff = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curfalloff = BKE_curvemapping_copy(gmd->curfalloff); } @@ -208,7 +206,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -338,6 +336,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + HookGpencilModifierData *mmd = (HookGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Hook = { /* name */ "Hook", /* structName */ "HookGpencilModifierData", @@ -358,6 +365,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Hook = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c index 73b3c332a2e..5d5d673ca55 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -55,9 +55,7 @@ static void initData(GpencilModifierData *md) { LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->cache_data = NULL; gpmd->strength = 1.0f; @@ -65,7 +63,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void deformStroke(GpencilModifierData *md, @@ -80,7 +78,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -200,6 +198,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Lattice = { /* name */ "Lattice", /* structName */ "LatticeGpencilModifierData", @@ -220,6 +227,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Lattice = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c index 5fffe683e6e..542e68a7903 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -56,15 +56,14 @@ static void initData(GpencilModifierData *md) { MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->flag |= GP_MIRROR_AXIS_X; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void update_position(Object *ob, MirrorGpencilModifierData *mmd, bGPDstroke *gps, int axis) @@ -130,7 +129,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp for (i = 0, gps = gpf->strokes.first; i < tot_strokes; i++, gps = gps->next) { if (is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -213,6 +212,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Mirror = { /* name */ "Mirror", /* structName */ "MirrorGpencilModifierData", @@ -233,6 +241,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Mirror = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c index 2552f527a5e..22e46626a13 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -71,11 +71,12 @@ static void initData(GpencilModifierData *md) mmd->fading_center = 0.5f; mmd->fading_thickness = 0.5f; mmd->fading_opacity = 0.5f; + mmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void minter_v3_v3v3v3_ref( @@ -211,7 +212,7 @@ static void bakeModifier(Main *UNUSED(bmain), for (gps = gpf->strokes.first; gps; gps = gps->next) { if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -252,7 +253,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp for (gps = gpf->strokes.first; gps; gps = gps->next) { if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -297,6 +298,13 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + MultiplyGpencilModifierData *mmd = (MultiplyGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Multiply = { /* name */ "Multiple Strokes", /* structName */ "MultiplyGpencilModifierData", @@ -317,6 +325,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Multiply = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index 5ed08e39197..82f9d9a323d 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -44,6 +44,8 @@ #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -59,9 +61,7 @@ static void initData(GpencilModifierData *md) gpmd->flag |= GP_NOISE_FULL_STROKE; gpmd->flag |= GP_NOISE_USE_RANDOM; gpmd->factor = 0.5f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->step = 4; gpmd->seed = 1; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -91,7 +91,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -135,7 +135,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -259,6 +259,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Noise = { /* name */ "Noise", /* structName */ "NoiseGpencilModifierData", @@ -279,6 +286,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Noise = { /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c index a78de314c21..686f589ffe9 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -38,6 +38,8 @@ #include "BKE_deform.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -48,9 +50,7 @@ static void initData(GpencilModifierData *md) { OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; ARRAY_SET_ITEMS(gpmd->loc, 0.0f, 0.0f, 0.0f); ARRAY_SET_ITEMS(gpmd->rot, 0.0f, 0.0f, 0.0f); ARRAY_SET_ITEMS(gpmd->scale, 0.0f, 0.0f, 0.0f); @@ -58,7 +58,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } /* change stroke offsetness */ @@ -77,7 +77,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -129,6 +129,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + OffsetGpencilModifierData *mmd = (OffsetGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Offset = { /* name */ "Offset", /* structName */ "OffsetGpencilModifierData", @@ -149,6 +156,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Offset = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c index 5ca99be0dff..92b2621d211 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -38,8 +38,10 @@ #include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -52,9 +54,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->factor = 1.0f; gpmd->hardeness = 1.0f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->modify_color = GP_MODIFY_COLOR_BOTH; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); if (gpmd->curve_intensity) { @@ -73,7 +73,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -92,7 +92,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -189,6 +189,13 @@ static void freeData(GpencilModifierData *md) } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Opacity = { /* name */ "Opacity", /* structName */ "OpacityGpencilModifierData", @@ -209,6 +216,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c index 7b914b2a3b0..2cda108682e 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -34,6 +34,8 @@ #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -48,13 +50,12 @@ static void initData(GpencilModifierData *md) gpmd->factor = 0.0f; gpmd->length = 0.1f; gpmd->distance = 0.1f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void deformStroke(GpencilModifierData *md, @@ -68,7 +69,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, mmd->mode == GP_SIMPLIFY_SAMPLE ? 3 : 4, @@ -123,6 +124,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + SimplifyGpencilModifierData *mmd = (SimplifyGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Simplify = { /* name */ "Simplify", /* structName */ "SimplifyGpencilModifierData", @@ -143,6 +151,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Simplify = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c index fb9089ea6cb..e2e13b736e4 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -35,6 +35,8 @@ #include "BKE_deform.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -47,9 +49,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->flag |= GP_SMOOTH_MOD_LOCATION; gpmd->factor = 0.5f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->step = 1; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -69,7 +69,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -88,7 +88,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 3, @@ -167,6 +167,13 @@ static void freeData(GpencilModifierData *md) } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + SmoothGpencilModifierData *mmd = (SmoothGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Smooth = { /* name */ "Smooth", /* structName */ "SmoothGpencilModifierData", @@ -187,6 +194,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Smooth = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c index 0fdc3694af2..072159136ce 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -36,6 +36,8 @@ #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -47,13 +49,12 @@ static void initData(GpencilModifierData *md) SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md; gpmd->pass_index = 0; gpmd->level = 1; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } /* subdivide stroke to get more control points */ @@ -72,7 +73,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, minimum_vert, @@ -104,6 +105,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = { /* name */ "Subdivide", /* structName */ "SubdivGpencilModifierData", @@ -124,6 +132,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c new file mode 100644 index 00000000000..a5adf12b617 --- /dev/null +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c @@ -0,0 +1,172 @@ +/* + * 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) 2017, 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_gpencil_modifier_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_colortools.h" +#include "BKE_deform.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" + +#include "DEG_depsgraph.h" + +#include "MOD_gpencil_modifiertypes.h" +#include "MOD_gpencil_util.h" + +static void initData(GpencilModifierData *md) +{ + TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md; + gpmd->fit_method = GP_TEX_CONSTANT_LENGTH; + gpmd->fill_rotation = 0.0f; + gpmd->fill_scale = 1.0f; + gpmd->fill_offset[0] = 0.0f; + gpmd->fill_offset[1] = 0.0f; + gpmd->uv_offset = 0.0f; + gpmd->uv_scale = 1.0f; + gpmd->pass_index = 0; + gpmd->material = NULL; +} + +static void copyData(const GpencilModifierData *md, GpencilModifierData *target) +{ + BKE_gpencil_modifier_copydata_generic(md, target); +} + +/* change stroke uv texture values */ +static void deformStroke(GpencilModifierData *md, + Depsgraph *UNUSED(depsgraph), + Object *ob, + bGPDlayer *gpl, + bGPDframe *UNUSED(gpf), + bGPDstroke *gps) +{ + TextureGpencilModifierData *mmd = (TextureGpencilModifierData *)md; + const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname); + + if (!is_stroke_affected_by_modifier(ob, + mmd->layername, + mmd->material, + mmd->pass_index, + mmd->layer_pass, + 1, + gpl, + gps, + mmd->flag & GP_TEX_INVERT_LAYER, + mmd->flag & GP_TEX_INVERT_PASS, + mmd->flag & GP_TEX_INVERT_LAYERPASS, + mmd->flag & GP_TEX_INVERT_MATERIAL)) { + return; + } + if ((mmd->mode == FILL) || (mmd->mode == STROKE_AND_FILL)) { + gps->uv_rotation += mmd->fill_rotation; + gps->uv_translation[0] += mmd->fill_offset[0]; + gps->uv_translation[1] += mmd->fill_offset[1]; + gps->uv_scale *= mmd->fill_scale; + BKE_gpencil_stroke_geometry_update(gps); + } + + if ((mmd->mode == STROKE) || (mmd->mode == STROKE_AND_FILL)) { + float totlen = 1.0f; + if (mmd->fit_method == GP_TEX_FIT_STROKE) { + totlen = 0.0f; + for (int i = 1; i < gps->totpoints; i++) { + totlen += len_v3v3(&gps->points[i - 1].x, &gps->points[i].x); + } + } + + 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_TEX_INVERT_VGROUP) != 0, def_nr); + if (weight < 0.0f) { + continue; + } + + pt->uv_fac /= totlen; + pt->uv_fac *= mmd->uv_scale; + pt->uv_fac += mmd->uv_offset; + } + } +} + +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) +{ + TextureGpencilModifierData *mmd = (TextureGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + +GpencilModifierTypeInfo modifierType_Gpencil_Texture = { + /* name */ "Texture Mapping", + /* structName */ "TextureGpencilModifierData", + /* structSize */ sizeof(TextureGpencilModifierData), + /* type */ eGpencilModifierTypeType_Gpencil, + /* flags */ eGpencilModifierTypeFlag_SupportsEditmode, + + /* copyData */ copyData, + + /* deformStroke */ deformStroke, + /* generateStrokes */ NULL, + /* bakeModifier */ bakeModifier, + /* remapTime */ NULL, + + /* initData */ initData, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepsgraph */ NULL, + /* dependsOnTime */ NULL, + /* foreachObjectLink */ 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 4d985652a1e..b9fadea7fd0 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -37,6 +37,8 @@ #include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -49,9 +51,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->thickness_fac = 1.0f; gpmd->thickness = 30; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->curve_thickness = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); if (gpmd->curve_thickness) { BKE_curvemapping_initialize(gpmd->curve_thickness); @@ -77,7 +77,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_thickness = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_thickness = BKE_curvemapping_copy(gmd->curve_thickness); } @@ -95,7 +95,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -159,6 +159,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Thick = { /* name */ "Thickness", /* structName */ "ThickGpencilModifierData", @@ -179,6 +186,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c index 10463f865e2..85400b56cad 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -45,7 +45,6 @@ static void initData(GpencilModifierData *md) { TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)md; - gpmd->layername[0] = '\0'; gpmd->offset = 1; gpmd->frame_scale = 1.0f; gpmd->flag |= GP_TIME_KEEP_LOOP; @@ -55,7 +54,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static int remapTime(struct GpencilModifierData *md, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c index 95a7fb53018..c35728bc8b3 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -61,9 +61,7 @@ static void initData(GpencilModifierData *md) { TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->radius = 1.0f; gpmd->factor = 0.5f; @@ -103,7 +101,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); if (gmd->colorband) { tgmd->colorband = MEM_dupallocN(gmd->colorband); @@ -130,7 +128,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -323,6 +321,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + TintGpencilModifierData *mmd = (TintGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Tint = { /* name */ "Tint", /* structName */ "TintGpencilModifierData", @@ -343,6 +350,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Tint = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h index dd7611fe2fc..9876aa6998c 100644 --- a/source/blender/gpu/GPU_context.h +++ b/source/blender/gpu/GPU_context.h @@ -26,14 +26,14 @@ #ifndef __GPU_CONTEXT_H__ #define __GPU_CONTEXT_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "GPU_batch.h" #include "GPU_common.h" #include "GPU_shader_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct GPUContext GPUContext; GPUContext *GPU_context_create(GLuint default_framebuffer); diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index f521fa3c702..e5a6a8ffde8 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -24,6 +24,9 @@ #ifndef __GPU_DRAW_H__ #define __GPU_DRAW_H__ +#include "BLI_utildefines.h" +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -34,9 +37,6 @@ struct Image; struct ImageUser; struct Main; -#include "BLI_utildefines.h" -#include "DNA_object_enums.h" - /* OpenGL drawing functions related to shading. */ /* Initialize diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h index 1cf6475408f..47b44b59461 100644 --- a/source/blender/gpu/GPU_immediate_util.h +++ b/source/blender/gpu/GPU_immediate_util.h @@ -70,6 +70,13 @@ void imm_draw_disk_partial_fill_2d(uint pos, void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2); void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2); +void imm_draw_box_checker_2d_ex(float x1, + float y1, + float x2, + float y2, + const float color_primary[4], + const float color_secondary[4], + int checker_size); void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2); void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]); diff --git a/source/blender/gpu/GPU_init_exit.h b/source/blender/gpu/GPU_init_exit.h index 0046eaa942b..3e30a1ddcf5 100644 --- a/source/blender/gpu/GPU_init_exit.h +++ b/source/blender/gpu/GPU_init_exit.h @@ -24,12 +24,12 @@ #ifndef __GPU_INIT_EXIT_H__ #define __GPU_INIT_EXIT_H__ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - void GPU_init(void); void GPU_exit(void); bool GPU_is_initialized(void); diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index dd64b858b35..0e382f2225f 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -29,9 +29,9 @@ extern "C" { #endif typedef struct GPUShader GPUShader; +struct GPUShaderInterface; struct GPUTexture; struct GPUUniformBuffer; -struct GPUShaderInterface; /* GPU Shader * - only for fragment shaders now diff --git a/source/blender/gpu/intern/gpu_batch_private.h b/source/blender/gpu/intern/gpu_batch_private.h index 42cfc1e2a5c..58d1810ac7a 100644 --- a/source/blender/gpu/intern/gpu_batch_private.h +++ b/source/blender/gpu/intern/gpu_batch_private.h @@ -27,14 +27,14 @@ #ifndef __GPU_BATCH_PRIVATE_H__ #define __GPU_BATCH_PRIVATE_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "GPU_batch.h" #include "GPU_context.h" #include "GPU_shader_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface); #ifdef __cplusplus diff --git a/source/blender/gpu/intern/gpu_context_private.h b/source/blender/gpu/intern/gpu_context_private.h index c9379e5433f..f64cdf439a1 100644 --- a/source/blender/gpu/intern/gpu_context_private.h +++ b/source/blender/gpu/intern/gpu_context_private.h @@ -26,12 +26,12 @@ #ifndef __GPU_CONTEXT_PRIVATE_H__ #define __GPU_CONTEXT_PRIVATE_H__ +#include "GPU_context.h" + #ifdef __cplusplus extern "C" { #endif -#include "GPU_context.h" - struct GPUFrameBuffer; GLuint GPU_vao_default(void); diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index 7bcb0a7a552..d95904c0007 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -272,6 +272,14 @@ void immBegin(GPUPrimType prim_type, uint vertex_len) /* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */ +#if TRUST_NO_ONE + { + GLint bufsize; + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufsize); + assert(active_buffer->buffer_offset + bytes_needed <= bufsize); + } +#endif + active_buffer->buffer_data = glMapBufferRange( GL_ARRAY_BUFFER, active_buffer->buffer_offset, diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c index 7266f595447..e834d6afccb 100644 --- a/source/blender/gpu/intern/gpu_immediate_util.c +++ b/source/blender/gpu/intern/gpu_immediate_util.c @@ -361,25 +361,35 @@ void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2) /** * Draw a standard checkerboard to indicate transparent backgrounds. */ -void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2) +void imm_draw_box_checker_2d_ex(float x1, + float y1, + float x2, + float y2, + const float color_primary[4], + const float color_secondary[4], + int checker_size) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - float checker_primary[4]; - float checker_secondary[4]; - int checker_size = UI_GetThemeValue(TH_TRANSPARENT_CHECKER_SIZE); immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); - UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, checker_primary); - UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, checker_secondary); - immUniform4fv("color1", checker_primary); - immUniform4fv("color2", checker_secondary); + immUniform4fv("color1", color_primary); + immUniform4fv("color2", color_secondary); immUniform1i("size", checker_size); immRectf(pos, x1, y1, x2, y2); immUnbindProgram(); } +void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2) +{ + float checker_primary[4]; + float checker_secondary[4]; + UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, checker_primary); + UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, checker_secondary); + int checker_size = UI_GetThemeValue(TH_TRANSPARENT_CHECKER_SIZE); + imm_draw_box_checker_2d_ex(x1, y1, x2, y2, checker_primary, checker_secondary, checker_size); +} void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]) { diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index cb1cd9a6f6d..1caa88d18ae 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -254,8 +254,12 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) } /* TODO: reject DOUBLE gl_types */ - input->location = glGetAttribLocation(program, name); + /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ + if (input->location == -1) { + MEM_freeN(input); + continue; + } shaderface->enabled_attr_mask |= (1 << input->location); diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 496e8981f2b..f30270b9eed 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -559,10 +559,10 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport, { /** * HACK(fclem): We copy the settings here to avoid use after free if an update frees the scene - * and the viewport stays cached (see T75443). But this means the OCIO curvemapping caching - * (which is based on CurveMap pointer address) cannot operate correctly and it will create - * a different OCIO processor for each viewport. We try to only realloc the curvemap copy if - * needed to avoid uneeded cache invalidation. + * and the viewport stays cached (see T75443). But this means the OCIO curve-mapping caching + * (which is based on #CurveMap pointer address) cannot operate correctly and it will create + * a different OCIO processor for each viewport. We try to only reallocate the curve-map copy + * if needed to avoid unneeded cache invalidation. */ if (view_settings->curve_mapping) { if (viewport->view_settings.curve_mapping) { diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 19a4390598f..66ed0dd0fa5 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -40,7 +40,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BIK_api.h" #include "BLI_blenlib.h" #include "BLI_math.h" @@ -55,7 +54,6 @@ extern "C" { #include "DNA_constraint_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -}; #include "itasc_plugin.h" diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h index c252a9a63f8..9f89969cf1c 100644 --- a/source/blender/imbuf/intern/IMB_allocimbuf.h +++ b/source/blender/imbuf/intern/IMB_allocimbuf.h @@ -24,6 +24,10 @@ #ifndef __IMB_ALLOCIMBUF_H__ #define __IMB_ALLOCIMBUF_H__ +#ifdef __cplusplus +extern "C" { +#endif + struct ImBuf; void imb_refcounter_lock_init(void); @@ -44,4 +48,8 @@ void imb_mmap_unlock(void); bool imb_addencodedbufferImBuf(struct ImBuf *ibuf); bool imb_enlargeencodedbufferImBuf(struct ImBuf *ibuf); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index f0e599c1375..79abe8472b9 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -27,6 +27,10 @@ #include "BLI_sys_types.h" #include "DNA_listBase.h" +#ifdef __cplusplus +extern "C" { +#endif + struct ImBuf; struct OCIO_ConstProcessorRcPtr; @@ -123,4 +127,8 @@ void colorspace_set_default_role(char *colorspace, int size, int role); void colormanage_imbuf_set_default_spaces(struct ImBuf *ibuf); void colormanage_imbuf_make_linear(struct ImBuf *ibuf, const char *from_colorspace); +#ifdef __cplusplus +} +#endif + #endif /* __IMB_COLORMANAGEMENT_INTERN_H__ */ diff --git a/source/blender/imbuf/intern/cineon/cineonlib.h b/source/blender/imbuf/intern/cineon/cineonlib.h index 461407fcf25..040435e44ee 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.h +++ b/source/blender/imbuf/intern/cineon/cineonlib.h @@ -26,12 +26,12 @@ #ifndef __CINEONLIB_H__ #define __CINEONLIB_H__ +#include "logImageCore.h" + #ifdef __cplusplus extern "C" { #endif -#include "logImageCore.h" - #define CINEON_FILE_MAGIC 0x802A5FD7 #define CINEON_UNDEFINED_U8 0xFF #define CINEON_UNDEFINED_U16 0xFFFF diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h index bf07b8e329d..3a7ebe9dddf 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.h +++ b/source/blender/imbuf/intern/cineon/dpxlib.h @@ -25,12 +25,12 @@ #ifndef __DPXLIB_H__ #define __DPXLIB_H__ +#include "logImageCore.h" + #ifdef __cplusplus extern "C" { #endif -#include "logImageCore.h" - #define DPX_FILE_MAGIC 0x53445058 #define DPX_UNDEFINED_U8 0xFF #define DPX_UNDEFINED_U16 0xFFFF diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 832b380bbc2..83d304203a0 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -18,9 +18,7 @@ * \ingroup imbdds */ -extern "C" { #include "BLI_utildefines.h" -} #include <DirectDrawSurface.h> #include <FlipDXT.h> @@ -34,8 +32,6 @@ extern "C" { # include "utfconv.h" #endif -extern "C" { - #include "IMB_allocimbuf.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -44,6 +40,8 @@ extern "C" { #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" +extern "C" { + int imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/) { return (0); /* todo: finish this function */ diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h index 12db8aa6416..e6782e217fc 100644 --- a/source/blender/imbuf/intern/dds/dds_api.h +++ b/source/blender/imbuf/intern/dds/dds_api.h @@ -21,12 +21,12 @@ #ifndef __DDS_API_H__ #define __DDS_API_H__ +#include "../../IMB_imbuf.h" + #ifdef __cplusplus extern "C" { #endif -#include "../../IMB_imbuf.h" - int imb_is_a_dds(const unsigned char *mem); /* use only first 32 bytes of mem */ int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags); struct ImBuf *imb_load_dds(const unsigned char *mem, diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index aa82487d69f..7ebbd1a7409 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -338,9 +338,9 @@ void nearest_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, in /*********************** Threaded image processing *************************/ -static void processor_apply_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) +static void processor_apply_func(TaskPool *__restrict pool, void *taskdata) { - void (*do_thread)(void *) = (void (*)(void *))BLI_task_pool_userdata(pool); + void (*do_thread)(void *) = (void (*)(void *))BLI_task_pool_user_data(pool); do_thread(taskdata); } @@ -353,14 +353,13 @@ void IMB_processor_apply_threaded( { const int lines_per_task = 64; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; void *handles; int total_tasks = (buffer_lines + lines_per_task - 1) / lines_per_task; int i, start_line; - task_pool = BLI_task_pool_create(task_scheduler, do_thread, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(do_thread, TASK_PRIORITY_LOW); handles = MEM_callocN(handle_size * total_tasks, "processor apply threaded handles"); @@ -399,11 +398,9 @@ typedef struct ScanlineGlobalData { int total_scanlines; } ScanlineGlobalData; -static void processor_apply_scanline_func(TaskPool *__restrict pool, - void *taskdata, - int UNUSED(threadid)) +static void processor_apply_scanline_func(TaskPool *__restrict pool, void *taskdata) { - ScanlineGlobalData *data = BLI_task_pool_userdata(pool); + ScanlineGlobalData *data = BLI_task_pool_user_data(pool); int start_scanline = POINTER_AS_INT(taskdata); int num_scanlines = min_ii(data->scanlines_per_task, data->total_scanlines - start_scanline); data->do_thread(data->custom_data, start_scanline, num_scanlines); @@ -420,8 +417,7 @@ void IMB_processor_apply_threaded_scanlines(int total_scanlines, data.scanlines_per_task = scanlines_per_task; data.total_scanlines = total_scanlines; const int total_tasks = (total_scanlines + scanlines_per_task - 1) / scanlines_per_task; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &data, TASK_PRIORITY_LOW); + TaskPool *task_pool = BLI_task_pool_create(&data, TASK_PRIORITY_LOW); for (int i = 0, start_line = 0; i < total_tasks; i++) { BLI_task_pool_push( task_pool, processor_apply_scanline_func, POINTER_FROM_INT(start_line), false, NULL); diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 6d3234771e7..df51aada5f0 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -35,7 +35,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_blenlib.h" #include "IMB_allocimbuf.h" @@ -43,7 +42,6 @@ extern "C" { #include "IMB_colormanagement_intern.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} OIIO_NAMESPACE_USING diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h index 520ad0c5da5..3dd089d65cb 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.h +++ b/source/blender/imbuf/intern/oiio/openimageio_api.h @@ -24,12 +24,12 @@ #ifndef __OPENIMAGEIO_API_H__ #define __OPENIMAGEIO_API_H__ +#include <stdio.h> + #ifdef __cplusplus extern "C" { #endif -#include <stdio.h> - struct ImBuf; int imb_is_a_photoshop(const char *name); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index a1719895853..62cc2e605e5 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -75,7 +75,7 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) { } #endif - +} #include "BLI_blenlib.h" #include "BLI_math_color.h" #include "BLI_threads.h" @@ -84,17 +84,13 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include "BKE_image.h" #include "IMB_allocimbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_metadata.h" #include "openexr_multi.h" -} - -extern "C" { -#include "IMB_colormanagement.h" -#include "IMB_colormanagement_intern.h" -} using namespace Imf; using namespace Imath; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h index df03d0d205f..b0835e5082e 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.h +++ b/source/blender/imbuf/intern/openexr/openexr_api.h @@ -24,12 +24,12 @@ #ifndef __OPENEXR_API_H__ #define __OPENEXR_API_H__ +#include <stdio.h> + #ifdef __cplusplus extern "C" { #endif -#include <stdio.h> - void imb_initopenexr(void); void imb_exitopenexr(void); diff --git a/source/blender/io/alembic/CMakeLists.txt b/source/blender/io/alembic/CMakeLists.txt index cbcdfaf4b77..6de7d327d4e 100644 --- a/source/blender/io/alembic/CMakeLists.txt +++ b/source/blender/io/alembic/CMakeLists.txt @@ -41,6 +41,7 @@ set(INC_SYS ) set(SRC + intern/abc_axis_conversion.cc intern/abc_customdata.cc intern/abc_exporter.cc intern/abc_reader_archive.cc @@ -65,6 +66,7 @@ set(SRC intern/alembic_capi.cc ABC_alembic.h + intern/abc_axis_conversion.h intern/abc_customdata.h intern/abc_exporter.h intern/abc_reader_archive.h diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.cc b/source/blender/io/alembic/intern/abc_axis_conversion.cc new file mode 100644 index 00000000000..17db5e9c99f --- /dev/null +++ b/source/blender/io/alembic/intern/abc_axis_conversion.cc @@ -0,0 +1,166 @@ +/* + * 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 Alembic + */ + +#include "abc_axis_conversion.h" + +extern "C" { +#include "BLI_assert.h" +#include "DNA_object_types.h" + +#include "BLI_math_geom.h" +} + +void create_swapped_rotation_matrix(float rot_x_mat[3][3], + float rot_y_mat[3][3], + float rot_z_mat[3][3], + const float euler[3], + AbcAxisSwapMode mode) +{ + const float rx = euler[0]; + float ry; + float rz; + + /* Apply transformation */ + switch (mode) { + case ABC_ZUP_FROM_YUP: + ry = -euler[2]; + rz = euler[1]; + break; + case ABC_YUP_FROM_ZUP: + ry = euler[2]; + rz = -euler[1]; + break; + default: + ry = 0.0f; + rz = 0.0f; + BLI_assert(false); + break; + } + + unit_m3(rot_x_mat); + unit_m3(rot_y_mat); + unit_m3(rot_z_mat); + + rot_x_mat[1][1] = cos(rx); + rot_x_mat[2][1] = -sin(rx); + rot_x_mat[1][2] = sin(rx); + rot_x_mat[2][2] = cos(rx); + + rot_y_mat[2][2] = cos(ry); + rot_y_mat[0][2] = -sin(ry); + rot_y_mat[2][0] = sin(ry); + rot_y_mat[0][0] = cos(ry); + + rot_z_mat[0][0] = cos(rz); + rot_z_mat[1][0] = -sin(rz); + rot_z_mat[0][1] = sin(rz); + rot_z_mat[1][1] = cos(rz); +} + +/* Convert matrix from Z=up to Y=up or vice versa. + * Use yup_mat = zup_mat for in-place conversion. */ +void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode) +{ + float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4]; + float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; + float src_trans[3], dst_scale[3], src_scale[3], euler[3]; + + zero_v3(src_trans); + zero_v3(dst_scale); + zero_v3(src_scale); + zero_v3(euler); + unit_m3(src_rot); + unit_m3(dst_rot); + unit_m4(dst_scale_mat); + + /* TODO(Sybren): This code assumes there is no sheer component and no + * homogeneous scaling component, which is not always true when writing + * non-hierarchical (e.g. flat) objects (e.g. when parent has non-uniform + * scale and the child rotates). This is currently not taken into account + * when axis-swapping. */ + + /* Extract translation, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_XZY, src_rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat); + mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat); + mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat); + + mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot); + + /* Start construction of dst_mat from rotation matrix */ + unit_m4(dst_mat); + copy_m4_m3(dst_mat, dst_rot); + + /* Apply translation */ + switch (mode) { + case ABC_ZUP_FROM_YUP: + copy_zup_from_yup(dst_mat[3], src_trans); + break; + case ABC_YUP_FROM_ZUP: + copy_yup_from_zup(dst_mat[3], src_trans); + break; + default: + BLI_assert(false); + } + + /* Apply scale matrix. Swaps y and z, but does not + * negate like translation does. */ + dst_scale[0] = src_scale[0]; + dst_scale[1] = src_scale[2]; + dst_scale[2] = src_scale[1]; + + size_to_mat4(dst_scale_mat, dst_scale); + mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat); +} + +/* Recompute transform matrix of object in new coordinate system + * (from Z-Up to Y-Up). */ +void create_transform_matrix(Object *obj, + float r_yup_mat[4][4], + AbcMatrixMode mode, + Object *proxy_from) +{ + float zup_mat[4][4]; + + /* get local or world matrix. */ + if (mode == ABC_MATRIX_LOCAL && obj->parent) { + /* Note that this produces another matrix than the local matrix, due to + * constraints and modifiers as well as the obj->parentinv matrix. */ + invert_m4_m4(obj->parent->imat, obj->parent->obmat); + mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat); + } + else { + copy_m4_m4(zup_mat, obj->obmat); + } + + if (proxy_from) { + mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); + } + + copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); +} diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.h b/source/blender/io/alembic/intern/abc_axis_conversion.h new file mode 100644 index 00000000000..7fde0e92ea4 --- /dev/null +++ b/source/blender/io/alembic/intern/abc_axis_conversion.h @@ -0,0 +1,99 @@ +/* + * 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) 2016 Kévin Dietrich & Blender Foundation. + * All rights reserved. + */ +#pragma once + +/** \file + * \ingroup Alembic + */ + +struct Object; + +#ifdef _MSC_VER +# define ABC_INLINE static __forceinline +#else +# define ABC_INLINE static inline +#endif + +/* TODO(kevin): for now keeping these transformations hardcoded to make sure + * everything works properly, and also because Alembic is almost exclusively + * used in Y-up software, but eventually they'll be set by the user in the UI + * like other importers/exporters do, to support other axis. */ + +/* Copy from Y-up to Z-up. */ + +ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3]) +{ + const float old_yup1 = yup[1]; /* in case zup == yup */ + zup[0] = yup[0]; + zup[1] = -yup[2]; + zup[2] = old_yup1; +} + +ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3]) +{ + const short old_yup1 = yup[1]; /* in case zup == yup */ + zup[0] = yup[0]; + zup[1] = -yup[2]; + zup[2] = old_yup1; +} + +/* Copy from Z-up to Y-up. */ + +ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3]) +{ + const float old_zup1 = zup[1]; /* in case yup == zup */ + yup[0] = zup[0]; + yup[1] = zup[2]; + yup[2] = -old_zup1; +} + +ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3]) +{ + const short old_zup1 = zup[1]; /* in case yup == zup */ + yup[0] = zup[0]; + yup[1] = zup[2]; + yup[2] = -old_zup1; +} + +/* Names are given in (dst, src) order, just like + * the parameters of copy_m44_axis_swap() */ +typedef enum { + ABC_ZUP_FROM_YUP = 1, + ABC_YUP_FROM_ZUP = 2, +} AbcAxisSwapMode; + +/* Create a rotation matrix for each axis from euler angles. + * Euler angles are swapped to change coordinate system. */ +void create_swapped_rotation_matrix(float rot_x_mat[3][3], + float rot_y_mat[3][3], + float rot_z_mat[3][3], + const float euler[3], + AbcAxisSwapMode mode); + +void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode); + +typedef enum { + ABC_MATRIX_WORLD = 1, + ABC_MATRIX_LOCAL = 2, +} AbcMatrixMode; + +void create_transform_matrix(Object *obj, + float r_transform_mat[4][4], + AbcMatrixMode mode, + Object *proxy_from); diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index c5f60ac3e29..40a057f9a20 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -27,7 +27,6 @@ #include <algorithm> #include <unordered_map> -extern "C" { #include "DNA_customdata_types.h" #include "DNA_meshdata_types.h" @@ -35,7 +34,6 @@ extern "C" { #include "BLI_utildefines.h" #include "BKE_customdata.h" -} /* NOTE: for now only UVs and Vertex Colors are supported for streaming. * Although Alembic only allows for a single UV layer per {I|O}Schema, and does diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index 11b005eb66a..04572c736af 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_exporter.cc b/source/blender/io/alembic/intern/abc_exporter.cc index e3e095463b4..dbf24452b78 100644 --- a/source/blender/io/alembic/intern/abc_exporter.cc +++ b/source/blender/io/alembic/intern/abc_exporter.cc @@ -33,7 +33,6 @@ #include "abc_writer_points.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_camera_types.h" #include "DNA_curve_types.h" #include "DNA_fluid_types.h" @@ -62,7 +61,6 @@ extern "C" { #include "BKE_scene.h" #include "DEG_depsgraph_query.h" -} using Alembic::Abc::OBox3dProperty; using Alembic::Abc::TimeSamplingPtr; @@ -105,7 +103,7 @@ ExportSettings::ExportSettings() static bool object_is_smoke_sim(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (md) { FluidModifierData *smd = reinterpret_cast<FluidModifierData *>(md); diff --git a/source/blender/io/alembic/intern/abc_reader_archive.cc b/source/blender/io/alembic/intern/abc_reader_archive.cc index 6ad44553701..563466d81bc 100644 --- a/source/blender/io/alembic/intern/abc_reader_archive.cc +++ b/source/blender/io/alembic/intern/abc_reader_archive.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -23,12 +23,10 @@ #include "abc_reader_archive.h" -extern "C" { #include "BKE_main.h" #include "BLI_path_util.h" #include "BLI_string.h" -} #ifdef WIN32 # include "utfconv.h" diff --git a/source/blender/io/alembic/intern/abc_reader_archive.h b/source/blender/io/alembic/intern/abc_reader_archive.h index bdb53bd0b8c..35273e10108 100644 --- a/source/blender/io/alembic/intern/abc_reader_archive.h +++ b/source/blender/io/alembic/intern/abc_reader_archive.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_reader_camera.cc b/source/blender/io/alembic/intern/abc_reader_camera.cc index ab506f32cbe..0752534f8c2 100644 --- a/source/blender/io/alembic/intern/abc_reader_camera.cc +++ b/source/blender/io/alembic/intern/abc_reader_camera.cc @@ -22,7 +22,6 @@ #include "abc_reader_transform.h" #include "abc_util.h" -extern "C" { #include "DNA_camera_types.h" #include "DNA_object_types.h" @@ -30,7 +29,6 @@ extern "C" { #include "BKE_object.h" #include "BLI_math.h" -} using Alembic::AbcGeom::CameraSample; using Alembic::AbcGeom::ICamera; diff --git a/source/blender/io/alembic/intern/abc_reader_curves.cc b/source/blender/io/alembic/intern/abc_reader_curves.cc index 1be164c7c94..d5e0b694294 100644 --- a/source/blender/io/alembic/intern/abc_reader_curves.cc +++ b/source/blender/io/alembic/intern/abc_reader_curves.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -22,6 +22,7 @@ */ #include "abc_reader_curves.h" +#include "abc_axis_conversion.h" #include "abc_reader_transform.h" #include "abc_util.h" @@ -29,7 +30,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" @@ -38,7 +38,6 @@ extern "C" { #include "BKE_curve.h" #include "BKE_mesh.h" #include "BKE_object.h" -} using Alembic::Abc::FloatArraySamplePtr; using Alembic::Abc::Int32ArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_reader_curves.h b/source/blender/io/alembic/intern/abc_reader_curves.h index 763a83f586f..eb0538308f8 100644 --- a/source/blender/io/alembic/intern/abc_reader_curves.h +++ b/source/blender/io/alembic/intern/abc_reader_curves.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index b69a5301d76..8b79a3a0aa0 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -19,6 +19,7 @@ */ #include "abc_reader_mesh.h" +#include "abc_axis_conversion.h" #include "abc_reader_transform.h" #include "abc_util.h" @@ -26,7 +27,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -39,7 +39,6 @@ extern "C" { #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_object.h" -} using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::P3fArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_reader_nurbs.cc b/source/blender/io/alembic/intern/abc_reader_nurbs.cc index 0ada10baba5..10d9a35a8e1 100644 --- a/source/blender/io/alembic/intern/abc_reader_nurbs.cc +++ b/source/blender/io/alembic/intern/abc_reader_nurbs.cc @@ -19,12 +19,12 @@ */ #include "abc_reader_nurbs.h" +#include "abc_axis_conversion.h" #include "abc_reader_transform.h" #include "abc_util.h" #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" @@ -33,7 +33,6 @@ extern "C" { #include "BKE_curve.h" #include "BKE_object.h" -} using Alembic::AbcGeom::FloatArraySamplePtr; using Alembic::AbcGeom::kWrapExisting; diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc index 9b0c3237c45..e5bd0771a42 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.cc +++ b/source/blender/io/alembic/intern/abc_reader_object.cc @@ -19,9 +19,9 @@ */ #include "abc_reader_object.h" +#include "abc_axis_conversion.h" #include "abc_util.h" -extern "C" { #include "DNA_cachefile_types.h" #include "DNA_constraint_types.h" #include "DNA_modifier_types.h" @@ -36,7 +36,6 @@ extern "C" { #include "BLI_math_geom.h" #include "BLI_string.h" #include "BLI_utildefines.h" -} using Alembic::AbcGeom::IObject; using Alembic::AbcGeom::IXform; @@ -295,7 +294,7 @@ void AbcObjectReader::read_matrix(float r_mat[4][4] /* local matrix */, void AbcObjectReader::addCacheModifier() { - ModifierData *md = modifier_new(eModifierType_MeshSequenceCache); + ModifierData *md = BKE_modifier_new(eModifierType_MeshSequenceCache); BLI_addtail(&m_object->modifiers, md); MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md); diff --git a/source/blender/io/alembic/intern/abc_reader_object.h b/source/blender/io/alembic/intern/abc_reader_object.h index 94923df2df9..dcc2697e0b5 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.h +++ b/source/blender/io/alembic/intern/abc_reader_object.h @@ -24,9 +24,7 @@ #include <Alembic/Abc/All.h> #include <Alembic/AbcGeom/All.h> -extern "C" { #include "DNA_ID.h" -} struct CacheFile; struct Main; diff --git a/source/blender/io/alembic/intern/abc_reader_points.cc b/source/blender/io/alembic/intern/abc_reader_points.cc index e4dc345f868..c5d08693176 100644 --- a/source/blender/io/alembic/intern/abc_reader_points.cc +++ b/source/blender/io/alembic/intern/abc_reader_points.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -26,14 +26,12 @@ #include "abc_reader_transform.h" #include "abc_util.h" -extern "C" { #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_object.h" -} using Alembic::AbcGeom::kWrapExisting; using Alembic::AbcGeom::N3fArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_reader_points.h b/source/blender/io/alembic/intern/abc_reader_points.h index bb33afb466f..99881e091f9 100644 --- a/source/blender/io/alembic/intern/abc_reader_points.h +++ b/source/blender/io/alembic/intern/abc_reader_points.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_reader_transform.cc b/source/blender/io/alembic/intern/abc_reader_transform.cc index ce569a9ccb5..3df391f8432 100644 --- a/source/blender/io/alembic/intern/abc_reader_transform.cc +++ b/source/blender/io/alembic/intern/abc_reader_transform.cc @@ -21,13 +21,11 @@ #include "abc_reader_transform.h" #include "abc_util.h" -extern "C" { #include "DNA_object_types.h" #include "BLI_utildefines.h" #include "BKE_object.h" -} using Alembic::Abc::ISampleSelector; diff --git a/source/blender/io/alembic/intern/abc_util.cc b/source/blender/io/alembic/intern/abc_util.cc index b26ef8b3b76..1f3bd2a1aaa 100644 --- a/source/blender/io/alembic/intern/abc_util.cc +++ b/source/blender/io/alembic/intern/abc_util.cc @@ -20,6 +20,7 @@ #include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_reader_camera.h" #include "abc_reader_curves.h" #include "abc_reader_mesh.h" @@ -31,13 +32,11 @@ #include <algorithm> -extern "C" { #include "DNA_object_types.h" #include "BLI_math_geom.h" #include "PIL_time.h" -} std::string get_id_name(const Object *const ob) { @@ -121,144 +120,6 @@ void split(const std::string &s, const char delim, std::vector<std::string> &tok } } -void create_swapped_rotation_matrix(float rot_x_mat[3][3], - float rot_y_mat[3][3], - float rot_z_mat[3][3], - const float euler[3], - AbcAxisSwapMode mode) -{ - const float rx = euler[0]; - float ry; - float rz; - - /* Apply transformation */ - switch (mode) { - case ABC_ZUP_FROM_YUP: - ry = -euler[2]; - rz = euler[1]; - break; - case ABC_YUP_FROM_ZUP: - ry = euler[2]; - rz = -euler[1]; - break; - default: - ry = 0.0f; - rz = 0.0f; - BLI_assert(false); - break; - } - - unit_m3(rot_x_mat); - unit_m3(rot_y_mat); - unit_m3(rot_z_mat); - - rot_x_mat[1][1] = cos(rx); - rot_x_mat[2][1] = -sin(rx); - rot_x_mat[1][2] = sin(rx); - rot_x_mat[2][2] = cos(rx); - - rot_y_mat[2][2] = cos(ry); - rot_y_mat[0][2] = -sin(ry); - rot_y_mat[2][0] = sin(ry); - rot_y_mat[0][0] = cos(ry); - - rot_z_mat[0][0] = cos(rz); - rot_z_mat[1][0] = -sin(rz); - rot_z_mat[0][1] = sin(rz); - rot_z_mat[1][1] = cos(rz); -} - -/* Convert matrix from Z=up to Y=up or vice versa. - * Use yup_mat = zup_mat for in-place conversion. */ -void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode) -{ - float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4]; - float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; - float src_trans[3], dst_scale[3], src_scale[3], euler[3]; - - zero_v3(src_trans); - zero_v3(dst_scale); - zero_v3(src_scale); - zero_v3(euler); - unit_m3(src_rot); - unit_m3(dst_rot); - unit_m4(dst_scale_mat); - - /* TODO(Sybren): This code assumes there is no sheer component and no - * homogeneous scaling component, which is not always true when writing - * non-hierarchical (e.g. flat) objects (e.g. when parent has non-uniform - * scale and the child rotates). This is currently not taken into account - * when axis-swapping. */ - - /* Extract translation, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_XZY, src_rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat); - mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat); - mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat); - - mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot); - - /* Start construction of dst_mat from rotation matrix */ - unit_m4(dst_mat); - copy_m4_m3(dst_mat, dst_rot); - - /* Apply translation */ - switch (mode) { - case ABC_ZUP_FROM_YUP: - copy_zup_from_yup(dst_mat[3], src_trans); - break; - case ABC_YUP_FROM_ZUP: - copy_yup_from_zup(dst_mat[3], src_trans); - break; - default: - BLI_assert(false); - } - - /* Apply scale matrix. Swaps y and z, but does not - * negate like translation does. */ - dst_scale[0] = src_scale[0]; - dst_scale[1] = src_scale[2]; - dst_scale[2] = src_scale[1]; - - size_to_mat4(dst_scale_mat, dst_scale); - mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat); -} - -/* Recompute transform matrix of object in new coordinate system - * (from Z-Up to Y-Up). */ -void create_transform_matrix(Object *obj, - float r_yup_mat[4][4], - AbcMatrixMode mode, - Object *proxy_from) -{ - float zup_mat[4][4]; - - /* get local or world matrix. */ - if (mode == ABC_MATRIX_LOCAL && obj->parent) { - /* Note that this produces another matrix than the local matrix, due to - * constraints and modifiers as well as the obj->parentinv matrix. */ - invert_m4_m4(obj->parent->imat, obj->parent->obmat); - mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat); - } - else { - copy_m4_m4(zup_mat, obj->obmat); - } - - if (proxy_from) { - mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); - } - - copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); -} - bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name) { if (!prop.valid()) { diff --git a/source/blender/io/alembic/intern/abc_util.h b/source/blender/io/alembic/intern/abc_util.h index 0b3462c2132..57b4d9800a5 100644 --- a/source/blender/io/alembic/intern/abc_util.h +++ b/source/blender/io/alembic/intern/abc_util.h @@ -56,15 +56,6 @@ Imath::M44d convert_matrix_datatype(float mat[4][4]); /* Convert from Alembic to float matrix representations. Does NOT convert from Y-up to Z-up. */ void convert_matrix_datatype(const Imath::M44d &xform, float r_mat[4][4]); -typedef enum { - ABC_MATRIX_WORLD = 1, - ABC_MATRIX_LOCAL = 2, -} AbcMatrixMode; -void create_transform_matrix(Object *obj, - float r_transform_mat[4][4], - AbcMatrixMode mode, - Object *proxy_from); - void split(const std::string &s, const char delim, std::vector<std::string> &tokens); template<class TContainer> bool begins_with(const TContainer &input, const TContainer &match) @@ -115,66 +106,6 @@ float get_weight_and_index(float time, AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings); -/* ************************** */ - -/* TODO(kevin): for now keeping these transformations hardcoded to make sure - * everything works properly, and also because Alembic is almost exclusively - * used in Y-up software, but eventually they'll be set by the user in the UI - * like other importers/exporters do, to support other axis. */ - -/* Copy from Y-up to Z-up. */ - -ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3]) -{ - const float old_yup1 = yup[1]; /* in case zup == yup */ - zup[0] = yup[0]; - zup[1] = -yup[2]; - zup[2] = old_yup1; -} - -ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3]) -{ - const short old_yup1 = yup[1]; /* in case zup == yup */ - zup[0] = yup[0]; - zup[1] = -yup[2]; - zup[2] = old_yup1; -} - -/* Copy from Z-up to Y-up. */ - -ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3]) -{ - const float old_zup1 = zup[1]; /* in case yup == zup */ - yup[0] = zup[0]; - yup[1] = zup[2]; - yup[2] = -old_zup1; -} - -ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3]) -{ - const short old_zup1 = zup[1]; /* in case yup == zup */ - yup[0] = zup[0]; - yup[1] = zup[2]; - yup[2] = -old_zup1; -} - -/* Names are given in (dst, src) order, just like - * the parameters of copy_m44_axis_swap() */ -typedef enum { - ABC_ZUP_FROM_YUP = 1, - ABC_YUP_FROM_ZUP = 2, -} AbcAxisSwapMode; - -/* Create a rotation matrix for each axis from euler angles. - * Euler angles are swapped to change coordinate system. */ -void create_swapped_rotation_matrix(float rot_x_mat[3][3], - float rot_y_mat[3][3], - float rot_z_mat[3][3], - const float euler[3], - AbcAxisSwapMode mode); - -void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode); - /* *************************** */ #undef ABC_DEBUG_TIME diff --git a/source/blender/io/alembic/intern/abc_writer_archive.cc b/source/blender/io/alembic/intern/abc_writer_archive.cc index af18d480a18..5aae1f05f4b 100644 --- a/source/blender/io/alembic/intern/abc_writer_archive.cc +++ b/source/blender/io/alembic/intern/abc_writer_archive.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -22,14 +22,13 @@ */ #include "abc_writer_archive.h" -extern "C" { + #include "BKE_blender_version.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "DNA_scene_types.h" -} #ifdef WIN32 # include "utfconv.h" diff --git a/source/blender/io/alembic/intern/abc_writer_archive.h b/source/blender/io/alembic/intern/abc_writer_archive.h index e261e60990a..82b0e98b376 100644 --- a/source/blender/io/alembic/intern/abc_writer_archive.h +++ b/source/blender/io/alembic/intern/abc_writer_archive.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_writer_camera.cc b/source/blender/io/alembic/intern/abc_writer_camera.cc index e705e5ba911..07ae81e584f 100644 --- a/source/blender/io/alembic/intern/abc_writer_camera.cc +++ b/source/blender/io/alembic/intern/abc_writer_camera.cc @@ -21,10 +21,8 @@ #include "abc_writer_camera.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_camera_types.h" #include "DNA_object_types.h" -} using Alembic::AbcGeom::OCamera; using Alembic::AbcGeom::OFloatProperty; diff --git a/source/blender/io/alembic/intern/abc_writer_curves.cc b/source/blender/io/alembic/intern/abc_writer_curves.cc index 3ab9b365a72..db93ac1920e 100644 --- a/source/blender/io/alembic/intern/abc_writer_curves.cc +++ b/source/blender/io/alembic/intern/abc_writer_curves.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -22,17 +22,16 @@ */ #include "abc_writer_curves.h" +#include "abc_axis_conversion.h" #include "abc_reader_curves.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "BKE_curve.h" #include "BKE_mesh.h" #include "BKE_object.h" -} using Alembic::AbcGeom::OCompoundProperty; using Alembic::AbcGeom::OCurves; diff --git a/source/blender/io/alembic/intern/abc_writer_curves.h b/source/blender/io/alembic/intern/abc_writer_curves.h index e57978ada2a..83f0289dd2d 100644 --- a/source/blender/io/alembic/intern/abc_writer_curves.h +++ b/source/blender/io/alembic/intern/abc_writer_curves.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_writer_hair.cc b/source/blender/io/alembic/intern/abc_writer_hair.cc index f29d195f2ff..ed62889b03d 100644 --- a/source/blender/io/alembic/intern/abc_writer_hair.cc +++ b/source/blender/io/alembic/intern/abc_writer_hair.cc @@ -19,12 +19,11 @@ */ #include "abc_writer_hair.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_writer_transform.h" #include <cstdio> -extern "C" { #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -35,7 +34,6 @@ extern "C" { #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_particle.h" -} using Alembic::Abc::P3fArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_writer_mball.cc b/source/blender/io/alembic/intern/abc_writer_mball.cc index 151848674f9..3593acf18b0 100644 --- a/source/blender/io/alembic/intern/abc_writer_mball.cc +++ b/source/blender/io/alembic/intern/abc_writer_mball.cc @@ -21,7 +21,6 @@ #include "abc_writer_mball.h" #include "abc_writer_mesh.h" -extern "C" { #include "DNA_mesh_types.h" #include "DNA_meta_types.h" #include "DNA_object_types.h" @@ -33,7 +32,6 @@ extern "C" { #include "BKE_object.h" #include "BLI_utildefines.h" -} AbcMBallWriter::AbcMBallWriter(Main *bmain, Object *ob, diff --git a/source/blender/io/alembic/intern/abc_writer_mesh.cc b/source/blender/io/alembic/intern/abc_writer_mesh.cc index f7b575e7b23..89c37dab468 100644 --- a/source/blender/io/alembic/intern/abc_writer_mesh.cc +++ b/source/blender/io/alembic/intern/abc_writer_mesh.cc @@ -19,10 +19,9 @@ */ #include "abc_writer_mesh.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -40,7 +39,6 @@ extern "C" { #include "bmesh_tools.h" #include "DEG_depsgraph_query.h" -} using Alembic::Abc::FloatArraySample; using Alembic::Abc::Int32ArraySample; @@ -169,7 +167,7 @@ static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last); for (; md; md = md->prev) { - if (!modifier_isEnabled(scene, md, eModifierMode_Render)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) { continue; } @@ -192,9 +190,9 @@ static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluidsim); - if (md && (modifier_isEnabled(scene, md, eModifierMode_Render))) { + if (md && (BKE_modifier_is_enabled(scene, md, eModifierMode_Render))) { FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md); if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) { diff --git a/source/blender/io/alembic/intern/abc_writer_nurbs.cc b/source/blender/io/alembic/intern/abc_writer_nurbs.cc index d643f5482c0..8b4a1050d33 100644 --- a/source/blender/io/alembic/intern/abc_writer_nurbs.cc +++ b/source/blender/io/alembic/intern/abc_writer_nurbs.cc @@ -19,17 +19,15 @@ */ #include "abc_writer_nurbs.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "BLI_listbase.h" #include "BKE_curve.h" -} using Alembic::AbcGeom::FloatArraySample; using Alembic::AbcGeom::OBoolProperty; diff --git a/source/blender/io/alembic/intern/abc_writer_object.cc b/source/blender/io/alembic/intern/abc_writer_object.cc index 75dc93bd08e..f4a3587f54d 100644 --- a/source/blender/io/alembic/intern/abc_writer_object.cc +++ b/source/blender/io/alembic/intern/abc_writer_object.cc @@ -20,11 +20,9 @@ #include "abc_writer_object.h" -extern "C" { #include "DNA_object_types.h" #include "BKE_object.h" -} AbcObjectWriter::AbcObjectWriter(Object *ob, uint32_t time_sampling, diff --git a/source/blender/io/alembic/intern/abc_writer_object.h b/source/blender/io/alembic/intern/abc_writer_object.h index c3511566372..830c4aee903 100644 --- a/source/blender/io/alembic/intern/abc_writer_object.h +++ b/source/blender/io/alembic/intern/abc_writer_object.h @@ -26,9 +26,7 @@ #include "abc_exporter.h" -extern "C" { #include "DNA_ID.h" -} class AbcTransformWriter; diff --git a/source/blender/io/alembic/intern/abc_writer_points.cc b/source/blender/io/alembic/intern/abc_writer_points.cc index 70a1ead239a..d45af2eed4c 100644 --- a/source/blender/io/alembic/intern/abc_writer_points.cc +++ b/source/blender/io/alembic/intern/abc_writer_points.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -26,7 +26,6 @@ #include "abc_writer_mesh.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -36,7 +35,6 @@ extern "C" { #include "BLI_math.h" #include "DEG_depsgraph_query.h" -} using Alembic::AbcGeom::kVertexScope; using Alembic::AbcGeom::OPoints; diff --git a/source/blender/io/alembic/intern/abc_writer_points.h b/source/blender/io/alembic/intern/abc_writer_points.h index c171cddd10e..184a363ae6b 100644 --- a/source/blender/io/alembic/intern/abc_writer_points.h +++ b/source/blender/io/alembic/intern/abc_writer_points.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_writer_transform.cc b/source/blender/io/alembic/intern/abc_writer_transform.cc index d7bcc46d96f..1ec7db0a1c6 100644 --- a/source/blender/io/alembic/intern/abc_writer_transform.cc +++ b/source/blender/io/alembic/intern/abc_writer_transform.cc @@ -19,17 +19,15 @@ */ #include "abc_writer_transform.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include <OpenEXR/ImathBoxAlgo.h> -extern "C" { #include "DNA_object_types.h" #include "BLI_math.h" #include "DEG_depsgraph_query.h" -} using Alembic::AbcGeom::OObject; using Alembic::AbcGeom::OXform; diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index ced5791e0e8..987a3cacb3b 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -40,7 +40,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_cachefile_types.h" #include "DNA_curve_types.h" #include "DNA_modifier_types.h" @@ -74,7 +73,6 @@ extern "C" { #include "WM_api.h" #include "WM_types.h" -} using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::ObjectHeader; diff --git a/source/blender/io/collada/AnimationExporter.h b/source/blender/io/collada/AnimationExporter.h index 3e40a485ddf..b4564eb7b2d 100644 --- a/source/blender/io/collada/AnimationExporter.h +++ b/source/blender/io/collada/AnimationExporter.h @@ -23,7 +23,6 @@ #include "BCAnimationCurve.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -48,7 +47,6 @@ extern "C" { #include "BKE_object.h" #include "BKE_scene.h" #include "ED_object.h" -} #include "MEM_guardedalloc.h" diff --git a/source/blender/io/collada/AnimationImporter.h b/source/blender/io/collada/AnimationImporter.h index 263a130d1eb..51041c6ee3e 100644 --- a/source/blender/io/collada/AnimationImporter.h +++ b/source/blender/io/collada/AnimationImporter.h @@ -35,14 +35,14 @@ #include "COLLADAFWNode.h" #include "COLLADAFWUniqueId.h" -extern "C" { #include "BKE_context.h" + #include "DNA_anim_types.h" + #include "DNA_camera_types.h" #include "DNA_light_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} //#include "ArmatureImporter.h" #include "TransformReader.h" diff --git a/source/blender/io/collada/ArmatureExporter.cpp b/source/blender/io/collada/ArmatureExporter.cpp index 660917c2aa1..fc697e1617b 100644 --- a/source/blender/io/collada/ArmatureExporter.cpp +++ b/source/blender/io/collada/ArmatureExporter.cpp @@ -29,11 +29,8 @@ #include "BKE_action.h" #include "BKE_armature.h" - -extern "C" { #include "BKE_global.h" #include "BKE_mesh.h" -} #include "ED_armature.h" diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index 4e9f31182f1..a69500432e8 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -25,14 +25,12 @@ #include "COLLADAFWUniqueId.h" -extern "C" { #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_object.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "ED_armature.h" -} #include "DEG_depsgraph.h" @@ -335,7 +333,7 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone /* * It is possible that the child's head is located on the parents head. * When this happens, then moving the parent's tail to the child's head - * would result in a zero sized bone and Blender would silently remove the bone. + * would result in a zero sized bone and Blender would silently remove the bone. * So we move the tail only when the resulting bone has a minimum length: */ diff --git a/source/blender/io/collada/ArmatureImporter.h b/source/blender/io/collada/ArmatureImporter.h index bafa10ca804..7393b882f4b 100644 --- a/source/blender/io/collada/ArmatureImporter.h +++ b/source/blender/io/collada/ArmatureImporter.h @@ -25,7 +25,6 @@ #include "COLLADAFWNode.h" #include "COLLADAFWUniqueId.h" -extern "C" { #include "BKE_context.h" #include "BKE_key.h" @@ -35,7 +34,6 @@ extern "C" { #include "DNA_scene_types.h" #include "ED_armature.h" -} #include "AnimationImporter.h" #include "ExtraTags.h" diff --git a/source/blender/io/collada/BCAnimationCurve.h b/source/blender/io/collada/BCAnimationCurve.h index 71640ff3013..e0216ee6849 100644 --- a/source/blender/io/collada/BCAnimationCurve.h +++ b/source/blender/io/collada/BCAnimationCurve.h @@ -25,14 +25,13 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_armature.h" #include "BKE_fcurve.h" #include "BKE_material.h" + #include "ED_anim_api.h" #include "ED_keyframes_edit.h" #include "ED_keyframing.h" -} typedef float(TangentPoint)[2]; diff --git a/source/blender/io/collada/BCAnimationSampler.cpp b/source/blender/io/collada/BCAnimationSampler.cpp index 0c19ce9a4c7..fc23a58ccbc 100644 --- a/source/blender/io/collada/BCAnimationSampler.cpp +++ b/source/blender/io/collada/BCAnimationSampler.cpp @@ -27,20 +27,21 @@ #include "ExportSettings.h" #include "collada_utils.h" -extern "C" { #include "BKE_action.h" #include "BKE_constraint.h" #include "BKE_key.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" + #include "BLI_listbase.h" + #include "DNA_anim_types.h" #include "DNA_constraint_types.h" #include "DNA_key_types.h" #include "DNA_scene_types.h" + #include "ED_object.h" -} static std::string EMPTY_STRING; static BCAnimationCurveMap BCEmptyAnimationCurves; diff --git a/source/blender/io/collada/BCAnimationSampler.h b/source/blender/io/collada/BCAnimationSampler.h index 96138d0cbca..3273ac8e0a0 100644 --- a/source/blender/io/collada/BCAnimationSampler.h +++ b/source/blender/io/collada/BCAnimationSampler.h @@ -21,12 +21,12 @@ #include "BCSampleData.h" #include "collada_utils.h" -extern "C" { #include "BKE_action.h" #include "BKE_lib_id.h" + #include "BLI_math_rotation.h" + #include "DNA_action_types.h" -} /* Collection of animation curves */ class BCAnimation { diff --git a/source/blender/io/collada/BCMath.h b/source/blender/io/collada/BCMath.h index 9ecea85b08c..38158751740 100644 --- a/source/blender/io/collada/BCMath.h +++ b/source/blender/io/collada/BCMath.h @@ -23,10 +23,9 @@ #include "BlenderTypes.h" -extern "C" { #include "BKE_object.h" + #include "BLI_math.h" -} class BCQuat { private: diff --git a/source/blender/io/collada/BCSampleData.h b/source/blender/io/collada/BCSampleData.h index 877fb49981a..6f3ca9135b3 100644 --- a/source/blender/io/collada/BCSampleData.h +++ b/source/blender/io/collada/BCSampleData.h @@ -28,15 +28,15 @@ #include "BCSampleData.h" #include "ExportSettings.h" -extern "C" { #include "BKE_object.h" + #include "BLI_math_rotation.h" + #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_light_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" -} typedef std::map<Bone *, BCMatrix *> BCBoneMatrixMap; diff --git a/source/blender/io/collada/BlenderContext.h b/source/blender/io/collada/BlenderContext.h index 15ebd671b1a..bf6fde134fa 100644 --- a/source/blender/io/collada/BlenderContext.h +++ b/source/blender/io/collada/BlenderContext.h @@ -21,11 +21,6 @@ #ifndef __BLENDERCONTEXT_H__ #define __BLENDERCONTEXT_H__ -#ifdef __cplusplus - -extern "C" { -#endif - #include "BKE_context.h" #include "BKE_main.h" #include "BLI_linklist.h" @@ -35,6 +30,10 @@ extern "C" { #include "DNA_layer_types.h" #include "DNA_object_types.h" +#ifdef __cplusplus +extern "C" { +#endif + static const BC_global_forward_axis BC_DEFAULT_FORWARD = BC_GLOBAL_FORWARD_Y; static const BC_global_up_axis BC_DEFAULT_UP = BC_GLOBAL_UP_Z; diff --git a/source/blender/io/collada/CameraExporter.cpp b/source/blender/io/collada/CameraExporter.cpp index 74862c44270..246a454eb66 100644 --- a/source/blender/io/collada/CameraExporter.cpp +++ b/source/blender/io/collada/CameraExporter.cpp @@ -22,9 +22,8 @@ #include "COLLADASWCamera.h" -extern "C" { #include "DNA_camera_types.h" -} + #include "CameraExporter.h" #include "collada_internal.h" diff --git a/source/blender/io/collada/CameraExporter.h b/source/blender/io/collada/CameraExporter.h index e4df994354c..0dda6392d03 100644 --- a/source/blender/io/collada/CameraExporter.h +++ b/source/blender/io/collada/CameraExporter.h @@ -24,10 +24,8 @@ #include "COLLADASWLibraryCameras.h" #include "COLLADASWStreamWriter.h" -extern "C" { #include "DNA_object_types.h" #include "DNA_scene_types.h" -} #include "DNA_camera_types.h" #include "ExportSettings.h" diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp index c26647d4747..1b8c859f443 100644 --- a/source/blender/io/collada/ControllerExporter.cpp +++ b/source/blender/io/collada/ControllerExporter.cpp @@ -29,13 +29,10 @@ #include "BKE_action.h" #include "BKE_armature.h" - -extern "C" { #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_lib_id.h" #include "BKE_mesh.h" -} #include "ED_armature.h" diff --git a/source/blender/io/collada/DocumentExporter.cpp b/source/blender/io/collada/DocumentExporter.cpp index 7565aa881fd..b890d4cf018 100644 --- a/source/blender/io/collada/DocumentExporter.cpp +++ b/source/blender/io/collada/DocumentExporter.cpp @@ -58,7 +58,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -96,13 +95,12 @@ extern "C" { #include "ED_keyframing.h" #ifdef WITH_BUILDINFO -extern char build_commit_date[]; -extern char build_commit_time[]; -extern char build_hash[]; +extern "C" char build_commit_date[]; +extern "C" char build_commit_time[]; +extern "C" char build_hash[]; #endif #include "RNA_access.h" -} #include "DocumentExporter.h" #include "collada_internal.h" diff --git a/source/blender/io/collada/DocumentExporter.h b/source/blender/io/collada/DocumentExporter.h index f024befbd17..1fe52420534 100644 --- a/source/blender/io/collada/DocumentExporter.h +++ b/source/blender/io/collada/DocumentExporter.h @@ -25,9 +25,7 @@ #include "collada.h" #include "collada_utils.h" -extern "C" { #include "DNA_customdata_types.h" -} class DocumentExporter { public: diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 281786bb45f..2305072a6eb 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -45,7 +45,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -72,7 +71,6 @@ extern "C" { #include "WM_api.h" #include "WM_types.h" -} #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/io/collada/EffectExporter.cpp b/source/blender/io/collada/EffectExporter.cpp index f21ea57c91c..7f6d3cbdc6f 100644 --- a/source/blender/io/collada/EffectExporter.cpp +++ b/source/blender/io/collada/EffectExporter.cpp @@ -31,7 +31,6 @@ #include "collada_internal.h" #include "collada_utils.h" -extern "C" { #include "DNA_mesh_types.h" #include "DNA_world_types.h" @@ -39,7 +38,6 @@ extern "C" { #include "BKE_customdata.h" #include "BKE_material.h" #include "BKE_mesh.h" -} static std::string getActiveUVLayerName(Object *ob) { diff --git a/source/blender/io/collada/ExportSettings.h b/source/blender/io/collada/ExportSettings.h index 69e260a1e91..477f0b8b678 100644 --- a/source/blender/io/collada/ExportSettings.h +++ b/source/blender/io/collada/ExportSettings.h @@ -21,6 +21,9 @@ #ifndef __EXPORTSETTINGS_H__ #define __EXPORTSETTINGS_H__ +#include "BLI_linklist.h" +#include "BlenderContext.h" + #ifdef __cplusplus # include "BCMath.h" # include <vector> @@ -28,9 +31,6 @@ extern "C" { #endif -#include "BLI_linklist.h" -#include "BlenderContext.h" - typedef enum BC_export_mesh_type { BC_MESH_TYPE_VIEW, BC_MESH_TYPE_RENDER, diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index 469d8601a8b..c7fcc51d42f 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -29,7 +29,6 @@ #include "DNA_meshdata_types.h" -extern "C" { #include "BLI_utildefines.h" #include "BKE_customdata.h" @@ -37,7 +36,6 @@ extern "C" { #include "BKE_lib_id.h" #include "BKE_material.h" #include "BKE_mesh.h" -} #include "collada_internal.h" #include "collada_utils.h" diff --git a/source/blender/io/collada/ImageExporter.cpp b/source/blender/io/collada/ImageExporter.cpp index 1cd3301b8a8..1c897e37a4a 100644 --- a/source/blender/io/collada/ImageExporter.cpp +++ b/source/blender/io/collada/ImageExporter.cpp @@ -21,7 +21,6 @@ #include "COLLADABUURI.h" #include "COLLADASWImage.h" -extern "C" { #include "DNA_image_types.h" #include "DNA_meshdata_types.h" #include "DNA_texture_types.h" @@ -37,7 +36,6 @@ extern "C" { #include "BLI_string.h" #include "IMB_imbuf_types.h" -} #include "ImageExporter.h" #include "MaterialExporter.h" diff --git a/source/blender/io/collada/InstanceWriter.cpp b/source/blender/io/collada/InstanceWriter.cpp index a0bea16adfb..6c197823ec2 100644 --- a/source/blender/io/collada/InstanceWriter.cpp +++ b/source/blender/io/collada/InstanceWriter.cpp @@ -23,11 +23,10 @@ #include "COLLADASWInstanceMaterial.h" -extern "C" { #include "BKE_customdata.h" #include "BKE_material.h" + #include "DNA_mesh_types.h" -} #include "InstanceWriter.h" #include "collada_internal.h" diff --git a/source/blender/io/collada/MaterialExporter.h b/source/blender/io/collada/MaterialExporter.h index 8b3d1130fe9..babb113567f 100644 --- a/source/blender/io/collada/MaterialExporter.h +++ b/source/blender/io/collada/MaterialExporter.h @@ -27,12 +27,11 @@ #include "COLLADASWLibraryMaterials.h" #include "COLLADASWStreamWriter.h" -extern "C" { #include "BKE_material.h" + #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} #include "ExportSettings.h" #include "GeometryExporter.h" diff --git a/source/blender/io/collada/Materials.h b/source/blender/io/collada/Materials.h index 86fc4c00073..e1d12246a2b 100644 --- a/source/blender/io/collada/Materials.h +++ b/source/blender/io/collada/Materials.h @@ -20,13 +20,11 @@ #include <map> #include <string> -extern "C" { #include "BKE_context.h" #include "BKE_node.h" #include "BLI_listbase.h" #include "DNA_material_types.h" #include "DNA_node_types.h" -} #include "COLLADAFWEffectCommon.h" #include "collada_utils.h" diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index 6ac87d3d394..6683f07bf65 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -30,7 +30,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_customdata.h" #include "BKE_displist.h" #include "BKE_global.h" @@ -43,7 +42,6 @@ extern "C" { #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" -} #include "ArmatureImporter.h" #include "MeshImporter.h" diff --git a/source/blender/io/collada/MeshImporter.h b/source/blender/io/collada/MeshImporter.h index 5ad2fb17fce..2f2a18ff11a 100644 --- a/source/blender/io/collada/MeshImporter.h +++ b/source/blender/io/collada/MeshImporter.h @@ -38,14 +38,13 @@ #include "ArmatureImporter.h" #include "collada_utils.h" -extern "C" { #include "BLI_edgehash.h" + #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} /* only for ArmatureImporter to "see" MeshImporter::get_object_by_geom_uid */ class MeshImporterBase { diff --git a/source/blender/io/collada/SceneExporter.cpp b/source/blender/io/collada/SceneExporter.cpp index 2f70bc1c26b..1b3bc1b66ea 100644 --- a/source/blender/io/collada/SceneExporter.cpp +++ b/source/blender/io/collada/SceneExporter.cpp @@ -18,13 +18,11 @@ * \ingroup collada */ -extern "C" { #include "BKE_collection.h" #include "BKE_lib_id.h" #include "BKE_object.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" -} #include "BCSampleData.h" #include "SceneExporter.h" diff --git a/source/blender/io/collada/SceneExporter.h b/source/blender/io/collada/SceneExporter.h index 6effb54fd48..3ea6a9fac8e 100644 --- a/source/blender/io/collada/SceneExporter.h +++ b/source/blender/io/collada/SceneExporter.h @@ -25,7 +25,6 @@ #include <stdio.h> #include <stdlib.h> -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -47,7 +46,6 @@ extern "C" { #include "BLI_fileops.h" #include "BLI_path_util.h" #include "ED_keyframing.h" -} #include "COLLADASWAsset.h" #include "COLLADASWBaseInputElement.h" diff --git a/source/blender/io/collada/collada.cpp b/source/blender/io/collada/collada.cpp index 683e64b2647..bf1ebbfa669 100644 --- a/source/blender/io/collada/collada.cpp +++ b/source/blender/io/collada/collada.cpp @@ -27,7 +27,6 @@ #include "ImportSettings.h" #include "collada.h" -extern "C" { #include "BKE_context.h" #include "BKE_scene.h" #include "DEG_depsgraph.h" @@ -37,6 +36,8 @@ extern "C" { #include "BLI_fileops.h" #include "BLI_linklist.h" +extern "C" { + static void print_import_header(ImportSettings &import_settings) { fprintf(stderr, "+-- Collada Import parameters------\n"); diff --git a/source/blender/io/collada/collada.h b/source/blender/io/collada/collada.h index deadbcffcaf..d8e498ef4b2 100644 --- a/source/blender/io/collada/collada.h +++ b/source/blender/io/collada/collada.h @@ -26,14 +26,14 @@ #include "ExportSettings.h" #include "ImportSettings.h" -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_linklist.h" #include "BLI_path_util.h" #include "RNA_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bContext; /* diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index 1df82ed3038..d2e05c7ae5b 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -30,7 +30,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_customdata_types.h" @@ -75,7 +74,6 @@ extern "C" { #if 0 # include "NOD_common.h" #endif -} #include "BlenderContext.h" #include "ExportSettings.h" diff --git a/source/blender/io/collada/collada_utils.h b/source/blender/io/collada/collada_utils.h index 54ba8073679..b1ec2c8b81a 100644 --- a/source/blender/io/collada/collada_utils.h +++ b/source/blender/io/collada/collada_utils.h @@ -33,7 +33,6 @@ #include <set> #include <vector> -extern "C" { #include "DNA_anim_types.h" #include "DNA_camera_types.h" #include "DNA_constraint_types.h" @@ -57,7 +56,6 @@ extern "C" { #include "BKE_node.h" #include "BKE_object.h" #include "BKE_scene.h" -} #include "DEG_depsgraph_query.h" diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc index d837d3d8dd3..e382fa6bb1d 100644 --- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc @@ -24,7 +24,6 @@ #include <stdio.h> #include <string> -extern "C" { #include "BKE_anim_data.h" #include "BKE_duplilist.h" #include "BKE_key.h" @@ -41,7 +40,6 @@ extern "C" { #include "DNA_particle_types.h" #include "DEG_depsgraph_query.h" -} namespace USD { @@ -345,8 +343,11 @@ void AbstractHierarchyIterator::visit_object(Object *object, context->original_export_path = ""; copy_m4_m4(context->matrix_world, object->obmat); + ExportGraph::key_type graph_index = determine_graph_index_object(context); + context_update_for_graph_index(context, graph_index); + // Store this HierarchyContext as child of the export parent. - export_graph_[std::make_pair(export_parent, nullptr)].insert(context); + export_graph_[graph_index].insert(context); // Create an empty entry for this object to indicate it is part of the export. This will be used // by connect_loose_objects(). Having such an "indicator" will make it possible to do an O(log n) @@ -359,38 +360,25 @@ void AbstractHierarchyIterator::visit_object(Object *object, } } +AbstractHierarchyIterator::ExportGraph::key_type AbstractHierarchyIterator:: + determine_graph_index_object(const HierarchyContext *context) +{ + return std::make_pair(context->export_parent, nullptr); +} + void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object, Object *duplicator, const std::set<Object *> &dupli_set) { - ExportGraph::key_type graph_index; - bool animation_check_include_parent = false; - HierarchyContext *context = new HierarchyContext(); context->object = dupli_object->ob; context->duplicator = duplicator; context->weak_export = false; context->export_path = ""; context->original_export_path = ""; + context->export_path = ""; + context->animation_check_include_parent = false; - /* If the dupli-object's parent is also instanced by this object, use that as the - * export parent. Otherwise use the dupli-parent as export parent. */ - Object *parent = dupli_object->ob->parent; - if (parent != nullptr && dupli_set.find(parent) != dupli_set.end()) { - // The parent object is part of the duplicated collection. - context->export_parent = parent; - graph_index = std::make_pair(parent, duplicator); - } - else { - /* The parent object is NOT part of the duplicated collection. This means that the world - * transform of this dupli-object can be influenced by objects that are not part of its - * export graph. */ - animation_check_include_parent = true; - context->export_parent = duplicator; - graph_index = std::make_pair(duplicator, nullptr); - } - - context->animation_check_include_parent = animation_check_include_parent; copy_m4_m4(context->matrix_world, dupli_object->mat); // Construct export name for the dupli-instance. @@ -401,9 +389,39 @@ void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object, } context->export_name = make_valid_name(get_object_name(context->object) + suffix_stream.str()); + ExportGraph::key_type graph_index = determine_graph_index_dupli(context, dupli_set); + context_update_for_graph_index(context, graph_index); export_graph_[graph_index].insert(context); } +AbstractHierarchyIterator::ExportGraph::key_type AbstractHierarchyIterator:: + determine_graph_index_dupli(const HierarchyContext *context, + const std::set<Object *> &dupli_set) +{ + /* If the dupli-object's parent is also instanced by this object, use that as the + * export parent. Otherwise use the dupli-parent as export parent. */ + + Object *parent = context->object->parent; + if (parent != nullptr && dupli_set.find(parent) != dupli_set.end()) { + // The parent object is part of the duplicated collection. + return std::make_pair(parent, context->duplicator); + } + return std::make_pair(context->duplicator, nullptr); +} + +void AbstractHierarchyIterator::context_update_for_graph_index( + HierarchyContext *context, const ExportGraph::key_type &graph_index) const +{ + // Update the HierarchyContext so that it is consistent with the graph index. + context->export_parent = graph_index.first; + if (context->export_parent != context->object->parent) { + /* The parent object in Blender is NOT used as the export parent. This means + * that the world transform of this object can be influenced by objects that + * are not part of its export graph. */ + context->animation_check_include_parent = true; + } +} + AbstractHierarchyIterator::ExportChildren &AbstractHierarchyIterator::graph_children( const HierarchyContext *context) { @@ -428,8 +446,7 @@ void AbstractHierarchyIterator::determine_export_paths(const HierarchyContext *p duplisource_export_path_[source_ob] = context->export_path; if (context->object->data != nullptr) { - ID *object_data = static_cast<ID *>(context->object->data); - ID *source_data = object_data; + ID *source_data = static_cast<ID *>(context->object->data); duplisource_export_path_[source_data] = get_object_data_path(context); } } @@ -488,6 +505,7 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_cont } for (HierarchyContext *context : graph_children(parent_context)) { + // Update the context so that it is correct for this parent-child relation. copy_m4_m4(context->parent_matrix_inv_world, parent_matrix_inv_world); // Get or create the transform writer. @@ -556,7 +574,7 @@ void AbstractHierarchyIterator::make_writers_particle_systems( HierarchyContext hair_context = *transform_context; hair_context.export_path = path_concatenate(transform_context->export_path, - get_id_name(&psys->part->id)); + make_valid_name(psys->name)); hair_context.particle_system = psys; AbstractHierarchyWriter *writer = nullptr; @@ -586,9 +604,10 @@ std::string AbstractHierarchyIterator::get_object_data_name(const Object *object return get_id_name(object_data); } -AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer(const std::string &export_path) +AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer( + const std::string &export_path) const { - WriterMap::iterator it = writers_.find(export_path); + WriterMap::const_iterator it = writers_.find(export_path); if (it == writers_.end()) { return nullptr; diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h index 08b50e2560d..e31d5c91252 100644 --- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h +++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h @@ -56,7 +56,7 @@ class AbstractHierarchyWriter; * struct contains everything necessary to export a single object to a file. */ struct HierarchyContext { /*********** Determined during hierarchy iteration: ***************/ - Object *object; + Object *object; /* Evaluated object. */ Object *export_parent; Object *duplicator; float matrix_world[4][4]; @@ -188,11 +188,14 @@ class AbstractHierarchyIterator { const std::set<Object *> &dupli_set); ExportChildren &graph_children(const HierarchyContext *parent_context); + void context_update_for_graph_index(HierarchyContext *context, + const ExportGraph::key_type &graph_index) const; void determine_export_paths(const HierarchyContext *parent_context); void determine_duplication_references(const HierarchyContext *parent_context, std::string indent); + /* These three functions create writers and call their write() method. */ void make_writers(const HierarchyContext *parent_context); void make_writer_object_data(const HierarchyContext *context); void make_writers_particle_systems(const HierarchyContext *context); @@ -201,7 +204,7 @@ class AbstractHierarchyIterator { std::string get_object_name(const Object *object) const; std::string get_object_data_name(const Object *object) const; - AbstractHierarchyWriter *get_writer(const std::string &export_path); + AbstractHierarchyWriter *get_writer(const std::string &export_path) const; typedef AbstractHierarchyWriter *(AbstractHierarchyIterator::*create_writer_func)( const HierarchyContext *); @@ -233,12 +236,19 @@ class AbstractHierarchyIterator { virtual bool should_visit_dupli_object(const DupliObject *dupli_object) const; + virtual ExportGraph::key_type determine_graph_index_object(const HierarchyContext *context); + virtual ExportGraph::key_type determine_graph_index_dupli(const HierarchyContext *context, + const std::set<Object *> &dupli_set); + /* These functions should create an AbstractHierarchyWriter subclass instance, or return * nullptr if the object or its data should not be exported. Returning a nullptr for * data/hair/particle will NOT prevent the transform to be written. * * The returned writer is owned by the AbstractHierarchyWriter, and should be freed in - * delete_object_writer(). */ + * delete_object_writer(). + * + * The created AbstractHierarchyWriter instances should NOT keep a copy of the context pointer. + * The context can be stack-allocated and go out of scope. */ virtual AbstractHierarchyWriter *create_transform_writer(const HierarchyContext *context) = 0; virtual AbstractHierarchyWriter *create_data_writer(const HierarchyContext *context) = 0; virtual AbstractHierarchyWriter *create_hair_writer(const HierarchyContext *context) = 0; diff --git a/source/blender/io/usd/intern/usd_capi.cc b/source/blender/io/usd/intern/usd_capi.cc index 60ab3676847..f8e0a03abfa 100644 --- a/source/blender/io/usd/intern/usd_capi.cc +++ b/source/blender/io/usd/intern/usd_capi.cc @@ -26,7 +26,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_query.h" @@ -44,7 +43,6 @@ extern "C" { #include "WM_api.h" #include "WM_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc index 47f09af7442..56e367dd877 100644 --- a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc @@ -31,7 +31,6 @@ #include <pxr/base/tf/stringUtils.h> -extern "C" { #include "BKE_duplilist.h" #include "BLI_assert.h" @@ -41,7 +40,6 @@ extern "C" { #include "DNA_ID.h" #include "DNA_layer_types.h" #include "DNA_object_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_abstract.h b/source/blender/io/usd/intern/usd_writer_abstract.h index cf0f7e9d437..01b53f4c916 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.h +++ b/source/blender/io/usd/intern/usd_writer_abstract.h @@ -29,10 +29,9 @@ #include <vector> -extern "C" { #include "DEG_depsgraph_query.h" + #include "DNA_material_types.h" -} struct Material; struct Object; diff --git a/source/blender/io/usd/intern/usd_writer_camera.cc b/source/blender/io/usd/intern/usd_writer_camera.cc index 9b85d69559c..ea551a43c9f 100644 --- a/source/blender/io/usd/intern/usd_writer_camera.cc +++ b/source/blender/io/usd/intern/usd_writer_camera.cc @@ -22,13 +22,11 @@ #include <pxr/usd/usdGeom/camera.h> #include <pxr/usd/usdGeom/tokens.h> -extern "C" { #include "BKE_camera.h" #include "BLI_assert.h" #include "DNA_camera_types.h" #include "DNA_scene_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_hair.cc b/source/blender/io/usd/intern/usd_writer_hair.cc index 9251425c0b8..d38c1032969 100644 --- a/source/blender/io/usd/intern/usd_writer_hair.cc +++ b/source/blender/io/usd/intern/usd_writer_hair.cc @@ -22,11 +22,9 @@ #include <pxr/usd/usdGeom/basisCurves.h> #include <pxr/usd/usdGeom/tokens.h> -extern "C" { #include "BKE_particle.h" #include "DNA_particle_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_light.cc b/source/blender/io/usd/intern/usd_writer_light.cc index e13e2c58a79..0ce3ee5f8ce 100644 --- a/source/blender/io/usd/intern/usd_writer_light.cc +++ b/source/blender/io/usd/intern/usd_writer_light.cc @@ -24,13 +24,11 @@ #include <pxr/usd/usdLux/rectLight.h> #include <pxr/usd/usdLux/sphereLight.h> -extern "C" { #include "BLI_assert.h" #include "BLI_utildefines.h" #include "DNA_light_types.h" #include "DNA_object_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 2e6696e12ca..909869d2af1 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -23,7 +23,6 @@ #include <pxr/usd/usdShade/material.h> #include <pxr/usd/usdShade/materialBindingAPI.h> -extern "C" { #include "BLI_assert.h" #include "BLI_math_vector.h" @@ -42,7 +41,6 @@ extern "C" { #include "DNA_modifier_types.h" #include "DNA_object_fluidsim_types.h" #include "DNA_particle_types.h" -} namespace USD { @@ -441,7 +439,7 @@ void USDGenericMeshWriter::write_surface_velocity(Object *object, /* Only velocities from the fluid simulation are exported. This is the most important case, * though, as the baked mesh changes topology all the time, and thus computing the velocities * at import time in a post-processing step is hard. */ - ModifierData *md = modifiers_findByType(object, eModifierType_Fluidsim); + ModifierData *md = BKE_modifiers_findby_type(object, eModifierType_Fluidsim); if (md == nullptr) { return; } @@ -450,7 +448,7 @@ void USDGenericMeshWriter::write_surface_velocity(Object *object, const bool use_render = (DEG_get_mode(usd_export_context_.depsgraph) == DAG_EVAL_RENDER); const ModifierMode required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; const Scene *scene = DEG_get_evaluated_scene(usd_export_context_.depsgraph); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { return; } FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md); diff --git a/source/blender/io/usd/intern/usd_writer_metaball.cc b/source/blender/io/usd/intern/usd_writer_metaball.cc index 25b216d20f3..96bf854d327 100644 --- a/source/blender/io/usd/intern/usd_writer_metaball.cc +++ b/source/blender/io/usd/intern/usd_writer_metaball.cc @@ -23,7 +23,6 @@ #include <pxr/usd/usdShade/material.h> #include <pxr/usd/usdShade/materialBindingAPI.h> -extern "C" { #include "BLI_assert.h" #include "BKE_displist.h" @@ -34,7 +33,6 @@ extern "C" { #include "DNA_mesh_types.h" #include "DNA_meta_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_transform.cc b/source/blender/io/usd/intern/usd_writer_transform.cc index 321b516221a..038f2b17b1a 100644 --- a/source/blender/io/usd/intern/usd_writer_transform.cc +++ b/source/blender/io/usd/intern/usd_writer_transform.cc @@ -22,13 +22,11 @@ #include <pxr/base/gf/matrix4f.h> #include <pxr/usd/usdGeom/xform.h> -extern "C" { #include "BKE_object.h" #include "BLI_math_matrix.h" #include "DNA_layer_types.h" -} namespace USD { diff --git a/source/blender/io/usd/usd.h b/source/blender/io/usd/usd.h index 8a5575d53cf..eee98521289 100644 --- a/source/blender/io/usd/usd.h +++ b/source/blender/io/usd/usd.h @@ -20,12 +20,12 @@ #ifndef __USD_H__ #define __USD_H__ +#include "DEG_depsgraph.h" + #ifdef __cplusplus extern "C" { #endif -#include "DEG_depsgraph.h" - struct Scene; struct bContext; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 5230cb050f4..39f22fb9555 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -25,14 +25,13 @@ #ifndef __DNA_ID_H__ #define __DNA_ID_H__ +#include "DNA_defs.h" #include "DNA_listBase.h" #ifdef __cplusplus extern "C" { #endif -#include "DNA_defs.h" - struct FileData; struct GHash; struct GPUTexture; @@ -436,6 +435,7 @@ typedef enum ID_Type { ID_HA = MAKE_ID2('H', 'A'), /* Hair */ ID_PT = MAKE_ID2('P', 'T'), /* PointCloud */ ID_VO = MAKE_ID2('V', 'O'), /* Volume */ + ID_SIM = MAKE_ID2('S', 'I'), /* Simulation */ } ID_Type; /* Only used as 'placeholder' in .blend files for directly linked data-blocks. */ @@ -564,9 +564,9 @@ enum { /* RESET_NEVER tag data-block as needing an auto-override execution, if enabled. */ LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH = 1 << 17, - /* tag data-block has having an extra user. */ + /* tag data-block as having an extra user. */ LIB_TAG_EXTRAUSER = 1 << 2, - /* tag data-block has having actually increased usercount for the extra virtual user. */ + /* tag data-block as having actually increased usercount for the extra virtual user. */ LIB_TAG_EXTRAUSER_SET = 1 << 7, /* RESET_AFTER_USE tag newly duplicated/copied IDs. @@ -735,6 +735,7 @@ typedef enum IDRecalcFlag { #define FILTER_ID_HA (1ULL << 32) #define FILTER_ID_PT (1ULL << 33) #define FILTER_ID_VO (1ULL << 34) +#define FILTER_ID_SIM (1ULL << 35) #define FILTER_ID_ALL \ (FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD | \ @@ -742,7 +743,7 @@ typedef enum IDRecalcFlag { FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | \ FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | \ FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \ - FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO) + FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM) /* IMPORTANT: this enum matches the order currently use in set_listbasepointers, * keep them in sync! */ @@ -786,6 +787,7 @@ enum { INDEX_ID_WS, INDEX_ID_WM, INDEX_ID_MSK, + INDEX_ID_SIM, INDEX_ID_NULL, INDEX_ID_MAX, }; diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 40c25d39cad..c95a701a78a 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -28,16 +28,16 @@ #ifndef __DNA_ACTION_TYPES_H__ #define __DNA_ACTION_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_listBase.h" #include "DNA_userdef_types.h" /* ThemeWireColor */ #include "DNA_vec_types.h" #include "DNA_view2d_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct Collection; struct GHash; struct Object; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index fbffa039ee9..6a024ec9e7e 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -24,15 +24,15 @@ #ifndef __DNA_ANIM_TYPES_H__ #define __DNA_ANIM_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_action_types.h" #include "DNA_curve_types.h" #include "DNA_listBase.h" +#ifdef __cplusplus +extern "C" { +#endif + /* ************************************************ */ /* F-Curve DataTypes */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index b29816c735b..635c155dec6 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -261,23 +261,23 @@ typedef enum eBone_InheritScaleMode { /* Inherit all scale and shear. */ BONE_INHERIT_SCALE_FULL = 0, /* Inherit scale, but remove final shear. */ - BONE_INHERIT_SCALE_FIX_SHEAR, + BONE_INHERIT_SCALE_FIX_SHEAR = 1, /* Inherit average scale. */ - BONE_INHERIT_SCALE_AVERAGE, + BONE_INHERIT_SCALE_AVERAGE = 2, /* Inherit no scale or shear. */ - BONE_INHERIT_SCALE_NONE, + BONE_INHERIT_SCALE_NONE = 3, /* Inherit effects of shear on parent (same as old disabled Inherit Scale). */ - BONE_INHERIT_SCALE_NONE_LEGACY, + BONE_INHERIT_SCALE_NONE_LEGACY = 4, /* Inherit parent X scale as child X scale etc. */ - BONE_INHERIT_SCALE_ALIGNED, + BONE_INHERIT_SCALE_ALIGNED = 5, } eBone_InheritScaleMode; /* bone->bbone_prev_type, bbone_next_type */ typedef enum eBone_BBoneHandleType { - BBONE_HANDLE_AUTO = 0, /* Default mode based on parents & children. */ - BBONE_HANDLE_ABSOLUTE, /* Custom handle in absolute position mode. */ - BBONE_HANDLE_RELATIVE, /* Custom handle in relative position mode. */ - BBONE_HANDLE_TANGENT, /* Custom handle in tangent mode (use direction, not location). */ + BBONE_HANDLE_AUTO = 0, /* Default mode based on parents & children. */ + BBONE_HANDLE_ABSOLUTE = 1, /* Custom handle in absolute position mode. */ + BBONE_HANDLE_RELATIVE = 2, /* Custom handle in relative position mode. */ + BBONE_HANDLE_TANGENT = 3, /* Custom handle in tangent mode (use direction, not location). */ } eBone_BBoneHandleType; #define MAXBONENAME 64 diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 041943bc5e4..c143c2a442a 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -75,7 +75,7 @@ typedef struct BrushGpencilSettings { short fill_leak; /** Fill zoom factor */ short fill_factor; - char _pad1[4]; + int flag2; /** Number of simplify steps. */ int fill_simplylvl; @@ -118,11 +118,24 @@ typedef struct BrushGpencilSettings { int sculpt_mode_flag; /** Preset type (used to reset brushes - internal). */ short preset_type; - char _pad3[6]; + char _pad3[2]; + + /** Randomness for Hue. */ + float random_hue; + /** Randomness for Saturation. */ + float random_saturation; + /** Randomness for Value. */ + float random_value; struct CurveMapping *curve_sensitivity; struct CurveMapping *curve_strength; struct CurveMapping *curve_jitter; + struct CurveMapping *curve_rand_pressure; + struct CurveMapping *curve_rand_strength; + struct CurveMapping *curve_rand_uv; + struct CurveMapping *curve_rand_hue; + struct CurveMapping *curve_rand_saturation; + struct CurveMapping *curve_rand_value; /* optional link of material to replace default in context */ /** Material. */ @@ -204,6 +217,33 @@ typedef enum eGPDbrush_Flag { GP_BRUSH_TRIM_STROKE = (1 << 16), } eGPDbrush_Flag; +typedef enum eGPDbrush_Flag2 { + /* Brush use random Hue at stroke level */ + GP_BRUSH_USE_HUE_AT_STROKE = (1 << 0), + /* Brush use random Saturation at stroke level */ + GP_BRUSH_USE_SAT_AT_STROKE = (1 << 1), + /* Brush use random Value at stroke level */ + GP_BRUSH_USE_VAL_AT_STROKE = (1 << 2), + /* Brush use random Pressure at stroke level */ + GP_BRUSH_USE_PRESS_AT_STROKE = (1 << 3), + /* Brush use random Strength at stroke level */ + GP_BRUSH_USE_STRENGTH_AT_STROKE = (1 << 4), + /* Brush use random UV at stroke level */ + GP_BRUSH_USE_UV_AT_STROKE = (1 << 5), + /* Brush use Hue random pressure */ + GP_BRUSH_USE_HUE_RAND_PRESS = (1 << 6), + /* Brush use Saturation random pressure */ + GP_BRUSH_USE_SAT_RAND_PRESS = (1 << 7), + /* Brush use Value random pressure */ + GP_BRUSH_USE_VAL_RAND_PRESS = (1 << 8), + /* Brush use Pressure random pressure */ + GP_BRUSH_USE_PRESSURE_RAND_PRESS = (1 << 9), + /* Brush use Strength random pressure */ + GP_BRUSH_USE_STRENGTH_RAND_PRESS = (1 << 10), + /* Brush use UV random pressure */ + GP_BRUSH_USE_UV_RAND_PRESS = (1 << 11), +} eGPDbrush_Flag2; + /* BrushGpencilSettings->gp_fill_draw_mode */ typedef enum eGP_FillDrawModes { GP_FILL_DMODE_BOTH = 0, @@ -805,8 +845,8 @@ typedef enum { /* blur kernel types, Brush.blur_mode */ typedef enum eBlurKernelType { - KERNEL_GAUSSIAN, - KERNEL_BOX, + KERNEL_GAUSSIAN = 0, + KERNEL_BOX = 1, } eBlurKernelType; /* Brush.falloff_shape */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 9efd2116601..65087a6d459 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -735,11 +735,11 @@ typedef enum eConstraint_EulerOrder { /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */ CONSTRAINT_EULER_XYZ = 1, - CONSTRAINT_EULER_XZY, - CONSTRAINT_EULER_YXZ, - CONSTRAINT_EULER_YZX, - CONSTRAINT_EULER_ZXY, - CONSTRAINT_EULER_ZYX, + CONSTRAINT_EULER_XZY = 2, + CONSTRAINT_EULER_YXZ = 3, + CONSTRAINT_EULER_YZX = 4, + CONSTRAINT_EULER_ZXY = 5, + CONSTRAINT_EULER_ZYX = 6, } eConstraint_EulerOrder; /* -------------------------------------- */ @@ -762,13 +762,13 @@ typedef enum eCopyRotation_MixMode { /* Replace rotation channel values. */ ROTLIKE_MIX_REPLACE = 0, /* Legacy Offset mode - don't use. */ - ROTLIKE_MIX_OFFSET, + ROTLIKE_MIX_OFFSET = 1, /* Add Euler components together. */ - ROTLIKE_MIX_ADD, + ROTLIKE_MIX_ADD = 2, /* Multiply the copied rotation on the left. */ - ROTLIKE_MIX_BEFORE, + ROTLIKE_MIX_BEFORE = 3, /* Multiply the copied rotation on the right. */ - ROTLIKE_MIX_AFTER, + ROTLIKE_MIX_AFTER = 4, } eCopyRotation_MixMode; /* bLocateLikeConstraint.flag */ @@ -799,9 +799,9 @@ typedef enum eCopyTransforms_MixMode { /* Replace rotation channel values. */ TRANSLIKE_MIX_REPLACE = 0, /* Multiply the copied transformation on the left, with anti-shear scale handling. */ - TRANSLIKE_MIX_BEFORE, + TRANSLIKE_MIX_BEFORE = 1, /* Multiply the copied transformation on the right, with anti-shear scale handling. */ - TRANSLIKE_MIX_AFTER, + TRANSLIKE_MIX_AFTER = 2, } eCopyTransforms_MixMode; /* bTransformConstraint.to/from */ @@ -816,7 +816,7 @@ typedef enum eTransform_MixModeLoc { /* Add component values together (default). */ TRANS_MIXLOC_ADD = 0, /* Replace component values. */ - TRANS_MIXLOC_REPLACE, + TRANS_MIXLOC_REPLACE = 1, } eTransform_MixModeLoc; /* bTransformConstraint.mix_mode_rot */ @@ -824,11 +824,11 @@ typedef enum eTransform_MixModeRot { /* Add component values together (default). */ TRANS_MIXROT_ADD = 0, /* Replace component values. */ - TRANS_MIXROT_REPLACE, + TRANS_MIXROT_REPLACE = 1, /* Multiply the generated rotation on the left. */ - TRANS_MIXROT_BEFORE, + TRANS_MIXROT_BEFORE = 2, /* Multiply the generated rotation on the right. */ - TRANS_MIXROT_AFTER, + TRANS_MIXROT_AFTER = 3, } eTransform_MixModeRot; /* bTransformConstraint.mix_mode_scale */ @@ -836,7 +836,7 @@ typedef enum eTransform_MixModeScale { /* Replace component values (default). */ TRANS_MIXSCALE_REPLACE = 0, /* Multiply component values together. */ - TRANS_MIXSCALE_MULTIPLY, + TRANS_MIXSCALE_MULTIPLY = 1, } eTransform_MixModeScale; /* bSameVolumeConstraint.free_axis */ @@ -867,9 +867,9 @@ typedef enum eActionConstraint_MixMode { /* Multiply the action transformation on the right. */ ACTCON_MIX_AFTER_FULL = 0, /* Multiply the action transformation on the right, with anti-shear scale handling. */ - ACTCON_MIX_AFTER, + ACTCON_MIX_AFTER = 1, /* Multiply the action transformation on the left, with anti-shear scale handling. */ - ACTCON_MIX_BEFORE, + ACTCON_MIX_BEFORE = 2, } eActionConstraint_MixMode; /* Locked-Axis Values (Locked Track) */ diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 5ee16c2631d..e99d7fd5609 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -26,12 +26,12 @@ #ifndef __DNA_CUSTOMDATA_TYPES_H__ #define __DNA_CUSTOMDATA_TYPES_H__ +#include "DNA_defs.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_defs.h" - /** Descriptor and storage for a custom data layer. */ typedef struct CustomDataLayer { /** Type of data in layer. */ diff --git a/source/blender/makesdna/DNA_defaults.h b/source/blender/makesdna/DNA_defaults.h index 9b4a05034df..ca5ac649e33 100644 --- a/source/blender/makesdna/DNA_defaults.h +++ b/source/blender/makesdna/DNA_defaults.h @@ -29,12 +29,12 @@ #include "BLI_utildefines.h" +#include "dna_type_offsets.h" + #ifdef __cplusplus extern "C" { #endif -#include "dna_type_offsets.h" - extern const void *DNA_default_table[SDNA_TYPE_MAX]; char *_DNA_struct_default_alloc_impl(const char *data_src, size_t size, const char *alloc_str); diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h index d949b34cb57..c97e68a6a6b 100644 --- a/source/blender/makesdna/DNA_dynamicpaint_types.h +++ b/source/blender/makesdna/DNA_dynamicpaint_types.h @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index c3425826d36..125423cd061 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -47,6 +47,8 @@ typedef enum GpencilModifierType { eGpencilModifierType_Armature = 15, eGpencilModifierType_Time = 16, eGpencilModifierType_Multiply = 17, + eGpencilModifierType_Texture = 18, + /* Keep last. */ NUM_GREASEPENCIL_MODIFIER_TYPES, } GpencilModifierType; @@ -77,10 +79,12 @@ typedef struct GpencilModifierData { typedef struct NoiseGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -120,10 +124,12 @@ typedef enum eNoiseGpencil_Flag { typedef struct SubdivGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -151,10 +157,12 @@ typedef enum eSubdivGpencil_Type { typedef struct ThickGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -225,10 +233,12 @@ typedef enum eOpacityModesGpencil_Flag { typedef struct ColorGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -255,10 +265,12 @@ typedef enum eColorGpencil_Flag { typedef struct OpacityGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -290,6 +302,8 @@ typedef enum eOpacityGpencil_Flag { typedef struct ArrayGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Number of elements in array. */ int count; /** Several flags. */ @@ -313,7 +327,7 @@ typedef struct ArrayGpencilModifierData { /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Material replace (0 keep default). */ int mat_rpl; /** Custom index for passes. */ @@ -332,13 +346,15 @@ typedef enum eArrayGpencil_Flag { typedef struct BuildGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** If set, restrict modifier to operating on this layer. */ char layername[64]; int pass_index; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int layer_pass; @@ -368,6 +384,9 @@ typedef struct BuildGpencilModifierData { * For the "Concurrent" mode, when should "shorter" strips start/end. */ short time_alignment; + /** Factor of the stroke (used instead of frame evaluation. */ + float percentage_fac; + char _pad[4]; } BuildGpencilModifierData; typedef enum eBuildGpencil_Mode { @@ -403,15 +422,20 @@ typedef enum eBuildGpencil_Flag { /* Restrict modifier to only operating between the nominated frames */ GP_BUILD_RESTRICT_TIME = (1 << 2), GP_BUILD_INVERT_LAYERPASS = (1 << 3), + + /* Use a percentage instead of frame number to evaluate strokes. */ + GP_BUILD_PERCENTAGE = (1 << 4), } eBuildGpencil_Flag; typedef struct LatticeGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -436,10 +460,12 @@ typedef enum eLatticeGpencil_Flag { typedef struct MirrorGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -464,12 +490,14 @@ typedef struct HookGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Optional name of bone target, MAX_ID_NAME-2. */ char subtarget[64]; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -515,10 +543,12 @@ typedef enum eHookGpencil_Falloff { typedef struct SimplifyGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -558,10 +588,12 @@ typedef enum eSimplifyGpencil_Mode { typedef struct OffsetGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -585,10 +617,12 @@ typedef enum eOffsetGpencil_Flag { typedef struct SmoothGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -634,10 +668,12 @@ typedef struct ArmatureGpencilModifierData { typedef struct MultiplyGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -672,10 +708,12 @@ typedef struct TintGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -713,4 +751,52 @@ typedef enum eTintGpencil_Flag { GP_TINT_CUSTOM_CURVE = (1 << 6), } eTintGpencil_Flag; +typedef struct TextureGpencilModifierData { + GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; + /** Layer name. */ + char layername[64]; + /** Material name. */ + char materialname[64] DNA_DEPRECATED; + /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + char vgname[64]; + /** Custom index for passes. */ + int pass_index; + /** Flags. */ + int flag; + /** Offset value to add to uv_fac. */ + float uv_offset; + float uv_scale; + float fill_rotation; + float fill_offset[2]; + float fill_scale; + /** Custom index for passes. */ + int layer_pass; + /** Texture fit options. */ + short fit_method; + short mode; +} TextureGpencilModifierData; + +typedef enum eTextureGpencil_Flag { + GP_TEX_INVERT_LAYER = (1 << 0), + GP_TEX_INVERT_PASS = (1 << 1), + GP_TEX_INVERT_VGROUP = (1 << 2), + GP_TEX_INVERT_LAYERPASS = (1 << 3), + GP_TEX_INVERT_MATERIAL = (1 << 4), +} eTextureGpencil_Flag; + +/* Texture->fit_method */ +typedef enum eTextureGpencil_Fit { + GP_TEX_FIT_STROKE = 0, + GP_TEX_CONSTANT_LENGTH = 1, +} eTextureGpencil_Fit; + +/* Texture->mode */ +typedef enum eTextureGpencil_Mode { + STROKE = 0, + FILL = 1, + STROKE_AND_FILL = 2, +} eTextureGpencil_Mode; + #endif /* __DNA_GPENCIL_MODIFIER_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index d3d7ca1cc3b..c3180ae79db 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -264,6 +264,10 @@ typedef enum eGPDstroke_Flag { /* Flag used to indicate that stroke is used for fill close and must use * fill color for stroke and no fill area */ GP_STROKE_NOFILL = (1 << 8), + /* only for use with stroke-buffer (while drawing arrows) */ + GP_STROKE_USE_ARROW_START = (1 << 12), + /* only for use with stroke-buffer (while drawing arrows) */ + GP_STROKE_USE_ARROW_END = (1 << 13), /* Tag for update geometry */ GP_STROKE_TAG = (1 << 14), /* only for use with stroke-buffer (while drawing eraser) */ @@ -276,9 +280,21 @@ typedef enum eGPDstroke_Caps { GP_STROKE_CAP_ROUND = 0, GP_STROKE_CAP_FLAT = 1, + /* Keeo last. */ GP_STROKE_CAP_MAX, } GPDstroke_Caps; +/* Arrows ----------------------- */ + +/* bGPDataRuntime.arrowstyle */ +typedef enum eGPDstroke_Arrowstyle { + GP_STROKE_ARROWSTYLE_NONE = 0, + GP_STROKE_ARROWSTYLE_SEGMENT = 2, + GP_STROKE_ARROWSTYLE_OPEN = 3, + GP_STROKE_ARROWSTYLE_CLOSED = 4, + GP_STROKE_ARROWSTYLE_SQUARE = 6, +} eGPDstroke_Arrowstyle; + /* ***************************************** */ /* GP Frame */ @@ -504,12 +520,16 @@ typedef struct bGPdata_Runtime { /** Number of total elements available in cache. */ int sbuffer_size; - /** Vertex Color applied to point (while drawing). */ - float vert_color[4]; - /** Vertex Color applied to Fill (while drawing). */ float vert_color_fill[4]; + /** Arrow points for stroke corners **/ + float arrow_start[8]; + float arrow_end[8]; + /* Arrow style for each corner */ + int arrow_start_style; + int arrow_end_style; + /** Number of control-points for stroke. */ int tot_cp_points; char _pad2[4]; diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 4676e7fa313..6348dc5f03d 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -21,13 +21,13 @@ #ifndef __DNA_LAYER_TYPES_H__ #define __DNA_LAYER_TYPES_H__ +#include "DNA_freestyle_types.h" +#include "DNA_listBase.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_freestyle_types.h" -#include "DNA_listBase.h" - /** * Render-passes for EEVEE. * #ViewLayerEEVEE.render_passes @@ -115,6 +115,7 @@ typedef struct ViewLayer { ListBase object_bases; /** Default allocated now. */ struct SceneStats *stats; + char footer_str[128]; struct Base *basact; /** A view layer has one top level layer collection, because a scene has only one top level diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h index 66d6e3f4868..5ddfedfed2d 100644 --- a/source/blender/makesdna/DNA_lightprobe_types.h +++ b/source/blender/makesdna/DNA_lightprobe_types.h @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 10a549edc17..357c3260121 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -324,35 +324,35 @@ enum { /* blend_shadow */ enum { MA_BS_NONE = 0, - MA_BS_SOLID, - MA_BS_CLIP, - MA_BS_HASHED, + MA_BS_SOLID = 1, + MA_BS_CLIP = 2, + MA_BS_HASHED = 3, }; /* Grease Pencil Stroke styles */ enum { GP_MATERIAL_STROKE_STYLE_SOLID = 0, - GP_MATERIAL_STROKE_STYLE_TEXTURE, + GP_MATERIAL_STROKE_STYLE_TEXTURE = 1, }; /* Grease Pencil Fill styles */ enum { GP_MATERIAL_FILL_STYLE_SOLID = 0, - GP_MATERIAL_FILL_STYLE_GRADIENT, - GP_MATERIAL_FILL_STYLE_CHECKER, /* DEPRECATED (only for convert old files) */ - GP_MATERIAL_FILL_STYLE_TEXTURE, + GP_MATERIAL_FILL_STYLE_GRADIENT = 1, + GP_MATERIAL_FILL_STYLE_CHECKER = 2, /* DEPRECATED (only for convert old files) */ + GP_MATERIAL_FILL_STYLE_TEXTURE = 3, }; /* Grease Pencil Gradient Types */ enum { GP_MATERIAL_GRADIENT_LINEAR = 0, - GP_MATERIAL_GRADIENT_RADIAL, + GP_MATERIAL_GRADIENT_RADIAL = 1, }; /* Grease Pencil Follow Drawing Modes */ enum { GP_MATERIAL_FOLLOW_PATH = 0, - GP_MATERIAL_FOLLOW_OBJ, - GP_MATERIAL_FOLLOW_FIXED, + GP_MATERIAL_FOLLOW_OBJ = 1, + GP_MATERIAL_FOLLOW_FIXED = 2, }; #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 24e5aa496b9..9c72bd02c2b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -453,23 +453,23 @@ enum { /* BevelModifierData->face_str_mode */ enum { - MOD_BEVEL_FACE_STRENGTH_NONE, - MOD_BEVEL_FACE_STRENGTH_NEW, - MOD_BEVEL_FACE_STRENGTH_AFFECTED, - MOD_BEVEL_FACE_STRENGTH_ALL, + MOD_BEVEL_FACE_STRENGTH_NONE = 0, + MOD_BEVEL_FACE_STRENGTH_NEW = 1, + MOD_BEVEL_FACE_STRENGTH_AFFECTED = 2, + MOD_BEVEL_FACE_STRENGTH_ALL = 3, }; /* BevelModifier->miter_inner and ->miter_outer */ enum { - MOD_BEVEL_MITER_SHARP, - MOD_BEVEL_MITER_PATCH, - MOD_BEVEL_MITER_ARC, + MOD_BEVEL_MITER_SHARP = 0, + MOD_BEVEL_MITER_PATCH = 1, + MOD_BEVEL_MITER_ARC = 2, }; /* BevelModifier->vmesh_method */ enum { - MOD_BEVEL_VMESH_ADJ, - MOD_BEVEL_VMESH_CUTOFF, + MOD_BEVEL_VMESH_ADJ = 0, + MOD_BEVEL_VMESH_CUTOFF = 1, }; typedef struct FluidModifierData { @@ -595,10 +595,10 @@ enum { }; enum { - MOD_DECIM_MODE_COLLAPSE, - MOD_DECIM_MODE_UNSUBDIV, + MOD_DECIM_MODE_COLLAPSE = 0, + MOD_DECIM_MODE_UNSUBDIV = 1, /** called planar in the UI */ - MOD_DECIM_MODE_DISSOLVE, + MOD_DECIM_MODE_DISSOLVE = 2, }; typedef struct SmoothModifierData { @@ -1695,15 +1695,15 @@ enum { /* Triangulate methods - NGons */ enum { MOD_TRIANGULATE_NGON_BEAUTY = 0, - MOD_TRIANGULATE_NGON_EARCLIP, + MOD_TRIANGULATE_NGON_EARCLIP = 1, }; /* Triangulate methods - Quads */ enum { MOD_TRIANGULATE_QUAD_BEAUTY = 0, - MOD_TRIANGULATE_QUAD_FIXED, - MOD_TRIANGULATE_QUAD_ALTERNATE, - MOD_TRIANGULATE_QUAD_SHORTEDGE, + MOD_TRIANGULATE_QUAD_FIXED = 1, + MOD_TRIANGULATE_QUAD_ALTERNATE = 2, + MOD_TRIANGULATE_QUAD_SHORTEDGE = 3, }; typedef struct LaplacianSmoothModifierData { diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 557e069a4a6..94d11095108 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -24,14 +24,14 @@ #ifndef __DNA_MOVIECLIP_TYPES_H__ #define __DNA_MOVIECLIP_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_color_types.h" /* for color management */ #include "DNA_tracking_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct ImBuf; struct MovieClipProxy; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 8029e8ebc13..4ff0e531168 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -154,6 +154,12 @@ typedef enum eNodeSocketDatatype { __SOCK_MESH = 5, /* deprecated */ SOCK_INT = 6, SOCK_STRING = 7, + SOCK_OBJECT = 8, + SOCK_IMAGE = 9, + SOCK_EMITTERS = 10, + SOCK_EVENTS = 11, + SOCK_FORCES = 12, + SOCK_CONTROL_FLOW = 13, } eNodeSocketDatatype; /* socket shape */ @@ -498,6 +504,7 @@ typedef struct bNodeTree { #define NTREE_SHADER 0 #define NTREE_COMPOSIT 1 #define NTREE_TEXTURE 2 +#define NTREE_SIMULATION 3 /* ntree->init, flag */ #define NTREE_TYPE_INIT 1 @@ -565,6 +572,14 @@ typedef struct bNodeSocketValueString { char value[1024]; } bNodeSocketValueString; +typedef struct bNodeSocketValueObject { + struct Object *value; +} bNodeSocketValueObject; + +typedef struct bNodeSocketValueImage { + struct Image *value; +} bNodeSocketValueImage; + /* data structs, for node->storage */ enum { CMP_NODE_MASKTYPE_ADD = 0, @@ -1293,6 +1308,23 @@ enum { NODE_VECTOR_MATH_TANGENT = 23, }; +/* Boolean math node operations. */ +enum { + NODE_BOOLEAN_MATH_AND = 0, + NODE_BOOLEAN_MATH_OR = 1, + NODE_BOOLEAN_MATH_NOT = 2, +}; + +/* Float compare node operations. */ +enum { + NODE_FLOAT_COMPARE_LESS_THAN = 0, + NODE_FLOAT_COMPARE_LESS_EQUAL = 1, + NODE_FLOAT_COMPARE_GREATER_THAN = 2, + NODE_FLOAT_COMPARE_GREATER_EQUAL = 3, + NODE_FLOAT_COMPARE_EQUAL = 4, + NODE_FLOAT_COMPARE_NOT_EQUAL = 5, +}; + /* Clamp node types. */ enum { NODE_CLAMP_MINMAX = 0, @@ -1385,4 +1417,16 @@ typedef enum NodeShaderOutputTarget { SHD_OUTPUT_CYCLES = 2, } NodeShaderOutputTarget; +/* Particle Time Step Event node */ +typedef enum NodeSimParticleTimeStepEventType { + NODE_PARTICLE_TIME_STEP_EVENT_BEGIN = 0, + NODE_PARTICLE_TIME_STEP_EVENT_END = 1, +} NodeSimParticleTimeStepEventType; + +/* Simulation Time node */ +typedef enum NodeSimInputTimeType { + NODE_SIM_INPUT_SIMULATION_TIME = 0, + NODE_SIM_INPUT_SCENE_TIME = 1, +} NodeSimInputTimeType; + #endif diff --git a/source/blender/makesdna/DNA_object_force_types.h b/source/blender/makesdna/DNA_object_force_types.h index 88c712b5b28..73cfcddf984 100644 --- a/source/blender/makesdna/DNA_object_force_types.h +++ b/source/blender/makesdna/DNA_object_force_types.h @@ -24,13 +24,13 @@ #ifndef __DNA_OBJECT_FORCE_TYPES_H__ #define __DNA_OBJECT_FORCE_TYPES_H__ +#include "DNA_defs.h" +#include "DNA_listBase.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_defs.h" -#include "DNA_listBase.h" - /* pd->forcefield: Effector Fields types */ typedef enum ePFieldType { /** (this is used for general effector weight). */ @@ -62,6 +62,7 @@ typedef enum ePFieldType { /** Force based on smoke simulation air flow. */ PFIELD_SMOKEFLOW = 13, + /* Keep last. */ NUM_PFIELD_TYPES, } ePFieldType; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 1a76d32dc2c..47e6db835c9 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -462,6 +462,7 @@ enum { OB_VOLUME = 29, + /* Keep last. */ OB_TYPE_MAX, }; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2c931e68875..1533b82ad4e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -29,10 +29,6 @@ /* XXX, temp feature - campbell */ #define DURIAN_CAMERA_SWITCH -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_collection_types.h" #include "DNA_color_types.h" /* color management */ @@ -46,6 +42,10 @@ extern "C" { #include "DNA_vec_types.h" #include "DNA_view3d_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct Brush; struct Collection; @@ -99,19 +99,19 @@ typedef struct AviCodecData { } AviCodecData; typedef enum eFFMpegPreset { - FFM_PRESET_NONE, + FFM_PRESET_NONE = 0, #ifdef DNA_DEPRECATED_ALLOW /* Previously used by h.264 to control encoding speed vs. file size. */ - FFM_PRESET_ULTRAFAST, /* DEPRECATED */ - FFM_PRESET_SUPERFAST, /* DEPRECATED */ - FFM_PRESET_VERYFAST, /* DEPRECATED */ - FFM_PRESET_FASTER, /* DEPRECATED */ - FFM_PRESET_FAST, /* DEPRECATED */ - FFM_PRESET_MEDIUM, /* DEPRECATED */ - FFM_PRESET_SLOW, /* DEPRECATED */ - FFM_PRESET_SLOWER, /* DEPRECATED */ - FFM_PRESET_VERYSLOW, /* DEPRECATED */ + FFM_PRESET_ULTRAFAST = 1, /* DEPRECATED */ + FFM_PRESET_SUPERFAST = 2, /* DEPRECATED */ + FFM_PRESET_VERYFAST = 3, /* DEPRECATED */ + FFM_PRESET_FASTER = 4, /* DEPRECATED */ + FFM_PRESET_FAST = 5, /* DEPRECATED */ + FFM_PRESET_MEDIUM = 6, /* DEPRECATED */ + FFM_PRESET_SLOW = 7, /* DEPRECATED */ + FFM_PRESET_SLOWER = 8, /* DEPRECATED */ + FFM_PRESET_VERYSLOW = 9, /* DEPRECATED */ #endif /* Used by WEBM/VP9 and h.264 to control encoding speed vs. file size. @@ -121,9 +121,9 @@ typedef enum eFFMpegPreset { /** the default and recommended for most applications */ FFM_PRESET_GOOD = 10, /** recommended if you have lots of time and want the best compression efficiency */ - FFM_PRESET_BEST, + FFM_PRESET_BEST = 11, /** recommended for live / fast encoding */ - FFM_PRESET_REALTIME, + FFM_PRESET_REALTIME = 12, } eFFMpegPreset; /* Mapping from easily-understandable descriptions to CRF values. @@ -2200,14 +2200,14 @@ typedef enum eSculptFlags { /* ImagePaintSettings.mode */ typedef enum eImagePaintMode { - IMAGEPAINT_MODE_MATERIAL, /* detect texture paint slots from the material */ - IMAGEPAINT_MODE_IMAGE, /* select texture paint image directly */ + IMAGEPAINT_MODE_MATERIAL = 0, /* detect texture paint slots from the material */ + IMAGEPAINT_MODE_IMAGE = 1, /* select texture paint image directly */ } eImagePaintMode; /* ImagePaintSettings.interp */ enum { IMAGEPAINT_INTERP_LINEAR = 0, - IMAGEPAINT_INTERP_CLOSEST, + IMAGEPAINT_INTERP_CLOSEST = 1, }; /* ImagePaintSettings.flag */ @@ -2307,17 +2307,17 @@ typedef enum eGPencil_Selectmode_types { /* ToolSettings.gpencil_guide_types */ typedef enum eGPencil_GuideTypes { GP_GUIDE_CIRCULAR = 0, - GP_GUIDE_RADIAL, - GP_GUIDE_PARALLEL, - GP_GUIDE_GRID, - GP_GUIDE_ISO, + GP_GUIDE_RADIAL = 1, + GP_GUIDE_PARALLEL = 2, + GP_GUIDE_GRID = 3, + GP_GUIDE_ISO = 4, } eGPencil_GuideTypes; /* ToolSettings.gpencil_guide_references */ typedef enum eGPencil_Guide_Reference { GP_GUIDE_REF_CURSOR = 0, - GP_GUIDE_REF_CUSTOM, - GP_GUIDE_REF_OBJECT, + GP_GUIDE_REF_CUSTOM = 1, + GP_GUIDE_REF_OBJECT = 2, } eGPencil_Guide_Reference; /* ToolSettings.particle flag */ diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 9a59b69604d..8497d363179 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -306,8 +306,8 @@ enum GlobalAreaFlag { }; typedef enum GlobalAreaAlign { - GLOBAL_AREA_ALIGN_TOP, - GLOBAL_AREA_ALIGN_BOTTOM, + GLOBAL_AREA_ALIGN_TOP = 0, + GLOBAL_AREA_ALIGN_BOTTOM = 1, } GlobalAreaAlign; typedef struct ScrArea_Runtime { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 17b3528aadf..9fee839f979 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -468,6 +468,7 @@ typedef struct SequencerScopes { #define SEQ_SPEED_INTEGRATE (1 << 0) #define SEQ_SPEED_UNUSED_1 (1 << 1) /* cleared */ #define SEQ_SPEED_COMPRESS_IPO_Y (1 << 2) +#define SEQ_SPEED_USE_INTERPOLATION (1 << 3) /* ***************** SEQUENCE ****************** */ #define SEQ_NAME_MAXSTR 64 @@ -634,7 +635,7 @@ enum { seqModifierType_Mask = 5, seqModifierType_WhiteBalance = 6, seqModifierType_Tonemap = 7, - + /* Keep last. */ NUM_SEQUENCE_MODIFIER_TYPES, }; diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h index e0931d8cac3..18a4e8655a3 100644 --- a/source/blender/makesdna/DNA_shader_fx_types.h +++ b/source/blender/makesdna/DNA_shader_fx_types.h @@ -42,6 +42,7 @@ typedef enum ShaderFxType { eShaderFxType_Colorize = 8, eShaderFxType_Shadow = 9, eShaderFxType_Glow = 10, + /* Keep last. */ NUM_SHADER_FX_TYPES, } ShaderFxType; diff --git a/source/blender/makesdna/DNA_simulation_defaults.h b/source/blender/makesdna/DNA_simulation_defaults.h new file mode 100644 index 00000000000..b4cecd861a9 --- /dev/null +++ b/source/blender/makesdna/DNA_simulation_defaults.h @@ -0,0 +1,40 @@ +/* + * 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 DNA + */ + +#ifndef __DNA_SIMULATION_DEFAULTS_H__ +#define __DNA_SIMULATION_DEFAULTS_H__ + +/* Struct members on own line. */ +/* clang-format off */ + +/* -------------------------------------------------------------------- */ +/** \name Simulation Struct + * \{ */ + +#define _DNA_DEFAULT_Simulation \ + { \ + .flag = 0, \ + } + +/** \} */ + +/* clang-format on */ + +#endif /* __DNA_SIMULATION_DEFAULTS_H__ */ diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h new file mode 100644 index 00000000000..113c301bb9e --- /dev/null +++ b/source/blender/makesdna/DNA_simulation_types.h @@ -0,0 +1,41 @@ +/* + * 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 DNA + */ + +#ifndef __DNA_SIMULATION_TYPES_H__ +#define __DNA_SIMULATION_TYPES_H__ + +#include "DNA_ID.h" + +typedef struct Simulation { + ID id; + struct AnimData *adt; /* animation data (must be immediately after id) */ + + struct bNodeTree *nodetree; + + int flag; + int _pad1[1]; +} Simulation; + +/* Simulation.flag */ +enum { + SIM_DS_EXPAND = (1 << 0), +}; + +#endif /* __DNA_SIMULATION_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 648d35c9a2d..8f4f066efbb 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -212,7 +212,7 @@ typedef enum eSpaceButtons_Context { BCONTEXT_SHADERFX = 15, BCONTEXT_OUTPUT = 16, - /* always as last... */ + /* Keep last. */ BCONTEXT_TOT, } eSpaceButtons_Context; @@ -1075,7 +1075,9 @@ typedef struct SpaceImage { int flag; char pixel_snap_mode; - char _pad2[3]; + char _pad2[7]; + + float uv_opacity; int tile_grid_shape[2]; @@ -1718,7 +1720,7 @@ typedef enum eSpace_Type { SPACE_TOPBAR = 21, SPACE_STATUSBAR = 22, - SPACE_TYPE_LAST = SPACE_STATUSBAR, +#define SPACE_TYPE_LAST SPACE_STATUSBAR } eSpace_Type; /* use for function args */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index ab9f3d07849..32a00cc25d1 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -70,6 +70,9 @@ typedef struct MovieTrackingCamera { /* Division distortion model coefficients */ float division_k1, division_k2; + + /* Nuke distortion model coefficients */ + float nuke_k1, nuke_k2; } MovieTrackingCamera; typedef struct MovieTrackingMarker { @@ -455,6 +458,7 @@ typedef struct MovieTracking { enum { TRACKING_DISTORTION_MODEL_POLYNOMIAL = 0, TRACKING_DISTORTION_MODEL_DIVISION = 1, + TRACKING_DISTORTION_MODEL_NUKE = 2, }; /* MovieTrackingCamera->units */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 7a09059e344..019e4c9ea9e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -619,9 +619,8 @@ typedef struct UserDef_FileSpaceData { typedef struct UserDef_Experimental { char use_undo_legacy; - char use_menu_search; /** `makesdna` does not allow empty structs. */ - char _pad0[6]; + char _pad0[7]; } UserDef_Experimental; #define USER_EXPERIMENTAL_TEST(userdef, member) \ @@ -874,9 +873,11 @@ typedef struct UserDef { int sequencer_disk_cache_compression; /* eUserpref_DiskCacheCompression */ int sequencer_disk_cache_size_limit; short sequencer_disk_cache_flag; - char _pad5[2]; + float collection_instance_empty_size; + char _pad10[4]; + struct WalkNavigation walk_navigation; /** The UI for the user preferences. */ @@ -1290,8 +1291,8 @@ typedef enum eUserpref_RenderDisplayType { } eUserpref_RenderDisplayType; typedef enum eUserpref_TempSpaceDisplayType { - USER_TEMP_SPACE_DISPLAY_FULLSCREEN, - USER_TEMP_SPACE_DISPLAY_WINDOW, + USER_TEMP_SPACE_DISPLAY_FULLSCREEN = 0, + USER_TEMP_SPACE_DISPLAY_WINDOW = 1, } eUserpref_TempSpaceDisplayType; typedef enum eUserpref_EmulateMMBMod { diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 21def800e4a..e486730ebcf 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -489,6 +489,7 @@ enum { V3D_OVERLAY_HIDE_BONES = (1 << 8), V3D_OVERLAY_HIDE_OBJECT_XTRAS = (1 << 9), V3D_OVERLAY_HIDE_OBJECT_ORIGINS = (1 << 10), + V3D_OVERLAY_STATS = (1 << 11), }; /** #View3DOverlay.edit_flag */ diff --git a/source/blender/makesdna/DNA_volume_types.h b/source/blender/makesdna/DNA_volume_types.h index 1a49df86761..b3615e87a50 100644 --- a/source/blender/makesdna/DNA_volume_types.h +++ b/source/blender/makesdna/DNA_volume_types.h @@ -95,9 +95,9 @@ enum { /* Volume.sequence_mode */ typedef enum VolumeSequenceMode { VOLUME_SEQUENCE_CLIP = 0, - VOLUME_SEQUENCE_EXTEND, - VOLUME_SEQUENCE_REPEAT, - VOLUME_SEQUENCE_PING_PONG, + VOLUME_SEQUENCE_EXTEND = 1, + VOLUME_SEQUENCE_REPEAT = 2, + VOLUME_SEQUENCE_PING_PONG = 3, } VolumeSequenceMode; /* VolumeDisplay.wireframe_type */ diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index a101e96e958..1b0bf086269 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -146,6 +146,7 @@ set(SRC ../DNA_object_defaults.h ../DNA_pointcloud_defaults.h ../DNA_scene_defaults.h + ../DNA_simulation_defaults.h ../DNA_speaker_defaults.h ../DNA_texture_defaults.h ../DNA_vec_defaults.h diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c index dadd2fd9d7d..2d86e97debf 100644 --- a/source/blender/makesdna/intern/dna_defaults.c +++ b/source/blender/makesdna/intern/dna_defaults.c @@ -71,6 +71,7 @@ #include "DNA_object_types.h" #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -93,6 +94,7 @@ #include "DNA_object_defaults.h" #include "DNA_pointcloud_defaults.h" #include "DNA_scene_defaults.h" +#include "DNA_simulation_defaults.h" #include "DNA_speaker_defaults.h" #include "DNA_texture_defaults.h" #include "DNA_volume_defaults.h" @@ -150,6 +152,9 @@ SDNA_DEFAULT_DECL_STRUCT(PointCloud); SDNA_DEFAULT_DECL_STRUCT(Scene); SDNA_DEFAULT_DECL_STRUCT(ToolSettings); +/* DNA_simulation_defaults.h */ +SDNA_DEFAULT_DECL_STRUCT(Simulation); + /* DNA_speaker_defaults.h */ SDNA_DEFAULT_DECL_STRUCT(Speaker); @@ -260,6 +265,9 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = { SDNA_DEFAULT_DECL_EX(GP_Sculpt_Settings, ToolSettings.gp_sculpt), SDNA_DEFAULT_DECL_EX(GP_Sculpt_Guide, ToolSettings.gp_sculpt.guide), + /* DNA_simulation_defaults.h */ + SDNA_DEFAULT_DECL(Simulation), + /* DNA_speaker_defaults.h */ SDNA_DEFAULT_DECL(Speaker), diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 39b26fef176..09cfe54e94d 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -136,6 +136,7 @@ static const char *includefiles[] = { "DNA_hair_types.h", "DNA_pointcloud_types.h", "DNA_volume_types.h", + "DNA_simulation_types.h", /* see comment above before editing! */ @@ -1073,8 +1074,8 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char types_size_native[structtype] = size_native; types_size_32[structtype] = size_32; types_size_64[structtype] = size_64; - /* two ways to detect if a struct contains a pointer: - * has_pointer is set or size_native doesn't match any of 32/64bit lengths*/ + /* Two ways to detect if a struct contains a pointer: + * has_pointer is set or size_native doesn't match any of 32/64bit lengths. */ if (has_pointer || size_64 != size_native || size_32 != size_native) { if (size_64 % 8) { fprintf(stderr, @@ -1590,6 +1591,7 @@ int main(int argc, char **argv) #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 31d1ed54fa1..d2e27bdbcad 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -259,6 +259,7 @@ extern StructRNA RNA_FreestyleLineStyle; extern StructRNA RNA_FreestyleModuleSettings; extern StructRNA RNA_FreestyleSettings; extern StructRNA RNA_Function; +extern StructRNA RNA_FunctionNode; extern StructRNA RNA_GPencilFrame; extern StructRNA RNA_GPencilInterpolateSettings; extern StructRNA RNA_GPencilLayer; @@ -548,6 +549,9 @@ extern StructRNA RNA_ShrinkwrapConstraint; extern StructRNA RNA_ShrinkwrapModifier; extern StructRNA RNA_SimpleDeformModifier; extern StructRNA RNA_SimplifyGpencilModifier; +extern StructRNA RNA_Simulation; +extern StructRNA RNA_SimulationNode; +extern StructRNA RNA_SimulationNodeTree; extern StructRNA RNA_SkinModifier; extern StructRNA RNA_SmoothGpencilModifier; extern StructRNA RNA_SmoothModifier; @@ -930,10 +934,6 @@ void RNA_property_update_main(struct Main *bmain, PropertyRNA *prop); bool RNA_property_update_check(struct PropertyRNA *prop); -void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop); -void RNA_property_update_cache_flush(struct Main *bmain, struct Scene *scene); -void RNA_property_update_cache_free(void); - /* Property Data */ bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index fef98f9da4b..b6bae805636 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -23,6 +23,10 @@ #include "RNA_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bNodeSocketType; struct bNodeTreeType; struct bNodeType; @@ -191,6 +195,8 @@ extern const EnumPropertyItem rna_enum_node_socket_in_out_items[]; extern const EnumPropertyItem rna_enum_node_math_items[]; extern const EnumPropertyItem rna_enum_mapping_type_items[]; 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_map_range_items[]; extern const EnumPropertyItem rna_enum_node_clamp_items[]; @@ -315,4 +321,8 @@ const EnumPropertyItem *RNA_mask_local_itemf(struct bContext *C, /* Non confirming, utility function. */ const EnumPropertyItem *RNA_enum_node_tree_types_itemf_impl(struct bContext *C, bool *r_free); +#ifdef __cplusplus +} +#endif + #endif /* __RNA_ENUM_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 64b7a3e70c1..cd05aba8794 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -103,6 +103,13 @@ if(WITH_NEW_OBJECT_TYPES) ) endif() +if (WITH_NEW_SIMULATION_TYPE) + list(APPEND DEFSRC + rna_simulation.c + ) +endif() + + set(APISRC rna_action_api.c rna_animation_api.c @@ -342,6 +349,11 @@ if(WITH_NEW_OBJECT_TYPES) add_definitions(-DWITH_NEW_OBJECT_TYPES) endif() +if (WITH_NEW_SIMULATION_TYPE) + add_definitions(-DWITH_NEW_SIMULATION_TYPE) +endif() + + # Build makesrna executable blender_include_dirs( . diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 46854bc6307..86a088f38ed 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -4302,6 +4302,9 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_screen.c", NULL, RNA_def_screen}, {"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint}, {"rna_sequencer.c", "rna_sequencer_api.c", RNA_def_sequencer}, +#ifdef WITH_NEW_SIMULATION_TYPE + {"rna_simulation.c", NULL, RNA_def_simulation}, +#endif {"rna_space.c", "rna_space_api.c", RNA_def_space}, {"rna_speaker.c", NULL, RNA_def_speaker}, {"rna_test.c", NULL, RNA_def_test}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 699ce0f041e..891c30af466 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -71,6 +71,9 @@ const EnumPropertyItem rna_enum_id_type_items[] = { {ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""}, {ID_LP, "LIGHT_PROBE", ICON_LIGHTPROBE_CUBEMAP, "Light Probe", ""}, {ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""}, +#ifdef WITH_NEW_SIMULATION_TYPE + {ID_SIM, "SIMULATION", ICON_PHYSICS, "Simulation", ""}, /* TODO: Use correct icon. */ +#endif {ID_SO, "SOUND", ICON_SOUND, "Sound", ""}, {ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""}, {ID_TXT, "TEXT", ICON_TEXT, "Text", ""}, @@ -303,6 +306,11 @@ short RNA_type_to_ID_code(const StructRNA *type) if (base_type == &RNA_Screen) { return ID_SCR; } +# ifdef WITH_NEW_SIMULATION_TYPE + if (base_type == &RNA_Simulation) { + return ID_SIM; + } +# endif if (base_type == &RNA_Sound) { return ID_SO; } @@ -405,6 +413,12 @@ StructRNA *ID_code_to_RNA_type(short idcode) return &RNA_Scene; case ID_SCR: return &RNA_Screen; + case ID_SIM: +# ifdef WITH_NEW_SIMULATION_TYPE + return &RNA_Simulation; +# else + return &RNA_ID; +# endif case ID_SO: return &RNA_Sound; case ID_SPK: diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index b56a18c18a9..85892758a88 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -98,8 +98,6 @@ void RNA_exit(void) { StructRNA *srna; - RNA_property_update_cache_free(); - for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) { if (srna->cont.prophash) { BLI_ghash_free(srna->cont.prophash, NULL, NULL); @@ -2308,115 +2306,6 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper rna_property_update(NULL, bmain, scene, ptr, prop); } -/* RNA Updates Cache ------------------------ */ -/* Overview of RNA Update cache system: - * - * RNA Update calls need to be cached in order to maintain reasonable performance - * of the animation system (i.e. maintaining a somewhat interactive framerate) - * while still allowing updates to be called (necessary in particular for modifier - * property updates to actually work). - * - * The cache is structured with a dual-layer structure - * - L1 = PointerRNA used as key; owner_id is used (it should always be defined, - * and most updates end up using just that anyways) - * - L2 = Update functions to be called on those PointerRNA's - */ - -/* cache element */ -typedef struct tRnaUpdateCacheElem { - struct tRnaUpdateCacheElem *next, *prev; - - PointerRNA ptr; /* L1 key - id as primary, data secondary/ignored? */ - ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */ -} tRnaUpdateCacheElem; - -/* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */ -static ListBase rna_updates_cache = {NULL, NULL}; - -/* ........................... */ - -void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) -{ - const bool is_rna = (prop->magic == RNA_MAGIC); - tRnaUpdateCacheElem *uce = NULL; - UpdateFunc fn = NULL; - LinkData *ld; - - /* sanity check */ - if (NULL == ptr) { - return; - } - - prop = rna_ensure_property(prop); - - /* we can only handle update calls with no context args for now (makes animsys updates easier) */ - if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) { - return; - } - fn = prop->update; - - /* find cache element for which key matches... */ - for (uce = rna_updates_cache.first; uce; uce = uce->next) { - /* Just match by id only for now, - * since most update calls that we'll encounter only really care about this. */ - /* TODO: later, the cache might need to have some nesting on L1 to cope better - * with these problems + some tagging to indicate we need this */ - if (uce->ptr.owner_id == ptr->owner_id) { - break; - } - } - if (uce == NULL) { - /* create new instance */ - uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem"); - BLI_addtail(&rna_updates_cache, uce); - - /* copy pointer */ - RNA_pointer_create(ptr->owner_id, ptr->type, ptr->data, &uce->ptr); - } - - /* check on the update func */ - for (ld = uce->L2Funcs.first; ld; ld = ld->next) { - /* stop on match - function already cached */ - if (fn == ld->data) { - return; - } - } - /* else... if still here, we need to add it */ - BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn)); -} - -void RNA_property_update_cache_flush(Main *bmain, Scene *scene) -{ - tRnaUpdateCacheElem *uce; - - /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */ - - /* execute the cached updates */ - for (uce = rna_updates_cache.first; uce; uce = uce->next) { - LinkData *ld; - - for (ld = uce->L2Funcs.first; ld; ld = ld->next) { - UpdateFunc fn = (UpdateFunc)ld->data; - fn(bmain, scene, &uce->ptr); - } - } -} - -void RNA_property_update_cache_free(void) -{ - tRnaUpdateCacheElem *uce, *ucn; - - for (uce = rna_updates_cache.first; uce; uce = ucn) { - ucn = uce->next; - - /* free L2 cache */ - BLI_freelistN(&uce->L2Funcs); - - /* remove self */ - BLI_freelinkN(&rna_updates_cache, uce); - } -} - /* ---------------------------------------------------------------------- */ /* Property Data */ @@ -5785,10 +5674,10 @@ static char *rna_idp_path(PointerRNA *ptr, } /** - * Find the path from the structure referenced by the pointer to the IDProperty object. + * Find the path from the structure referenced by the pointer to the #IDProperty object. * - * \param ptr Reference to the object owning the custom property storage. - * \param needle Custom property object to find. + * \param ptr: Reference to the object owning the custom property storage. + * \param needle: Custom property object to find. * \return Relative path or NULL. */ char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, IDProperty *needle) diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 2c4e221ca8c..d3b607fcb76 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1296,6 +1296,48 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + prop = RNA_def_property(srna, "curve_random_pressure", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_pressure"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_strength", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_strength"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_uv", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_uv"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_hue", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_hue"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_saturation", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_saturation"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_value"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + /* fill threshold for transparence */ prop = RNA_def_property(srna, "fill_threshold", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "fill_threshold"); @@ -1434,6 +1476,30 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Vertex Color Factor", "Factor used to mix vertex color to get final color"); + /* Hue randomness. */ + prop = RNA_def_property(srna, "random_hue_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "random_hue"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Hue", "Random factor to modify original hue"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + + /* Saturation randomness. */ + prop = RNA_def_property(srna, "random_saturation_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "random_saturation"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Saturation", "Random factor to modify original saturation"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + + /* Value randomness. */ + prop = RNA_def_property(srna, "random_value_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "random_value"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Value", "Random factor to modify original value"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + /* Flags */ prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_PRESSURE); @@ -1457,6 +1523,90 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + prop = RNA_def_property(srna, "use_stroke_random_hue", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_HUE_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_sat", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_SAT_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_val", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_VAL_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_radius", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_PRESS_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_strength", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_STRENGTH_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_uv", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_UV_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_hue", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_HUE_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_sat", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_SAT_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_val", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_VAL_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_radius", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_PRESSURE_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_strength", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_STRENGTH_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_uv", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_UV_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + prop = RNA_def_property(srna, "use_settings_stabilizer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_STABILIZE_MOUSE); RNA_def_property_boolean_default(prop, true); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 1dae78b9efd..70f219259ef 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -63,7 +63,8 @@ static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), { Object *ob = (Object *)ptr->owner_id; /* ClothSimSettings *settings = (ClothSimSettings *)ptr->data; */ - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type(ob, + eModifierType_Cloth); cloth_free_modifier(clmd); @@ -434,7 +435,7 @@ static void rna_ClothSettings_gravity_set(PointerRNA *ptr, const float *values) static char *rna_ClothSettings_path(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); if (md) { char name_esc[sizeof(md->name) * 2]; @@ -449,7 +450,7 @@ static char *rna_ClothSettings_path(PointerRNA *ptr) static char *rna_ClothCollisionSettings_path(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); if (md) { char name_esc[sizeof(md->name) * 2]; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 33f19153e3a..ea8b0cd758b 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -213,6 +213,7 @@ static StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr) # include "BKE_anim_data.h" # include "BKE_fcurve.h" +# include "BKE_fcurve_driver.h" # include "DEG_depsgraph.h" # include "DEG_depsgraph_build.h" diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 03b57a496ef..fff39326ada 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -224,7 +224,7 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FLIP); /* Only create a particle system in liquid domain mode. */ @@ -249,7 +249,7 @@ static void rna_Fluid_spray_parts_update(Main *bmain, Scene *UNUSED(scene), Poin { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_SPRAY); if (ob->type == OB_MESH && !exists) { @@ -267,7 +267,7 @@ static void rna_Fluid_bubble_parts_update(Main *bmain, Scene *UNUSED(scene), Poi { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_BUBBLE); if (ob->type == OB_MESH && !exists) { @@ -289,7 +289,7 @@ static void rna_Fluid_foam_parts_update(Main *bmain, Scene *UNUSED(scene), Point { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FOAM); if (ob->type == OB_MESH && !exists) { @@ -307,7 +307,7 @@ static void rna_Fluid_tracer_parts_update(Main *bmain, Scene *UNUSED(scene), Poi { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_TRACER); if (ob->type == OB_MESH && !exists) { @@ -329,7 +329,7 @@ static void rna_Fluid_combined_export_update(Main *bmain, Scene *scene, PointerR { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (mmd->domain->sndparticle_combined_export == SNDPARTICLE_COMBINED_EXPORT_OFF) { rna_Fluid_parts_delete(ptr, PART_FLUID_SPRAYFOAM); @@ -515,7 +515,7 @@ static void rna_Fluid_guide_parent_set(struct PointerRNA *ptr, FluidModifierData *mmd_par = NULL; if (par != NULL) { - mmd_par = (FluidModifierData *)modifiers_findByType(par, eModifierType_Fluid); + mmd_par = (FluidModifierData *)BKE_modifiers_findby_type(par, eModifierType_Fluid); if (mmd_par && mmd_par->domain) { mds->guide_parent = value.data; copy_v3_v3_int(mds->guide_res, mmd_par->domain->res); @@ -2467,7 +2467,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Random", "Amount of random velocity"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); - prop = RNA_def_property(srna, "velocity_coord", PROP_FLOAT, PROP_XYZ); + prop = RNA_def_property(srna, "velocity_coord", PROP_FLOAT, PROP_VELOCITY); RNA_def_property_float_sdna(prop, NULL, "vel_coord"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1000.1, 1000.1); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index f09d25ece41..b36cc493447 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -1664,13 +1664,11 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) prop = RNA_def_property(srna, "use_mask_layer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_MASK); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Mask Layer", "Mask pixels from underlying layers drawing"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "use_lights", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_LIGHTS); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text( prop, "Use Lights", "Enable the use of lights on stroke and fill materials"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 5475f62cb8c..3a8ded1a275 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -129,6 +129,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { "Opacity", "Opacity of the strokes"}, {eGpencilModifierType_Tint, "GP_TINT", ICON_MOD_TINT, "Tint", "Tint strokes with new color"}, + {eGpencilModifierType_Texture, + "GP_TEXTURE", + ICON_TEXTURE, + "Texture Mapping", + "Change stroke uv texture values"}, {0, NULL, 0, NULL, NULL}, }; @@ -234,6 +239,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr) return &RNA_ArmatureGpencilModifier; case eGpencilModifierType_Multiply: return &RNA_MultiplyGpencilModifier; + case eGpencilModifierType_Texture: + return &RNA_TextureGpencilModifier; /* Default */ case eGpencilModifierType_None: case NUM_GREASEPENCIL_MODIFIER_TYPES: @@ -302,6 +309,7 @@ RNA_GP_MOD_VGROUP_NAME_SET(Smooth, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Hook, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Offset, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Armature, vgname); +RNA_GP_MOD_VGROUP_NAME_SET(Texture, vgname); # undef RNA_GP_MOD_VGROUP_NAME_SET @@ -434,9 +442,10 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -563,9 +572,10 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -675,9 +685,10 @@ static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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, "level", PROP_INT, PROP_NONE); @@ -764,9 +775,10 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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, "factor", PROP_FLOAT, PROP_FACTOR); @@ -852,9 +864,10 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -946,9 +959,10 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -1043,9 +1057,10 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -1248,9 +1263,10 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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, "hue", PROP_FLOAT, PROP_NONE); @@ -1341,9 +1357,10 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -1437,9 +1454,10 @@ static void rna_def_modifier_gpencilarray(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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, "pass_index", PROP_INT, PROP_NONE); @@ -1663,6 +1681,20 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna) prop, "Restrict Frame Range", "Only modify strokes during the specified frame range"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + /* Use percentage */ + prop = RNA_def_property(srna, "use_percentage", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BUILD_PERCENTAGE); + RNA_def_property_ui_text( + prop, "Restrict Visible Points", "Use a percentage factor to determine the visible points"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + /* Percentage factor. */ + prop = RNA_def_property(srna, "percentage_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "percentage_fac"); + RNA_def_property_ui_text(prop, "Factor", "Defines how much of the stroke is visible"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "start_frame"); RNA_def_property_ui_text( @@ -1715,9 +1747,10 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -1794,9 +1827,10 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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, "pass_index", PROP_INT, PROP_NONE); @@ -1891,9 +1925,10 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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); @@ -2047,9 +2082,10 @@ static void rna_def_modifier_gpencilmultiply(BlenderRNA *brna) 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_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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, "pass_index", PROP_INT, PROP_NONE); @@ -2138,6 +2174,142 @@ static void rna_def_modifier_gpencilmultiply(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); } +static void rna_def_modifier_gpenciltexture(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static const EnumPropertyItem fit_type_items[] = { + {GP_TEX_CONSTANT_LENGTH, + "CONSTANT_LENGTH", + 0, + "Keep Texture at Constant Length", + "Keep the texture at a constant length regardless of the length of each stroke"}, + {GP_TEX_FIT_STROKE, + "FIT_STROKE", + 0, + "Fit Texture to Stroke Length", + "Scale the texture to fit the length of each stroke"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem mode_items[] = { + {STROKE, "STROKE", 0, "Stroke", "Manipulate only stroke texture coordinates"}, + {FILL, "FILL", 0, "Fill", "Manipulate only fill texture coordinates"}, + {STROKE_AND_FILL, + "STROKE_AND_FILL", + 0, + "Stroke and Fill", + "Manipulate both stroke and fill texture coordinates"}, + {0, NULL, 0, NULL, NULL}, + }; + + srna = RNA_def_struct(brna, "TextureGpencilModifier", "GpencilModifier"); + RNA_def_struct_ui_text( + srna, "Texture Modifier", "Transform stroke texture coordinates Modifier"); + RNA_def_struct_sdna(srna, "TextureGpencilModifierData"); + RNA_def_struct_ui_icon(srna, ICON_TEXTURE); + + 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, "invert_layers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_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, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + 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, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_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, "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_TextureGpencilModifier_vgname_set"); + 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_TEX_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, "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_material_pass", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_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, "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_TEX_INVERT_LAYERPASS); + RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "uv_offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "uv_offset"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -100.0, 100.0, 0.1, 3); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Offset UVs", "Offset value to add to stroke UVs"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "uv_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "uv_scale"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "UV Scale", "Factor to scale the UVs"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fill_rotation", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "fill_rotation"); + RNA_def_property_ui_text(prop, "Fill Rotation", "Additional rotation of the fill UV"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fill_offset", PROP_FLOAT, PROP_COORDS); + RNA_def_property_float_sdna(prop, NULL, "fill_offset"); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_text(prop, "Fill Offset", "Additional offset of the fill UV"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fill_scale", PROP_FLOAT, PROP_COORDS); + RNA_def_property_float_sdna(prop, NULL, "fill_scale"); + RNA_def_property_range(prop, 0.01f, 100.0f); + RNA_def_property_ui_text(prop, "Fill Scale", "Additional scale of the fill UV"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "fit_method"); + RNA_def_property_enum_items(prop, fit_type_items); + RNA_def_property_ui_text(prop, "Fit Method", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + + 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_dependency_update"); +} + void RNA_def_greasepencil_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -2211,6 +2383,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna) rna_def_modifier_gpencilhook(brna); rna_def_modifier_gpencilarmature(brna); rna_def_modifier_gpencilmultiply(brna); + rna_def_modifier_gpenciltexture(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 27097261930..cb59eee6afa 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -185,6 +185,7 @@ void RNA_def_render(struct BlenderRNA *brna); void RNA_def_rigidbody(struct BlenderRNA *brna); void RNA_def_rna(struct BlenderRNA *brna); void RNA_def_scene(struct BlenderRNA *brna); +void RNA_def_simulation(struct BlenderRNA *brna); void RNA_def_view_layer(struct BlenderRNA *brna); void RNA_def_screen(struct BlenderRNA *brna); void RNA_def_sculpt_paint(struct BlenderRNA *brna); @@ -449,6 +450,7 @@ void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_hairs(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_pointclouds(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_simulations(BlenderRNA *brna, PropertyRNA *cprop); /* ID Properties */ diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 855d5f46890..2f37e4079c7 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -134,6 +134,9 @@ RNA_MAIN_LISTBASE_FUNCS_DEF(pointclouds) RNA_MAIN_LISTBASE_FUNCS_DEF(scenes) RNA_MAIN_LISTBASE_FUNCS_DEF(screens) RNA_MAIN_LISTBASE_FUNCS_DEF(shapekeys) +# ifdef WITH_NEW_SIMULATION_TYPE +RNA_MAIN_LISTBASE_FUNCS_DEF(simulations) +# endif RNA_MAIN_LISTBASE_FUNCS_DEF(sounds) RNA_MAIN_LISTBASE_FUNCS_DEF(speakers) RNA_MAIN_LISTBASE_FUNCS_DEF(texts) @@ -402,6 +405,14 @@ void RNA_def_main(BlenderRNA *brna) "Volumes", "Volume data-blocks", RNA_def_main_volumes}, +# ifdef WITH_NEW_SIMULATION_TYPE + {"simulations", + "Simulation", + "rna_Main_simulations_begin", + "Simulations", + "Simulation data-blocks", + RNA_def_main_simulations}, +# endif {NULL, NULL, NULL, NULL, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 9799054ccd2..c5781175d65 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -69,6 +69,7 @@ # include "BKE_particle.h" # include "BKE_pointcloud.h" # include "BKE_scene.h" +# include "BKE_simulation.h" # include "BKE_sound.h" # include "BKE_speaker.h" # include "BKE_text.h" @@ -98,6 +99,7 @@ # include "DNA_node_types.h" # include "DNA_particle_types.h" # include "DNA_pointcloud_types.h" +# include "DNA_simulation_types.h" # include "DNA_sound_types.h" # include "DNA_speaker_types.h" # include "DNA_text_types.h" @@ -738,6 +740,18 @@ static Volume *rna_Main_volumes_new(Main *bmain, const char *name) return volume; } +# ifdef WITH_NEW_SIMULATION_TYPE +static Simulation *rna_Main_simulations_new(Main *bmain, const char *name) +{ + char safe_name[MAX_ID_NAME - 2]; + rna_idname_validate(name, safe_name); + + Simulation *simulation = BKE_simulation_add(bmain, safe_name); + id_us_min(&simulation->id); + return simulation; +} +# endif + /* tag functions, all the same */ # define RNA_MAIN_ID_TAG_FUNCS_DEF(_func_name, _listbase_name, _id_type) \ static void rna_Main_##_func_name##_tag(Main *bmain, bool value) \ @@ -785,6 +799,9 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(hairs, hairs, ID_HA) RNA_MAIN_ID_TAG_FUNCS_DEF(pointclouds, pointclouds, ID_PT) # endif RNA_MAIN_ID_TAG_FUNCS_DEF(volumes, volumes, ID_VO) +# ifdef WITH_NEW_SIMULATION_TYPE +RNA_MAIN_ID_TAG_FUNCS_DEF(simulations, simulations, ID_SIM) +# endif # undef RNA_MAIN_ID_TAG_FUNCS_DEF @@ -2304,4 +2321,44 @@ void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } +void RNA_def_main_simulations(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "BlendDataSimulations"); + srna = RNA_def_struct(brna, "BlendDataSimulations", NULL); + RNA_def_struct_sdna(srna, "Main"); + RNA_def_struct_ui_text(srna, "Main Simulations", "Collection of simulations"); + + func = RNA_def_function(srna, "new", "rna_Main_simulations_new"); + RNA_def_function_ui_description(func, "Add a new simulation to the main database"); + parm = RNA_def_string(func, "name", "Simulation", 0, "", "New name for the data-block"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + /* return type */ + parm = RNA_def_pointer(func, "simulation", "Simulation", "", "New simulation data-block"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Main_ID_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a simulation from the current blendfile"); + parm = RNA_def_pointer(func, "simulation", "Simulation", "", "Simulation to remove"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + RNA_def_boolean( + func, "do_unlink", true, "", "Unlink all usages of this simulation before deleting it"); + RNA_def_boolean(func, + "do_id_user", + true, + "", + "Decrement user counter of all datablocks used by this simulation data"); + RNA_def_boolean( + func, "do_ui_user", true, "", "Make sure interface does not reference this simulation data"); + + func = RNA_def_function(srna, "tag", "rna_Main_simulations_tag"); + parm = RNA_def_boolean(func, "value", 0, "Value", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); +} + #endif diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 4dd8053218c..638268adff7 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -266,7 +266,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { ICON_MOD_WAVE, "Wave", "Adds a ripple-like motion to an object’s geometry"}, - {0, "", 0, N_("Simulate"), ""}, + {0, "", 0, N_("Physics"), ""}, {eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""}, {eModifierType_Collision, "COLLISION", ICON_MOD_PHYSICS, "Collision", ""}, {eModifierType_DynamicPaint, "DYNAMIC_PAINT", ICON_MOD_DYNAMICPAINT, "Dynamic Paint", ""}, @@ -741,7 +741,7 @@ static void rna_Modifier_name_set(PointerRNA *ptr, const char *value) /* make sure the name is truly unique */ if (ptr->owner_id) { Object *ob = (Object *)ptr->owner_id; - modifier_unique_name(&ob->modifiers, md); + BKE_modifier_unique_name(&ob->modifiers, md); } /* fix all the animation data which may link to this */ @@ -920,7 +920,7 @@ static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain), { BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0); BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE && - "Unsupported RNA override operation on Hook modifier target objet pointer"); + "Unsupported RNA override operation on Hook modifier target object pointer"); UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop); /* We need a special handling here because setting hook target resets invert parent matrix, diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 5be3db37329..30d1380417f 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -81,6 +81,35 @@ static const EnumPropertyItem node_socket_type_items[] = { {SOCK_STRING, "STRING", 0, "String", ""}, {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, {SOCK_SHADER, "SHADER", 0, "Shader", ""}, + {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, + {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, + {SOCK_EMITTERS, "EMITTERS", 0, "Emitters", ""}, + {SOCK_EVENTS, "EVENTS", 0, "Events", ""}, + {SOCK_FORCES, "FORCES", 0, "Forces", ""}, + {SOCK_CONTROL_FLOW, "CONTROL_FLOW", 0, "Control Flow", ""}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem particle_attribute_socket_type_items[] = { + {SOCK_FLOAT, "FLOAT", 0, "Float", ""}, + {SOCK_INT, "INT", 0, "Int", ""}, + {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "RGBA", 0, "Color", ""}, + {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, + {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem node_socket_data_type_items[] = { + {SOCK_FLOAT, "FLOAT", 0, "Float", ""}, + {SOCK_INT, "INT", 0, "Int", ""}, + {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_STRING, "STRING", 0, "String", ""}, + {SOCK_RGBA, "RGBA", 0, "Color", ""}, + {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, + {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -244,6 +273,47 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_node_boolean_math_items[] = { + {NODE_BOOLEAN_MATH_AND, "AND", 0, "And", "Outputs true only when both inputs are true"}, + {NODE_BOOLEAN_MATH_OR, "OR", 0, "Or", "Outputs or when at least one of the inputs is true"}, + {NODE_BOOLEAN_MATH_NOT, "NOT", 0, "Not", "Outputs the opposite of the input"}, + {0, NULL, 0, NULL, NULL}, +}; + +const EnumPropertyItem rna_enum_node_float_compare_items[] = { + {NODE_FLOAT_COMPARE_LESS_THAN, + "LESS_THAN", + 0, + "A < B", + "True when the first input is smaller than second input"}, + {NODE_FLOAT_COMPARE_LESS_EQUAL, + "LESS_EQUAL", + 0, + "A <= B", + "True when the first input is smaller than the second input or equal"}, + {NODE_FLOAT_COMPARE_GREATER_THAN, + "GREATER_THAN", + 0, + "A > B", + "True when the first input is greater than the second input"}, + {NODE_FLOAT_COMPARE_GREATER_EQUAL, + "GREATER_EQUAL", + 0, + "A >= B", + "True when the first input is greater than the second input or equal"}, + {NODE_FLOAT_COMPARE_EQUAL, + "EQUAL", + 0, + "A = B", + "True when both inputs are approximately equal"}, + {NODE_FLOAT_COMPARE_NOT_EQUAL, + "NOT_EQUAL", + 0, + "A != B", + "True when both inputs are not approximately equal"}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_node_map_range_items[] = { {NODE_MAP_RANGE_LINEAR, "LINEAR", @@ -669,6 +739,34 @@ static const EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), # undef DefNode } + if (RNA_struct_is_a(ptr->type, &RNA_SimulationNode)) { +# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ + if (STREQ(#Category, "SimulationNode")) { \ + tmp.value = ID; \ + tmp.identifier = EnumName; \ + tmp.name = UIName; \ + tmp.description = UIDesc; \ + tmp.icon = ICON_NONE; \ + RNA_enum_item_add(&item, &totitem, &tmp); \ + } +# include "../../nodes/NOD_static_types.h" +# undef DefNode + } + + if (RNA_struct_is_a(ptr->type, &RNA_FunctionNode)) { +# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ + if (STREQ(#Category, "FunctionNode")) { \ + tmp.value = ID; \ + tmp.identifier = EnumName; \ + tmp.name = UIName; \ + tmp.description = UIDesc; \ + tmp.icon = ICON_NONE; \ + RNA_enum_item_add(&item, &totitem, &tmp); \ + } +# include "../../nodes/NOD_static_types.h" +# undef DefNode + } + RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -1785,6 +1883,50 @@ static StructRNA *rna_TextureNode_register(Main *bmain, return nt->rna_ext.srna; } +static StructRNA *rna_SimulationNode_register(Main *bmain, + ReportList *reports, + void *data, + const char *identifier, + StructValidateFunc validate, + StructCallbackFunc call, + StructFreeFunc free) +{ + bNodeType *nt = rna_Node_register_base( + bmain, reports, &RNA_SimulationNode, data, identifier, validate, call, free); + if (!nt) { + return NULL; + } + + nodeRegisterType(nt); + + /* update while blender is running */ + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + + return nt->rna_ext.srna; +} + +static StructRNA *rna_FunctionNode_register(Main *bmain, + ReportList *reports, + void *data, + const char *identifier, + StructValidateFunc validate, + StructCallbackFunc call, + StructFreeFunc free) +{ + bNodeType *nt = rna_Node_register_base( + bmain, reports, &RNA_FunctionNode, data, identifier, validate, call, free); + if (!nt) { + return NULL; + } + + nodeRegisterType(nt); + + /* update while blender is running */ + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + + return nt->rna_ext.srna; +} + static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create) { bNode *node = ptr->data; @@ -3590,6 +3732,15 @@ static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA * rna_Node_update(bmain, scene, ptr); } +static void rna_FunctionNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->owner_id; @@ -3599,6 +3750,15 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA rna_Node_update(bmain, scene, ptr); } +static void rna_SimulationNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr) { bNode *node = ptr->data; @@ -4025,6 +4185,39 @@ static void def_math(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_boolean_math(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_node_boolean_math_items); + RNA_def_property_ui_text(prop, "Operation", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update"); +} + +static void def_float_compare(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_node_float_compare_items); + RNA_def_property_ui_text(prop, "Operation", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update"); +} + +static void def_fn_switch(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, node_socket_data_type_items); + RNA_def_property_ui_text(prop, "Data Type", "Data type for inputs and outputs"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update"); +} + static void def_vector_math(StructRNA *srna) { PropertyRNA *prop; @@ -7908,6 +8101,82 @@ static void def_tex_bricks(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +/* -- Simulation Nodes --------------------------------------------------------- */ + +static void def_sim_particle_time_step_event(StructRNA *srna) +{ + static const EnumPropertyItem mode_items[] = { + {NODE_PARTICLE_TIME_STEP_EVENT_BEGIN, + "BEGIN", + 0, + "Begin", + "Execute for every particle at the beginning of each time step"}, + {NODE_PARTICLE_TIME_STEP_EVENT_END, + "END", + 0, + "End", + "Execute for every particle at the end of each time step"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "When in each time step is the event triggered"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + +static void def_sim_particle_attribute(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, particle_attribute_socket_type_items); + RNA_def_property_ui_text( + prop, + "Data Type", + "Expected type of the attribute. A default value is returned if the type is not correct"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); +} + +static void def_sim_set_particle_attribute(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, particle_attribute_socket_type_items); + RNA_def_property_ui_text( + prop, + "Data Type", + "Expected type of the attribute. Nothing is done if the type is not correct"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); +} + +static void def_sim_time(StructRNA *srna) +{ + static const EnumPropertyItem mode_items[] = { + {NODE_SIM_INPUT_SIMULATION_TIME, + "SIMULATION_TIME", + 0, + "Simulation Time", + "Time since start of simulation"}, + {NODE_SIM_INPUT_SCENE_TIME, "SCENE_TIME", 0, "Scene Time", "Time shown in the timeline"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "The time to output"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); +} + /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) @@ -7945,6 +8214,26 @@ static void rna_def_texture_node(BlenderRNA *brna) RNA_def_struct_register_funcs(srna, "rna_TextureNode_register", "rna_Node_unregister", NULL); } +static void rna_def_simulation_node(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "SimulationNode", "NodeInternal"); + RNA_def_struct_ui_text(srna, "Simulation Node", ""); + RNA_def_struct_sdna(srna, "bNode"); + RNA_def_struct_register_funcs(srna, "rna_SimulationNode_register", "rna_Node_unregister", NULL); +} + +static void rna_def_function_node(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "FunctionNode", "NodeInternal"); + RNA_def_struct_ui_text(srna, "Function Node", ""); + RNA_def_struct_sdna(srna, "bNode"); + RNA_def_struct_register_funcs(srna, "rna_FunctionNode_register", "rna_Node_unregister", NULL); +} + /* -------------------------------------------------------------------------- */ static void rna_def_node_socket(BlenderRNA *brna) @@ -8501,6 +8790,104 @@ static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier RNA_def_struct_sdna(srna, "bNodeSocket"); } +static void rna_def_node_socket_object(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "Object Node Socket", "Object socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); + + /* socket interface */ + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "Object Node Socket Interface", "Object socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); +} + +static void rna_def_node_socket_image(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "Image Node Socket", "Image socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Image"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); + + /* socket interface */ + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "Image Node Socket Interface", "Image socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Image"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); +} + +static void rna_def_node_socket_effector(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); +} + +static void rna_def_node_socket_control_flow(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); +} + static void rna_def_node_socket_standard_types(BlenderRNA *brna) { /* XXX Workaround: Registered functions are not exposed in python by bpy, @@ -8635,6 +9022,17 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) rna_def_node_socket_shader(brna, "NodeSocketShader", "NodeSocketInterfaceShader"); rna_def_node_socket_virtual(brna, "NodeSocketVirtual"); + + rna_def_node_socket_object(brna, "NodeSocketObject", "NodeSocketInterfaceObject"); + + rna_def_node_socket_image(brna, "NodeSocketImage", "NodeSocketInterfaceImage"); + + rna_def_node_socket_effector(brna, "NodeSocketEmitters", "NodeSocketInterfaceEmitters"); + rna_def_node_socket_effector(brna, "NodeSocketEvents", "NodeSocketInterfaceEvents"); + rna_def_node_socket_effector(brna, "NodeSocketForces", "NodeSocketInterfaceForces"); + + rna_def_node_socket_control_flow( + brna, "NodeSocketControlFlow", "NodeSocketInterfaceControlFlow"); } static void rna_def_internal_node(BlenderRNA *brna) @@ -9260,6 +9658,7 @@ static void rna_def_nodetree(BlenderRNA *brna) {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"}, {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"}, {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"}, + {NTREE_SIMULATION, "SIMULATION", ICON_PHYSICS, "Simulation", "Simulation nodes"}, {0, NULL, 0, NULL, NULL}, }; @@ -9483,6 +9882,17 @@ static void rna_def_texture_nodetree(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_TEXTURE); } +static void rna_def_simulation_nodetree(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "SimulationNodeTree", "NodeTree"); + RNA_def_struct_ui_text( + srna, "Simulation Node Tree", "Node tree consisting of linked nodes used for simulations"); + RNA_def_struct_sdna(srna, "bNodeTree"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */ +} + static StructRNA *define_specific_node(BlenderRNA *brna, const char *struct_name, const char *base_name, @@ -9569,6 +9979,8 @@ void RNA_def_nodetree(BlenderRNA *brna) rna_def_shader_node(brna); rna_def_compositor_node(brna); rna_def_texture_node(brna); + rna_def_simulation_node(brna); + rna_def_function_node(brna); rna_def_nodetree(brna); @@ -9577,6 +9989,7 @@ void RNA_def_nodetree(BlenderRNA *brna) rna_def_composite_nodetree(brna); rna_def_shader_nodetree(brna); rna_def_texture_nodetree(brna); + rna_def_simulation_nodetree(brna); # define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ { \ @@ -9593,12 +10006,13 @@ void RNA_def_nodetree(BlenderRNA *brna) */ # include "../../nodes/NOD_static_types.h" - /* Node group types need to be defined for shader, compositor, texture nodes individually. - * Cannot use the static types header for this, since they share the same int id. + /* Node group types need to be defined for shader, compositor, texture, simulation nodes + * individually. Cannot use the static types header for this, since they share the same int id. */ define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group); define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group); define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group); + define_specific_node(brna, "SimulationNodeGroup", "SimulationNode", "Group", "", def_group); def_custom_group(brna, "ShaderNodeCustomGroup", "ShaderNode", diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 33048d4b057..c2ee256ad58 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1638,7 +1638,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain, return false; } - /* While it would be nicer to use lower-level modifier_new() here, this one is lacking + /* While it would be nicer to use lower-level BKE_modifier_new() here, this one is lacking * special-cases handling (particles and other physics modifiers mostly), so using the ED version * instead, to avoid duplicating code. */ ModifierData *mod_dst = ED_object_modifier_add( @@ -1653,7 +1653,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain, ParticleSystem *psys_dst = (mod_dst->type == eModifierType_ParticleSystem) ? ((ParticleSystemModifierData *)mod_dst)->psys : NULL; - modifier_copyData(mod_src, mod_dst); + BKE_modifier_copydata(mod_src, mod_dst); if (mod_dst->type == eModifierType_ParticleSystem) { psys_dst->flag &= ~PSYS_DELETE; ((ParticleSystemModifierData *)mod_dst)->psys = psys_dst; @@ -1745,7 +1745,7 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain, return false; } - /* While it would be nicer to use lower-level modifier_new() here, this one is lacking + /* While it would be nicer to use lower-level BKE_modifier_new() here, this one is lacking * special-cases handling (particles and other physics modifiers mostly), so using the ED version * instead, to avoid duplicating code. */ GpencilModifierData *mod_dst = ED_object_gpencil_modifier_add( @@ -3204,7 +3204,6 @@ static void rna_def_object(BlenderRNA *brna) prop = RNA_def_property(srna, "use_grease_pencil_lights", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_USE_GPENCIL_LIGHTS); RNA_def_property_boolean_default(prop, true); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Use Lights", "Lights affect grease pencil object"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_GPencil_update"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index bc8f6d4e3ae..2c9bdd31141 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -36,7 +36,7 @@ #include "DNA_modifier_types.h" #include "DNA_object_types.h" -#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_curve.h" #include "BKE_layer.h" #include "DEG_depsgraph.h" @@ -951,7 +951,7 @@ void RNA_api_object(StructRNA *srna) RNA_def_function_ui_description(func, "Clears mesh data-block created by to_mesh()"); /* Armature */ - func = RNA_def_function(srna, "find_armature", "modifiers_isDeformedByArmature"); + func = RNA_def_function(srna, "find_armature", "BKE_modifiers_is_deformed_by_armature"); RNA_def_function_ui_description( func, "Find armature influencing this object as a parent or via a modifier"); parm = RNA_def_pointer( diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 4a34d1465dd..e79c186aae4 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -145,7 +145,7 @@ static char *rna_PointCache_path(PointerRNA *ptr) PointCache *cache = ptr->data; for (md = ob->modifiers.first; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (!(mti->flags & eModifierTypeFlag_UsesPointCache)) { continue; @@ -430,7 +430,7 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr)) /* both methods work ok, but return the shorter path */ # if 0 Object *ob = (Object *)ptr->owner_id; - ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Collision); + ModifierData *md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Collision); if (md) { char name_esc[sizeof(md->name) * 2]; @@ -604,7 +604,7 @@ static void rna_SoftBodySettings_spring_vgroup_set(PointerRNA *ptr, const char * static char *rna_SoftBodySettings_path(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody); + ModifierData *md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Softbody); char name_esc[sizeof(md->name) * 2]; BLI_strescape(name_esc, md->name, sizeof(name_esc)); @@ -780,7 +780,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) ModifierData *md; /* check softbody modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Softbody); if (md) { /* no pointer from modifier data to actual softbody storage, would be good to add */ if (ob->soft->effector_weights == ew) { @@ -791,7 +791,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) } /* check cloth modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Cloth); if (md) { ClothModifierData *cmd = (ClothModifierData *)md; if (cmd->sim_parms->effector_weights == ew) { @@ -802,7 +802,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) } /* check smoke modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (md) { FluidModifierData *mmd = (FluidModifierData *)md; if (mmd->domain->effector_weights == ew) { @@ -813,7 +813,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) } /* check dynamic paint modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint); if (md) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; @@ -843,7 +843,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) static void rna_CollisionSettings_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = modifiers_findByType(ob, eModifierType_Collision); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Collision); /* add/remove modifier as needed */ if (ob->pd->deflect && !md) { diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index c1fb3232bb3..73b3515030e 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -827,7 +827,7 @@ static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, Pointer ParticleSystem *psys = (ParticleSystem *)ptr->data; if (psys && !psys->clmd) { - psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); + psys->clmd = (ClothModifierData *)BKE_modifier_new(eModifierType_Cloth); psys->clmd->sim_parms->goalspring = 0.0f; psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS; psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index b16eb17747b..6423175e2f4 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -924,11 +924,11 @@ static void rna_Scene_volume_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_VOLUME | ID_RECALC_SEQUENCER_STRIPS); } -static const char *rna_Scene_statistics_string_get(Scene *scene, - Main *bmain, +static const char *rna_Scene_statistics_string_get(Scene *UNUSED(scene), + Main *UNUSED(bmain), ViewLayer *view_layer) { - return ED_info_stats_string(bmain, scene, view_layer); + return ED_info_footer_string(view_layer); } static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) @@ -5723,6 +5723,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem meta_input_items[] = { + {0, "SCENE", 0, "Scene", "Use metadata from the current scene"}, + {R_STAMP_STRIPMETA, + "STRIPS", + 0, + "Sequencer Strips", + "Use metadata from the strips in the sequencer"}, + {0, NULL, 0, NULL, NULL}, + }; + rna_def_scene_ffmpeg_settings(brna); srna = RNA_def_struct(brna, "RenderSettings", NULL); @@ -6240,10 +6250,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop, "Stamp Labels", "Display stamp labels (\"Camera\" in front of camera name, etc.)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "use_stamp_strip_meta", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_STRIPMETA); - RNA_def_property_ui_text( - prop, "Strip Metadata", "Use metadata from the strips in the sequencer"); + prop = RNA_def_property(srna, "metadata_input", PROP_ENUM, PROP_NONE); /* as an enum */ + RNA_def_property_enum_bitflag_sdna(prop, NULL, "stamp"); + RNA_def_property_enum_items(prop, meta_input_items); + RNA_def_property_ui_text(prop, "Metadata Input", "Where to take the metadata from"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_stamp_memory", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index d218084fc66..fd8ddfff14f 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -2020,9 +2020,10 @@ static void rna_def_editor(BlenderRNA *brna) prop = RNA_def_property(srna, "use_prefetch", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", SEQ_CACHE_PREFETCH_ENABLE); - RNA_def_property_ui_text(prop, - "Prefetch frames", - "Render frames ahead of playhead in background for faster playback"); + RNA_def_property_ui_text( + prop, + "Prefetch Frames", + "Render frames ahead of playhead in the background for faster playback"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); prop = RNA_def_property(srna, "recycle_max_cost", PROP_FLOAT, PROP_NONE); @@ -2760,6 +2761,13 @@ static void rna_def_speed_control(StructRNA *srna) prop, "Scale to Length", "Scale values from 0.0 to 1.0 to target sequence length"); RNA_def_property_update( prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); + + prop = RNA_def_property(srna, "frame_interpolation_mode", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_USE_INTERPOLATION); + RNA_def_property_ui_text( + prop, "Frame interpolation", "Do crossfade blending between current and next frame"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_gaussian_blur(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_simulation.c b/source/blender/makesrna/intern/rna_simulation.c new file mode 100644 index 00000000000..789ea299feb --- /dev/null +++ b/source/blender/makesrna/intern/rna_simulation.c @@ -0,0 +1,56 @@ +/* + * 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 RNA + */ + +#include <stdlib.h> + +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "DNA_simulation_types.h" + +#include "rna_internal.h" + +#ifdef RNA_RUNTIME + +#else + +static void rna_def_simulation(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "Simulation", "ID"); + RNA_def_struct_ui_text(srna, "Simulation", "Simulation data-block"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */ + + prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); + RNA_def_property_ui_text(prop, "Node Tree", "Node tree defining the simulation"); + + /* common */ + rna_def_animdata_common(srna); +} + +void RNA_def_simulation(BlenderRNA *brna) +{ + rna_def_simulation(brna); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_sound_api.c b/source/blender/makesrna/intern/rna_sound_api.c index 2be0ed966f1..418205426d2 100644 --- a/source/blender/makesrna/intern/rna_sound_api.c +++ b/source/blender/makesrna/intern/rna_sound_api.c @@ -10,7 +10,7 @@ * 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, + * 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) 2015 by the Blender Foundation. diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d4d35e07c2a..181d4529ef1 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -45,6 +45,7 @@ #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_workspace_types.h" @@ -531,7 +532,7 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr) { SpaceLink *space = (SpaceLink *)ptr->data; - switch (space->spacetype) { + switch ((eSpace_Type)space->spacetype) { case SPACE_VIEW3D: return &RNA_SpaceView3D; case SPACE_GRAPH: @@ -562,9 +563,16 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr) return &RNA_SpacePreferences; case SPACE_CLIP: return &RNA_SpaceClipEditor; - default: - return &RNA_Space; + + /* Currently no type info. */ + case SPACE_SCRIPT: + case SPACE_EMPTY: + case SPACE_TOPBAR: + case SPACE_STATUSBAR: + break; } + + return &RNA_Space; } static ScrArea *rna_area_from_space(PointerRNA *ptr) @@ -2166,6 +2174,40 @@ static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA * ED_node_tree_update(C); } +# ifdef WITH_NEW_SIMULATION_TYPE +static PointerRNA rna_SpaceNodeEditor_simulation_get(PointerRNA *ptr) +{ + SpaceNode *snode = (SpaceNode *)ptr->data; + ID *id = snode->id; + if (id && GS(id->name) == ID_SIM) { + return rna_pointer_inherit_refine(ptr, &RNA_Simulation, snode->id); + } + else { + return PointerRNA_NULL; + } +} + +static void rna_SpaceNodeEditor_simulation_set(PointerRNA *ptr, + const PointerRNA value, + struct ReportList *UNUSED(reports)) +{ + SpaceNode *snode = (SpaceNode *)ptr->data; + if (!STREQ(snode->tree_idname, "SimulationNodeTree")) { + return; + } + + Simulation *sim = (Simulation *)value.data; + if (sim != NULL) { + bNodeTree *ntree = sim->nodetree; + ED_node_tree_start(snode, ntree, NULL, NULL); + } + else { + ED_node_tree_start(snode, NULL, NULL, NULL); + } + snode->id = &sim->id; +} +# endif + static int rna_SpaceNodeEditor_tree_type_get(PointerRNA *ptr) { SpaceNode *snode = (SpaceNode *)ptr->data; @@ -2935,6 +2977,12 @@ static void rna_def_space_image_uv(BlenderRNA *brna) prop, "Tile Grid Shape", "How many tiles will be shown in the background"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "uv_opacity", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "uv_opacity"); + RNA_def_property_range(prop, 0.0f, 1.0f); + 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 */ prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE); @@ -3563,6 +3611,11 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Text", "Display overlay text"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_stats", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_STATS); + RNA_def_property_ui_text(prop, "Show Statistics", "Display scene statistics overlay text"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_extras", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna( prop, NULL, "overlay.flag", V3D_OVERLAY_HIDE_OBJECT_XTRAS); @@ -5521,6 +5574,13 @@ static void rna_def_fileselect_idfilter(BlenderRNA *brna) "Show/hide Point Cloud data-blocks"}, # endif {FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"}, +# ifdef WITH_NEW_SIMULATION_TYPE + {FILTER_ID_SIM, + "filter_simulation", + ICON_PHYSICS, + "Simulations", + "Show Simulation data-blocks"}, /* TODO: Use correct icon. */ +# endif {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"}, @@ -6202,6 +6262,19 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_ui_text( prop, "ID From", "Data-block from which the edited data-block is linked"); +# ifdef WITH_NEW_SIMULATION_TYPE + prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "Simulation"); + RNA_def_property_ui_text(prop, "Simulation", "Simulation that is being edited"); + RNA_def_property_pointer_funcs(prop, + "rna_SpaceNodeEditor_simulation_get", + "rna_SpaceNodeEditor_simulation_set", + NULL, + NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL); +# endif + prop = RNA_def_property(srna, "path", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "treepath", NULL); RNA_def_property_struct_type(prop, "NodeTreePath"); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 131c13c4d90..507d06482df 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -1149,6 +1149,7 @@ static void rna_def_trackingCamera(BlenderRNA *brna) "Divisions", "Division distortion model which " "better represents wide-angle cameras"}, + {TRACKING_DISTORTION_MODEL_NUKE, "NUKE", 0, "Nuke", "Nuke distortion model"}, {0, NULL, 0, NULL, NULL}, }; @@ -1252,6 +1253,19 @@ static void rna_def_trackingCamera(BlenderRNA *brna) RNA_def_property_ui_text(prop, "K2", "First coefficient of second order division distortion"); RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); + /* Nuke distortion parameters */ + prop = RNA_def_property(srna, "nuke_k1", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_range(prop, -10, 10, 0.1, 3); + RNA_def_property_ui_text(prop, "K1", "First coefficient of second order Nuke distortion"); + RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); + + prop = RNA_def_property(srna, "nuke_k2", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_range(prop, -10, 10, 0.1, 3); + RNA_def_property_ui_text(prop, "K2", "Second coefficient of second order Nuke distortion"); + RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); + /* pixel aspect */ prop = RNA_def_property(srna, "pixel_aspect", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "pixel_aspect"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index a169e81237d..2a64ffa73cd 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -693,7 +693,7 @@ void RNA_api_ui_layout(StructRNA *srna) static float node_socket_color_default[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* simple layout specifiers */ - func = RNA_def_function(srna, "row", "uiLayoutRow"); + func = RNA_def_function(srna, "row", "uiLayoutRowWithHeading"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_function_ui_description( @@ -701,8 +701,14 @@ void RNA_api_ui_layout(StructRNA *srna) "Sub-layout. Items placed in this sublayout are placed next to each other " "in a row"); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + RNA_def_string(func, + "heading", + NULL, + UI_MAX_NAME_STR, + "Heading", + "Label to insert into the layout for this row"); - func = RNA_def_function(srna, "column", "uiLayoutColumn"); + func = RNA_def_function(srna, "column", "uiLayoutColumnWithHeading"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_function_ui_description( @@ -710,6 +716,12 @@ void RNA_api_ui_layout(StructRNA *srna) "Sub-layout. Items placed in this sublayout are placed under each other " "in a column"); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + RNA_def_string(func, + "heading", + NULL, + UI_MAX_NAME_STR, + "Heading", + "Label to insert into the layout for this column"); func = RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow"); RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic", 0, INT_MAX); @@ -887,6 +899,20 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); api_ui_item_common(func); + func = RNA_def_function(srna, "prop_decorator", "uiItemDecoratorR"); + api_ui_item_rna_common(func); + RNA_def_int(func, + "index", + /* RNA_NO_INDEX == -1 */ + -1, + -2, + INT_MAX, + "", + "The index of this button, when set a single member of an array can be accessed, " + "when set to -1 all array members are used", + -2, + INT_MAX); + for (int is_menu_hold = 0; is_menu_hold < 2; is_menu_hold++) { func = (is_menu_hold) ? RNA_def_function(srna, "operator_menu_hold", "rna_uiItemOMenuHold") : RNA_def_function(srna, "operator", "rna_uiItemO"); @@ -1492,6 +1518,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); func = RNA_def_function(srna, "template_node_link", "uiTemplateNodeLink"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); parm = RNA_def_pointer(func, "ntree", "NodeTree", "", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "node", "Node", "", ""); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index c08a95d7e16..00d3189dcbe 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4840,6 +4840,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Enter Edit Mode", "Enter Edit Mode automatically after adding a new object"); + prop = RNA_def_property(srna, "collection_instance_empty_size", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.001f, FLT_MAX); + RNA_def_property_ui_text(prop, + "Collection Instance Empty Size", + "Display size of the empty when new collection instances are created"); + /* Undo */ prop = RNA_def_property(srna, "undo_steps", PROP_INT, PROP_NONE); @@ -6063,10 +6069,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) prop, "Undo Legacy", "Use legacy undo (slower than the new default one, but may be more stable in some cases)"); - - prop = RNA_def_property(srna, "use_menu_search", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "use_menu_search", 1); - RNA_def_property_ui_text(prop, "Menu Search", "Search actions by menus instead of operators"); } static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop) diff --git a/source/blender/makesrna/intern/rna_vfont_api.c b/source/blender/makesrna/intern/rna_vfont_api.c index a85dde5d8b1..1bf61db4871 100644 --- a/source/blender/makesrna/intern/rna_vfont_api.c +++ b/source/blender/makesrna/intern/rna_vfont_api.c @@ -10,7 +10,7 @@ * 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, + * 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) 2015 by the Blender Foundation. diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index b08e48a4b17..04a8500d136 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -45,6 +45,16 @@ static bool rna_XrSessionState_is_running(bContext *C) # endif } +static void rna_XrSessionState_reset_to_base_pose(bContext *C) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_base_pose_reset(&wm->xr); +# else + UNUSED_VARS(C); +# endif +} + # ifdef WITH_XR_OPENXR static wmXrData *rna_XrSessionState_wm_xr_data_get(PointerRNA *ptr) { @@ -197,6 +207,12 @@ static void rna_def_xr_session_state(BlenderRNA *brna) parm = RNA_def_boolean(func, "result", 0, "Result", ""); RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "reset_to_base_pose", "rna_XrSessionState_reset_to_base_pose"); + RNA_def_function_ui_description(func, "Force resetting of position and rotation deltas"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + prop = RNA_def_property(srna, "viewer_pose_location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_array(prop, 3); RNA_def_property_float_funcs(prop, "rna_XrSessionState_viewer_pose_location_get", NULL, NULL); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 275c16873a8..29d456e5126 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -61,7 +61,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif ArmatureModifierData *tamd = (ArmatureModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tamd->prevCos = NULL; } @@ -244,7 +244,7 @@ ModifierTypeInfo modifierType_Armature = { /* structName */ "ArmatureModifierData", /* structSize */ sizeof(ArmatureModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -253,7 +253,10 @@ ModifierTypeInfo modifierType_Armature = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ deformMatricesEM, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index bad1d7d3cf9..fc127c48fc9 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -503,7 +503,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } if (offset_is_too_small) { - modifier_setError( + BKE_modifier_set_error( &amd->modifier, "The offset is too small, we cannot generate the amount of geometry it would require"); } @@ -514,9 +514,9 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + (size_t)end_cap_nverts) > max_num_vertices) { count = 1; - modifier_setError(&amd->modifier, - "The amount of copies is too high, we cannot generate the amount of " - "geometry it would require"); + BKE_modifier_set_error(&amd->modifier, + "The amount of copies is too high, we cannot generate the amount of " + "geometry it would require"); } if (count < 1) { @@ -791,7 +791,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { ArrayModifierData *amd = (ArrayModifierData *)md; return arrayModifier_doArray(amd, ctx, mesh); @@ -831,13 +831,16 @@ ModifierTypeInfo modifierType_Array = { eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index bd2f8a6dca3..fb1b3cd219e 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -72,7 +72,7 @@ static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int const BevelModifierData *bmd_src = (const BevelModifierData *)md_src; BevelModifierData *bmd_dst = (BevelModifierData *)md_dst; - modifier_copyData_generic(md_src, md_dst, flag); + BKE_modifier_copydata_generic(md_src, md_dst, flag); bmd_dst->custom_profile = BKE_curveprofile_copy(bmd_src->custom_profile); } @@ -91,7 +91,7 @@ static void requiredDataMask(Object *UNUSED(ob), /* * This calls the new bevel code (added since 2.64) */ -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; BMesh *bm; @@ -206,7 +206,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes Object *ob = ctx->object; if (harden_normals && (ob->type == OB_MESH) && !(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) { - modifier_setError(md, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error(md, "Enable 'Auto Smooth' in Object Data Properties"); harden_normals = false; } @@ -275,7 +275,10 @@ ModifierTypeInfo modifierType_Bevel = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ freeData, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 67610e8cd29..d8b375b0ee9 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -153,7 +153,7 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BooleanModifierData *bmd = (BooleanModifierData *)md; Mesh *result = mesh; @@ -330,7 +330,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes /* if new mesh returned, return it; otherwise there was * an error, so delete the modifier object */ if (result == NULL) { - modifier_setError(md, "Cannot execute boolean operation"); + BKE_modifier_set_error(md, "Cannot execute boolean operation"); } } @@ -353,13 +353,16 @@ ModifierTypeInfo modifierType_Boolean = { /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 3c1a5744b33..2cd52005362 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -55,7 +55,7 @@ static bool dependsOnTime(ModifierData *UNUSED(md)) return true; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh) { Mesh *result; BuildModifierData *bmd = (BuildModifierData *)md; @@ -282,13 +282,16 @@ ModifierTypeInfo modifierType_Build = { /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index eb6292e5e46..5f2043d8c09 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -523,16 +523,19 @@ ModifierTypeInfo modifierType_Cast = { /* structName */ "CastModifierData", /* structSize */ sizeof(CastModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 0cab6144de8..da7485b5a2d 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -267,7 +267,10 @@ ModifierTypeInfo modifierType_Cloth = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index e1595488d08..0c6133ed7a6 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -254,7 +254,10 @@ ModifierTypeInfo modifierType_Collision = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 52003f8b1d8..6224cf6b1fc 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -79,7 +79,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const CorrectiveSmoothModifierData *csmd = (const CorrectiveSmoothModifierData *)md; CorrectiveSmoothModifierData *tcsmd = (CorrectiveSmoothModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); if (csmd->bind_coords) { tcsmd->bind_coords = MEM_dupallocN(csmd->bind_coords); @@ -602,12 +602,12 @@ static void correctivesmooth_modifier_do(ModifierData *md, BLI_assert(csmd->bind_coords != NULL); /* Copy bound data to the original modifier. */ CorrectiveSmoothModifierData *csmd_orig = (CorrectiveSmoothModifierData *) - modifier_get_original(&csmd->modifier); + BKE_modifier_get_original(&csmd->modifier); csmd_orig->bind_coords = MEM_dupallocN(csmd->bind_coords); csmd_orig->bind_coords_num = csmd->bind_coords_num; } else { - modifier_setError(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); } } @@ -617,14 +617,14 @@ static void correctivesmooth_modifier_do(ModifierData *md, } if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) { - modifier_setError(md, "Bind data required"); + BKE_modifier_set_error(md, "Bind data required"); goto error; } /* If the number of verts has changed, the bind is invalid, so we do nothing */ if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { if (csmd->bind_coords_num != numVerts) { - modifier_setError( + BKE_modifier_set_error( md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); goto error; } @@ -632,14 +632,15 @@ static void correctivesmooth_modifier_do(ModifierData *md, else { /* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */ if (ob->type != OB_MESH) { - modifier_setError(md, "Object is not a mesh"); + BKE_modifier_set_error(md, "Object is not a mesh"); goto error; } else { uint me_numVerts = (uint)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert); if (me_numVerts != numVerts) { - modifier_setError(md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); + BKE_modifier_set_error( + md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); goto error; } } @@ -776,7 +777,10 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index e287685a9e5..238c8223799 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -154,16 +154,19 @@ ModifierTypeInfo modifierType_Curve = { /* structName */ "CurveModifierData", /* structSize */ sizeof(CurveModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 72cbe197251..dea4bad6999 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -10,7 +10,7 @@ * 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, + * 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) 2014 Blender Foundation. @@ -156,7 +156,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), (DT_TYPE_BWEIGHT_VERT | DT_TYPE_BWEIGHT_EDGE | DT_TYPE_CREASE | DT_TYPE_SHARP_EDGE | \ DT_TYPE_LNOR | DT_TYPE_SHARP_FACE) -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me_mod) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me_mod) { DataTransferModifierData *dtmd = (DataTransferModifierData *)md; struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); @@ -217,16 +217,15 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes &reports); if (BKE_reports_contain(&reports, RPT_ERROR)) { - modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR)); + BKE_modifier_set_error(md, "%s", BKE_reports_string(&reports, RPT_ERROR)); } else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) { - modifier_setError((ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error((ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); } else if (result->totvert > HIGH_POLY_WARNING || ((Mesh *)(ob_source->data))->totvert > HIGH_POLY_WARNING) { - modifier_setError( - md, - "You are using a rather high poly as source or destination, computation might be slow"); + BKE_modifier_set_error( + md, "Source or destination object has a high polygon count, computation might be slow"); } return result; @@ -243,13 +242,16 @@ ModifierTypeInfo modifierType_DataTransfer = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index cf07b5460e1..3958713f7a8 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -73,7 +73,7 @@ static DecimateModifierData *getOriginalModifierData(const DecimateModifierData const ModifierEvalContext *ctx) { Object *ob_orig = DEG_get_original_object(ctx->object); - return (DecimateModifierData *)modifiers_findByName(ob_orig, dmd->modifier.name); + return (DecimateModifierData *)BKE_modifiers_findny_name(ob_orig, dmd->modifier.name); } static void updateFaceCount(const ModifierEvalContext *ctx, @@ -89,7 +89,7 @@ static void updateFaceCount(const ModifierEvalContext *ctx, } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) { DecimateModifierData *dmd = (DecimateModifierData *)md; Mesh *mesh = meshData, *result = NULL; @@ -128,7 +128,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } if (dmd->face_count <= 3) { - modifier_setError(md, "Modifier requires more than 3 input faces"); + BKE_modifier_set_error(md, "Modifier requires more than 3 input faces"); return mesh; } @@ -222,13 +222,16 @@ ModifierTypeInfo modifierType_Decimate = { /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 19a4e855153..514ea185ede 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -421,13 +421,16 @@ ModifierTypeInfo modifierType_Displace = { /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index d36fce3752b..3cace5745e6 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -101,7 +101,7 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; @@ -187,7 +187,10 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 69ba4aa2795..dd5669cd10c 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -113,7 +113,7 @@ static void initData(ModifierData *md) emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { Mesh *result; EdgeSplitModifierData *emd = (EdgeSplitModifierData *)md; @@ -136,13 +136,16 @@ ModifierTypeInfo modifierType_EdgeSplit = { eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index d380747eb31..747269f4c80 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -67,7 +67,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif ExplodeModifierData *temd = (ExplodeModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); temd->facepa = NULL; } @@ -1123,7 +1123,7 @@ static ParticleSystemModifierData *findPrecedingParticlesystem(Object *ob, Modif } return psmd; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { ExplodeModifierData *emd = (ExplodeModifierData *)md; ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ctx->object, md); @@ -1186,7 +1186,10 @@ ModifierTypeInfo modifierType_Explode = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index 1c2f0a413a7..4880bd06ee9 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -101,7 +101,7 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me) { #ifndef WITH_FLUID UNUSED_VARS(md, ctx); @@ -207,7 +207,10 @@ ModifierTypeInfo modifierType_Fluid = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 1ae2c5e4424..d93b3c56e5a 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -59,7 +59,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const HookModifierData *hmd = (const HookModifierData *)md; HookModifierData *thmd = (HookModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); thmd->curfalloff = BKE_curvemapping_copy(hmd->curfalloff); @@ -393,7 +393,7 @@ ModifierTypeInfo modifierType_Hook = { /* structName */ "HookModifierData", /* structSize */ sizeof(HookModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -401,7 +401,10 @@ ModifierTypeInfo modifierType_Hook = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index 683696b0725..095ca95594b 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -10,7 +10,7 @@ * 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, + * 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) 2013 by the Blender Foundation. @@ -667,17 +667,17 @@ static void LaplacianDeformModifier_do( } else { if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) { - modifier_setError( + BKE_modifier_set_error( &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) { - modifier_setError( + BKE_modifier_set_error( &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) { - modifier_setError(&lmd->modifier, - "Vertex group '%s' is not valid, or maybe empty", - sys->anchor_grp_name); + BKE_modifier_set_error(&lmd->modifier, + "Vertex group '%s' is not valid, or maybe empty", + sys->anchor_grp_name); } } } @@ -688,7 +688,7 @@ static void LaplacianDeformModifier_do( } else { if (!isValidVertexGroup(lmd, ob, mesh)) { - modifier_setError( + BKE_modifier_set_error( &lmd->modifier, "Vertex group '%s' is not valid, or maybe empty", lmd->anchor_grp_name); lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND; } @@ -709,7 +709,7 @@ static void LaplacianDeformModifier_do( } } if (sys && sys->is_matrix_computed && !sys->has_solution) { - modifier_setError(&lmd->modifier, "The system did not find a solution"); + BKE_modifier_set_error(&lmd->modifier, "The system did not find a solution"); } } @@ -729,7 +729,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const LaplacianDeformModifierData *lmd = (const LaplacianDeformModifierData *)md; LaplacianDeformModifierData *tlmd = (LaplacianDeformModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tlmd->vertexco = MEM_dupallocN(lmd->vertexco); tlmd->cache_system = NULL; @@ -814,7 +814,10 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 97e94c46340..2fefca68bad 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -574,13 +574,16 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ init_data, /* requiredDataMask */ required_data_mask, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 2b39f40a2b9..8dd507d51a4 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -137,16 +137,19 @@ ModifierTypeInfo modifierType_Lattice = { /* structName */ "LatticeModifierData", /* structSize */ sizeof(LatticeModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 3bdb5a3fd54..a458e4dd8bc 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -46,14 +46,14 @@ #include "MOD_modifiertypes.h" -#include "BLI_array_cxx.h" -#include "BLI_listbase_wrapper.h" -#include "BLI_vector.h" +#include "BLI_array.hh" +#include "BLI_listbase_wrapper.hh" +#include "BLI_vector.hh" using BLI::Array; using BLI::ArrayRef; using BLI::IndexRange; -using BLI::IntrusiveListBaseWrapper; +using BLI::ListBaseWrapper; using BLI::MutableArrayRef; using BLI::Vector; @@ -93,7 +93,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 : IntrusiveListBaseWrapper<bDeformGroup>(ob->defbase)) { + for (bDeformGroup *def : ListBaseWrapper<bDeformGroup>(ob->defbase)) { 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); @@ -293,7 +293,7 @@ static 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 *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { MaskModifierData *mmd = (MaskModifierData *)md; Object *ob = ctx->object; @@ -395,13 +395,16 @@ ModifierTypeInfo modifierType_Mask = { (ModifierTypeFlag)(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode), - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index c2cbddf806c..219de1569b3 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -167,13 +167,13 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* we could support any object type */ if (UNLIKELY(ob->type != OB_MESH)) { - modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); + BKE_modifier_set_error(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); } else if (UNLIKELY(me->totvert != numVerts)) { - modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); + BKE_modifier_set_error(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); } else if (UNLIKELY(me->totpoly == 0)) { - modifier_setError(&mcmd->modifier, "'Integrate' requires faces"); + BKE_modifier_set_error(&mcmd->modifier, "'Integrate' requires faces"); } else { /* the moons align! */ @@ -212,7 +212,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* -------------------------------------------------------------------- */ /* Apply the transformation matrix (if needed) */ if (UNLIKELY(err_str)) { - modifier_setError(&mcmd->modifier, "%s", err_str); + BKE_modifier_set_error(&mcmd->modifier, "%s", err_str); } else if (ok) { bool use_matrix = false; @@ -292,16 +292,19 @@ ModifierTypeInfo modifierType_MeshCache = { /* structName */ "MeshCacheModifierData", /* structSize */ sizeof(MeshCacheModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index d1fa496c3e5..c5ed6363415 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -93,7 +93,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const MeshDeformModifierData *mmd = (const MeshDeformModifierData *)md; MeshDeformModifierData *tmmd = (MeshDeformModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); if (mmd->bindinfluences) { tmmd->bindinfluences = MEM_dupallocN(mmd->bindinfluences); @@ -363,7 +363,7 @@ static void meshdeformModifier_do(ModifierData *md, Object *ob_target = mmd->object; cagemesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (cagemesh == NULL) { - modifier_setError(md, "Cannot get mesh from cage object"); + BKE_modifier_set_error(md, "Cannot get mesh from cage object"); return; } @@ -378,7 +378,7 @@ static void meshdeformModifier_do(ModifierData *md, if (!mmd->bindcagecos) { /* progress bar redraw can make this recursive .. */ if (!DEG_is_active(ctx->depsgraph)) { - modifier_setError(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); goto finally; } if (!recursive_bind_sentinel) { @@ -395,15 +395,15 @@ static void meshdeformModifier_do(ModifierData *md, totcagevert = cagemesh->totvert; if (mmd->totvert != totvert) { - modifier_setError(md, "Verts changed from %d to %d", mmd->totvert, totvert); + BKE_modifier_set_error(md, "Verts changed from %d to %d", mmd->totvert, totvert); goto finally; } else if (mmd->totcagevert != totcagevert) { - modifier_setError(md, "Cage verts changed from %d to %d", mmd->totcagevert, totcagevert); + BKE_modifier_set_error(md, "Cage verts changed from %d to %d", mmd->totcagevert, totcagevert); goto finally; } else if (mmd->bindcagecos == NULL) { - modifier_setError(md, "Bind data missing"); + BKE_modifier_set_error(md, "Bind data missing"); goto finally; } @@ -488,7 +488,7 @@ static void deformVertsEM(ModifierData *md, #define MESHDEFORM_MIN_INFLUENCE 0.00001f -void modifier_mdef_compact_influences(ModifierData *md) +void BKE_modifier_mdef_compact_influences(ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; float weight, *weights, totweight; @@ -558,7 +558,7 @@ ModifierTypeInfo modifierType_MeshDeform = { /* structName */ "MeshDeformModifierData", /* structSize */ sizeof(MeshDeformModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -567,7 +567,10 @@ ModifierTypeInfo modifierType_MeshDeform = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 7357f18eb6a..51275c4e58f 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -64,7 +64,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif MeshSeqCacheModifierData *tmcmd = (MeshSeqCacheModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tmcmd->reader = NULL; tmcmd->reader_object_path[0] = '\0'; @@ -90,7 +90,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (mcmd->cache_file == NULL) || (mcmd->object_path[0] == '\0'); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { #ifdef WITH_ALEMBIC MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; @@ -109,7 +109,8 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes STRNCPY(mcmd->reader_object_path, mcmd->object_path); BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path); if (!mcmd->reader) { - modifier_setError(md, "Could not create Alembic reader for file %s", cache_file->filepath); + BKE_modifier_set_error( + md, "Could not create Alembic reader for file %s", cache_file->filepath); return mesh; } } @@ -141,7 +142,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes Mesh *result = ABC_read_mesh(mcmd->reader, ctx->object, mesh, time, &err_str, mcmd->read_flag); if (err_str) { - modifier_setError(md, "%s", err_str); + BKE_modifier_set_error(md, "%s", err_str); } if (!ELEM(result, NULL, mesh) && (mesh != org_mesh)) { @@ -197,7 +198,10 @@ ModifierTypeInfo modifierType_MeshSequenceCache = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 3b3dfa2bda2..bbbcac262ca 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -100,7 +100,7 @@ static Mesh *mirrorModifier__doMirror(MirrorModifierData *mmd, return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; MirrorModifierData *mmd = (MirrorModifierData *)md; @@ -124,13 +124,16 @@ ModifierTypeInfo modifierType_Mirror = { /* this is only the case when 'MOD_MIR_VGROUP' is used */ eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index f9d53d08c2e..5174a996480 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -66,7 +66,7 @@ static void initData(ModifierData *md) static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int flag) { - modifier_copyData_generic(md_src, md_dst, flag); + BKE_modifier_copydata_generic(md_src, md_dst, flag); } static void freeRuntimeData(void *runtime_data_v) @@ -172,11 +172,11 @@ static Mesh *multires_as_ccg(MultiresModifierData *mmd, return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return result; #endif MultiresModifierData *mmd = (MultiresModifierData *)md; @@ -245,7 +245,7 @@ static void deformMatrices(ModifierData *md, { #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return; #endif @@ -286,7 +286,10 @@ ModifierTypeInfo modifierType_Multires = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index 9be422afab9..84c9fc1d726 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -51,7 +51,10 @@ ModifierTypeInfo modifierType_None = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 0b101b26906..1521cfab356 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -464,7 +464,7 @@ static bool is_valid_target(NormalEditModifierData *enmd) else if ((enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) && enmd->target) { return true; } - modifier_setError((ModifierData *)enmd, "Invalid target settings"); + BKE_modifier_set_error((ModifierData *)enmd, "Invalid target settings"); return false; } @@ -494,7 +494,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - modifier_setError((ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error((ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } @@ -684,7 +684,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { return normalEditModifier_do((NormalEditModifierData *)md, ctx, ctx->object, mesh); } @@ -697,13 +697,16 @@ ModifierTypeInfo modifierType_NormalEdit = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index fddfc74f267..4c7c644952b 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -46,7 +46,7 @@ #ifdef WITH_OCEANSIM static void init_cache_data(Object *ob, struct OceanModifierData *omd) { - const char *relbase = modifier_path_relbase_from_global(ob); + const char *relbase = BKE_modifier_path_relbase_from_global(ob); omd->oceancache = BKE_ocean_init_cache(omd->cachepath, relbase, @@ -100,7 +100,7 @@ static void initData(ModifierData *md) omd->repeat_x = 1; omd->repeat_y = 1; - modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); + BKE_modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); omd->cached = 0; omd->bakestart = 1; @@ -141,7 +141,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla # endif OceanModifierData *tomd = (OceanModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); /* The oceancache object will be recreated for this copy * automatically when cached=true */ @@ -482,7 +482,7 @@ static Mesh *doOcean(ModifierData *UNUSED(md), const ModifierEvalContext *UNUSED } #endif /* WITH_OCEANSIM */ -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; @@ -509,7 +509,10 @@ ModifierTypeInfo modifierType_Ocean = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 8a4468ec91e..644962ab71c 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -110,7 +110,7 @@ static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRend required_mode = eModifierMode_Realtime; } - if (!modifier_isEnabled(scene, ob_md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, ob_md, required_mode)) { return true; } @@ -204,7 +204,7 @@ static void store_float_in_vcol(MLoopCol *vcol, float float_value) vcol->a = 1.0f; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; @@ -554,13 +554,16 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 05bfe9aeff0..fc5359c953f 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -61,7 +61,7 @@ static void freeData(ModifierData *md) psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; /* ED_object_modifier_remove may have freed this first before calling - * modifier_free (which calls this function) */ + * BKE_modifier_free (which calls this function) */ if (psmd->psys) { psmd->psys->flag |= PSYS_DELETE; } @@ -74,7 +74,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tpsmd->mesh_final = NULL; tpsmd->mesh_original = NULL; @@ -216,7 +216,7 @@ static void deformVerts(ModifierData *md, if (DEG_is_active(ctx->depsgraph)) { Object *object_orig = DEG_get_original_object(ctx->object); - ModifierData *md_orig = modifiers_findByName(object_orig, psmd->modifier.name); + ModifierData *md_orig = BKE_modifiers_findny_name(object_orig, psmd->modifier.name); BLI_assert(md_orig != NULL); ParticleSystemModifierData *psmd_orig = (ParticleSystemModifierData *)md_orig; psmd_orig->flag = psmd->flag; @@ -264,7 +264,10 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 2fa8dc973a1..cdb513595a1 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -136,7 +136,7 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4]) output->curface++; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { RemeshModifierData *rmd; DualConOutput *output; @@ -210,9 +210,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(c #else /* !WITH_MOD_REMESH */ -static Mesh *applyModifier(ModifierData *UNUSED(md), - const ModifierEvalContext *UNUSED(ctx), - Mesh *mesh) +static Mesh *modifyMesh(ModifierData *UNUSED(md), + const ModifierEvalContext *UNUSED(ctx), + Mesh *mesh) { return mesh; } @@ -227,13 +227,16 @@ ModifierTypeInfo modifierType_Remesh = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index e832a23b4ed..d3d42068812 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -178,7 +178,7 @@ static void initData(ModifierData *md) ltmd->merge_dist = 0.01f; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) { Mesh *mesh = meshData; Mesh *result; @@ -1165,13 +1165,16 @@ ModifierTypeInfo modifierType_Screw = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 25f702bf696..abab0aff927 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -122,7 +122,7 @@ ModifierTypeInfo modifierType_ShapeKey = { /* structName */ "ShapeKeyModifierData", /* structSize */ sizeof(ShapeKeyModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ NULL, @@ -131,7 +131,10 @@ ModifierTypeInfo modifierType_ShapeKey = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ deformMatricesEM, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 842ec46f364..bb8519b01ea 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -204,16 +204,19 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* structSize */ sizeof(ShrinkwrapModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_AcceptsLattice | eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 65ea6b95824..0bd16a318ae 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -454,16 +454,19 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_AcceptsLattice | eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index ec7c2b5b1a4..98c7d809f33 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -1779,7 +1779,7 @@ static BMesh *build_skin(SkinNode *skin_nodes, skin_update_merged_vertices(skin_nodes, totvert); if (!skin_output_branch_hulls(&so, skin_nodes, totvert, emap, medge)) { - modifier_setError(&smd->modifier, "Hull error"); + BKE_modifier_set_error(&smd->modifier, "Hull error"); } /* Merge triangles here in the hope of providing better target @@ -1862,7 +1862,7 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) MEM_freeN(emapmem); if (!has_valid_root) { - modifier_setError( + BKE_modifier_set_error( &smd->modifier, "No valid root vertex found (you need one per mesh island you want to skin)"); } @@ -1911,7 +1911,7 @@ static void initData(ModifierData *md) smd->symmetry_axes = MOD_SKIN_SYMM_X; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { Mesh *result; @@ -1935,13 +1935,16 @@ ModifierTypeInfo modifierType_Skin = { /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 2a0376fd291..5b13bee7dac 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -231,13 +231,16 @@ ModifierTypeInfo modifierType_Smooth = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index efe6b188fa0..92516d3d417 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -78,7 +78,7 @@ ModifierTypeInfo modifierType_Softbody = { /* structName */ "SoftbodyModifierData", /* structSize */ sizeof(SoftbodyModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_RequiresOriginalData | eModifierTypeFlag_Single | eModifierTypeFlag_UsesPointCache, @@ -88,7 +88,10 @@ ModifierTypeInfo modifierType_Softbody = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index fc9719a5fb4..01277facacf 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -70,14 +70,14 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { const SolidifyModifierData *smd = (SolidifyModifierData *)md; switch (smd->mode) { case MOD_SOLIDIFY_MODE_EXTRUDE: - return MOD_solidify_extrude_applyModifier(md, ctx, mesh); + return MOD_solidify_extrude_modifyMesh(md, ctx, mesh); case MOD_SOLIDIFY_MODE_NONMANIFOLD: - return MOD_solidify_nonmanifold_applyModifier(md, ctx, mesh); + return MOD_solidify_nonmanifold_modifyMesh(md, ctx, mesh); default: BLI_assert(0); } @@ -94,13 +94,16 @@ ModifierTypeInfo modifierType_Solidify = { eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index fee1b552d89..75d2be5292e 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -183,9 +183,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, float (*poly_nors)[3], float (*r_ver /** \name Main Solidify Function * \{ */ -Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh) +Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; const SolidifyModifierData *smd = (SolidifyModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index e42207081ed..423a6b4458a 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -132,9 +132,9 @@ static int comp_float_int_pair(const void *a, const void *b) return (int)(x->angle > y->angle) - (int)(x->angle < y->angle); } -Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh) +Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *mesh) { Mesh *result; const SolidifyModifierData *smd = (SolidifyModifierData *)md; @@ -2424,15 +2424,15 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, MEM_freeN(face_edges); } if (edge_index != numNewEdges) { - modifier_setError( + BKE_modifier_set_error( md, "Internal Error: edges array wrong size: %u instead of %u", numNewEdges, edge_index); } if (poly_index != numNewPolys) { - modifier_setError( + BKE_modifier_set_error( md, "Internal Error: polys array wrong size: %u instead of %u", numNewPolys, poly_index); } if (loop_index != numNewLoops) { - modifier_setError( + BKE_modifier_set_error( md, "Internal Error: loops array wrong size: %u instead of %u", numNewLoops, loop_index); } BLI_assert(edge_index == numNewEdges); diff --git a/source/blender/modifiers/intern/MOD_solidify_util.h b/source/blender/modifiers/intern/MOD_solidify_util.h index 3a9608861dc..6ab4734c451 100644 --- a/source/blender/modifiers/intern/MOD_solidify_util.h +++ b/source/blender/modifiers/intern/MOD_solidify_util.h @@ -22,13 +22,13 @@ #define __MOD_SOLIDIFY_UTIL_H__ /* MOD_solidify_extrude.c */ -Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh); +Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *mesh); /* MOD_solidify_nonmanifold.c */ -Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh); +Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *mesh); #endif /* __MOD_SOLIDIFY_UTIL_H__ */ diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index b3bc5a66e8c..e054e3478ea 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -68,7 +68,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif SubsurfModifierData *tsmd = (SubsurfModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tsmd->emCache = tsmd->mCache = NULL; } @@ -206,11 +206,11 @@ static SubsurfRuntimeData *subsurf_ensure_runtime(SubsurfModifierData *smd) /* Modifier itself. */ -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return result; #endif SubsurfModifierData *smd = (SubsurfModifierData *)md; @@ -249,7 +249,7 @@ static void deformMatrices(ModifierData *md, int num_verts) { #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return; #endif @@ -290,7 +290,10 @@ ModifierTypeInfo modifierType_Subsurf = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 0e318e9b092..b7449cbe91c 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -56,7 +56,7 @@ static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int { SurfaceModifierData *surmd_dst = (SurfaceModifierData *)md_dst; - modifier_copyData_generic(md_src, md_dst, flag); + BKE_modifier_copydata_generic(md_src, md_dst, flag); surmd_dst->bvhtree = NULL; surmd_dst->mesh = NULL; @@ -196,7 +196,10 @@ ModifierTypeInfo modifierType_Surface = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 4ef1f32462a..4169c76272e 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright 2017, Blender Foundation. @@ -112,7 +112,7 @@ typedef struct SDefDeformData { const SDefVert *const bind_verts; float (*const targetCos)[3]; float (*const vertexCos)[3]; - float(*const weights); + float *const weights; float const strength; } SDefDeformData; @@ -180,7 +180,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md; SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); if (smd->verts) { tsmd->verts = MEM_dupallocN(smd->verts); @@ -1017,20 +1017,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap"); if (vert_edges == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); return false; } adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge"); if (adj_array == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); return false; } edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap"); if (edge_polys == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); MEM_freeN(adj_array); return false; @@ -1038,14 +1038,14 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, smd_orig->verts = MEM_malloc_arrayN(numverts, sizeof(*smd_orig->verts), "SDefBindVerts"); if (smd_orig->verts == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); return false; } BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2); if (treeData.tree == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); MEM_freeN(smd_orig->verts); smd_orig->verts = NULL; @@ -1056,7 +1056,8 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys); if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target has edges with more than two polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, + "Target has edges with more than two polygons"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); MEM_freeN(smd_orig->verts); @@ -1083,7 +1084,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, }; if (data.targetCos == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); return false; } @@ -1102,19 +1103,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, MEM_freeN(data.targetCos); if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target has edges with more than two polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, + "Target has edges with more than two polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target contains concave polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains concave polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target contains overlapping verts"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains overlapping verts"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) { @@ -1122,7 +1124,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, * to explain this with a reasonably sized message. * Though it shouldn't really matter all that much, * because this is very unlikely to occur */ - modifier_setError((ModifierData *)smd_eval, "Target contains invalid polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } @@ -1219,10 +1221,10 @@ static void surfacedeformModifier_do(ModifierData *md, if (!(smd->flags & MOD_SDEF_BIND)) { if (smd->verts != NULL) { if (!DEG_is_active(ctx->depsgraph)) { - modifier_setError(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); return; } - ModifierData *md_orig = modifier_get_original(md); + ModifierData *md_orig = BKE_modifier_get_original(md); freeData(md_orig); } return; @@ -1231,7 +1233,7 @@ static void surfacedeformModifier_do(ModifierData *md, Object *ob_target = smd->target; target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (!target) { - modifier_setError(md, "No valid target mesh"); + BKE_modifier_set_error(md, "No valid target mesh"); return; } @@ -1241,11 +1243,12 @@ static void surfacedeformModifier_do(ModifierData *md, /* If not bound, execute bind. */ if (smd->verts == NULL) { if (!DEG_is_active(ctx->depsgraph)) { - modifier_setError(md, "Attempt to unbind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to unbind from inactive dependency graph"); return; } - SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)modifier_get_original(md); + SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)BKE_modifier_get_original( + md); float tmp_mat[4][4]; invert_m4_m4(tmp_mat, ob->obmat); @@ -1260,11 +1263,11 @@ static void surfacedeformModifier_do(ModifierData *md, /* Poly count checks */ if (smd->numverts != numverts) { - modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts); + BKE_modifier_set_error(md, "Verts changed from %u to %u", smd->numverts, numverts); return; } else if (smd->numpoly != tnumpoly) { - modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); + BKE_modifier_set_error(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); return; } @@ -1395,7 +1398,10 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 1e6bc2e1819..bb88bda6394 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -103,7 +103,7 @@ static void initData(ModifierData *md) tmd->min_vertices = 4; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { TriangulateModifierData *tmd = (TriangulateModifierData *)md; Mesh *result; @@ -124,13 +124,16 @@ ModifierTypeInfo modifierType_Triangulate = { eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, // requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 242f31b6434..580a065f35e 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -303,7 +303,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, return mesh; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; UVProjectModifierData *umd = (UVProjectModifierData *)md; @@ -321,13 +321,16 @@ ModifierTypeInfo modifierType_UVProject = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 6545159bdde..4ece36d82a4 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -126,7 +126,7 @@ static void uv_warp_compute(void *__restrict userdata, } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { UVWarpModifierData *umd = (UVWarpModifierData *)md; int numPolys, numLoops; @@ -253,13 +253,16 @@ ModifierTypeInfo modifierType_UVWarp = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 30d45d1fc65..458e2d0caea 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -64,7 +64,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const WarpModifierData *wmd = (const WarpModifierData *)md; WarpModifierData *twmd = (WarpModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); twmd->curfalloff = BKE_curvemapping_copy(wmd->curfalloff); } @@ -393,7 +393,7 @@ ModifierTypeInfo modifierType_Warp = { /* structName */ "WarpModifierData", /* structSize */ sizeof(WarpModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -401,7 +401,10 @@ ModifierTypeInfo modifierType_Warp = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index fd481018cc2..fc4b65a7e5c 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -365,16 +365,19 @@ ModifierTypeInfo modifierType_Wave = { /* structName */ "WaveModifierData", /* structSize */ sizeof(WaveModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 04b503e588b..3baf7c878dc 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -546,7 +546,7 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD apply_weights_vertex_normal(wnmd, wn_data); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md; Object *ob = ctx->object; @@ -562,7 +562,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - modifier_setError((ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error((ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } @@ -708,13 +708,16 @@ ModifierTypeInfo modifierType_WeightedNormal = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index 633bbb1421b..5dae6bb8505 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.h b/source/blender/modifiers/intern/MOD_weightvg_util.h index 6a43ac69fe9..09a6a1afb3e 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.h +++ b/source/blender/modifiers/intern/MOD_weightvg_util.h @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 006191e29fc..1ff8dfbdcca 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. @@ -80,7 +80,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md; WeightVGEditModifierData *twmd = (WeightVGEditModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); twmd->cmap_curve = BKE_curvemapping_copy(wmd->cmap_curve); } @@ -164,7 +164,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (wmd->defgrp_name[0] == '\0'); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); @@ -315,7 +315,10 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index f256045f53a..f1db8502d74 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. @@ -210,7 +210,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (wmd->defgrp_name_a[0] == '\0'); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); @@ -436,13 +436,16 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 7b7aaaeb654..3e746403050 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. @@ -410,7 +410,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (wmd->proximity_ob_target == NULL); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); @@ -636,13 +636,16 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index 90b71b2d504..e21410ad63d 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -10,7 +10,7 @@ * 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, + * 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) 2005 by the Blender Foundation. @@ -1902,7 +1902,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { WeldModifierData *wmd = (WeldModifierData *)md; return weldModifier_doWeld(wmd, ctx, mesh); @@ -1938,13 +1938,16 @@ ModifierTypeInfo modifierType_Weld = { eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 04473b30585..4e2e97a2b8b 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -99,9 +99,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh * return result; } -static Mesh *applyModifier(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh) { return WireframeModifier_do((WireframeModifierData *)md, ctx->object, mesh); } @@ -113,13 +111,16 @@ ModifierTypeInfo modifierType_Wireframe = { /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index a2f825ee454..80bf0f7c5e2 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -21,8 +21,10 @@ set(INC . composite + function intern shader + simulation texture ../blenkernel ../blenlib @@ -127,6 +129,13 @@ set(SRC composite/node_composite_tree.c composite/node_composite_util.c + function/nodes/node_fn_boolean_math.cc + function/nodes/node_fn_combine_strings.cc + function/nodes/node_fn_float_compare.cc + function/nodes/node_fn_group_instance_id.cc + function/nodes/node_fn_switch.cc + function/node_function_util.cc + shader/nodes/node_shader_add_shader.c shader/nodes/node_shader_ambient_occlusion.c shader/nodes/node_shader_attribute.c @@ -220,6 +229,22 @@ set(SRC shader/node_shader_tree.c shader/node_shader_util.c + simulation/nodes/node_sim_common.cc + simulation/nodes/node_sim_emit_particles.cc + simulation/nodes/node_sim_execute_condition.cc + simulation/nodes/node_sim_force.cc + simulation/nodes/node_sim_multi_execute.cc + simulation/nodes/node_sim_particle_attribute.cc + simulation/nodes/node_sim_particle_birth_event.cc + simulation/nodes/node_sim_particle_mesh_collision_event.cc + simulation/nodes/node_sim_particle_mesh_emitter.cc + simulation/nodes/node_sim_particle_simulation.cc + simulation/nodes/node_sim_particle_time_step_event.cc + simulation/nodes/node_sim_set_particle_attribute.cc + simulation/nodes/node_sim_simulation_time.cc + simulation/node_simulation_tree.cc + simulation/node_simulation_util.cc + texture/nodes/node_texture_at.c texture/nodes/node_texture_bricks.c texture/nodes/node_texture_checker.c @@ -252,12 +277,16 @@ set(SRC intern/node_util.c composite/node_composite_util.h + function/node_function_util.h shader/node_shader_util.h + simulation/node_simulation_util.h texture/node_texture_util.h NOD_common.h NOD_composite.h + NOD_function.h NOD_shader.h + NOD_simulation.h NOD_socket.h NOD_static_types.h NOD_texture.h diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h index 26c78eab4ec..dcc4f4d0b76 100644 --- a/source/blender/nodes/NOD_common.h +++ b/source/blender/nodes/NOD_common.h @@ -26,6 +26,10 @@ #include "BKE_node.h" +#ifdef __cplusplus +extern "C" { +#endif + void register_node_type_frame(void); void register_node_type_reroute(void); @@ -42,4 +46,8 @@ struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char void node_group_input_update(struct bNodeTree *ntree, struct bNode *node); void node_group_output_update(struct bNodeTree *ntree, struct bNode *node); +#ifdef __cplusplus +} +#endif + #endif /* __NOD_COMMON_H__ */ diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h new file mode 100644 index 00000000000..377ae8bfb84 --- /dev/null +++ b/source/blender/nodes/NOD_function.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef __NOD_FUNCTION_H__ +#define __NOD_FUNCTION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void register_node_type_fn_boolean_math(void); +void register_node_type_fn_float_compare(void); +void register_node_type_fn_switch(void); +void register_node_type_fn_group_instance_id(void); +void register_node_type_fn_combine_strings(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __NOD_FUNCTION_H__ */ diff --git a/source/blender/nodes/NOD_simulation.h b/source/blender/nodes/NOD_simulation.h new file mode 100644 index 00000000000..2947d38fe83 --- /dev/null +++ b/source/blender/nodes/NOD_simulation.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef __NOD_SIMULATION_H__ +#define __NOD_SIMULATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct bNodeTreeType *ntreeType_Simulation; + +void register_node_tree_type_sim(void); + +void register_node_type_sim_group(void); + +void register_node_type_sim_particle_simulation(void); +void register_node_type_sim_force(void); +void register_node_type_sim_set_particle_attribute(void); +void register_node_type_sim_particle_birth_event(void); +void register_node_type_sim_particle_time_step_event(void); +void register_node_type_sim_execute_condition(void); +void register_node_type_sim_multi_execute(void); +void register_node_type_sim_particle_mesh_emitter(void); +void register_node_type_sim_particle_mesh_collision_event(void); +void register_node_type_sim_emit_particles(void); +void register_node_type_sim_time(void); +void register_node_type_sim_particle_attribute(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __NOD_SIMULATION_H__ */ diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 7fec3324aab..91aa11566d3 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -258,6 +258,26 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NO DefNode(TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" ) DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" ) +DefNode(SimulationNode, SIM_NODE_PARTICLE_SIMULATION, 0, "PARTICLE_SIMULATION", ParticleSimulation, "Particle Simulation", "") +DefNode(SimulationNode, SIM_NODE_FORCE, 0, "FORCE", Force, "Force", "") +DefNode(SimulationNode, SIM_NODE_SET_PARTICLE_ATTRIBUTE, def_sim_set_particle_attribute, "SET_PARTICLE_ATTRIBUTE", SetParticleAttribute, "Set Particle Attribute", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_BIRTH_EVENT, 0, "PARTICLE_BIRTH_EVENT", ParticleBirthEvent, "Particle Birth Event", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_TIME_STEP_EVENT, def_sim_particle_time_step_event, "PARTICLE_TIME_STEP_EVENT", ParticleTimeStepEvent, "Particle Time Step Event", "") +DefNode(SimulationNode, SIM_NODE_EXECUTE_CONDITION, 0, "EXECUTE_CONDITION", ExecuteCondition, "Execute Condition", "") +DefNode(SimulationNode, SIM_NODE_MULTI_EXECUTE, 0, "MULTI_EXECUTE", MultiExecute, "Multi Execute", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_EMITTER, 0, "PARTICLE_MESH_EMITTER", ParticleMeshEmitter, "Particle Mesh Emitter", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, 0, "PARTICLE_MESH_COLLISION_EVENT", ParticleMeshCollisionEvent, "Particle Mesh Collision Event", "") +DefNode(SimulationNode, SIM_NODE_EMIT_PARTICLES, 0, "EMIT_PARTICLES", EmitParticles, "Emit Particles", "") +DefNode(SimulationNode, SIM_NODE_TIME, def_sim_time, "TIME", Time, "Time", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_ATTRIBUTE, def_sim_particle_attribute, "PARTICLE_ATTRIBUTE", ParticleAttribute, "Particle Attribute", "") + +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_SWITCH, def_fn_switch, "SWITCH", Switch, "Switch", "") +DefNode(FunctionNode, FN_NODE_GROUP_INSTANCE_ID, 0, "GROUP_INSTANCE_ID", GroupInstanceID, "Group Instance ID", "") +DefNode(FunctionNode, FN_NODE_COMBINE_STRINGS, 0, "COMBINE_STRINGS", CombineStrings, "Combine Strings", "") + + /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/function/node_function_util.cc b/source/blender/nodes/function/node_function_util.cc new file mode 100644 index 00000000000..0927ba335fe --- /dev/null +++ b/source/blender/nodes/function/node_function_util.cc @@ -0,0 +1,30 @@ +/* + * 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_function_util.h" +#include "node_util.h" + +bool fn_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + /* Function nodes are only supported in simulation node trees so far. */ + return STREQ(ntree->idname, "SimulationNodeTree"); +} + +void fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + node_type_base(ntype, type, name, nclass, flag); + ntype->poll = fn_node_poll_default; +} diff --git a/source/blender/nodes/function/node_function_util.h b/source/blender/nodes/function/node_function_util.h new file mode 100644 index 00000000000..85e252f9bdd --- /dev/null +++ b/source/blender/nodes/function/node_function_util.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#ifndef __NODE_FUNCTION_UTIL_H__ +#define __NODE_FUNCTION_UTIL_H__ + +#include <string.h> + +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_node_types.h" + +#include "BKE_node.h" + +#include "BLT_translation.h" + +#include "NOD_function.h" + +#include "node_util.h" + +void fn_node_type_base( + struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +bool fn_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); + +#endif /* __NODE_FUNCTION_UTIL_H__ */ diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc new file mode 100644 index 00000000000..615ad4c6733 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc @@ -0,0 +1,62 @@ +/* + * 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_listbase.h" +#include "BLI_string.h" + +#include "RNA_enum_types.h" + +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_boolean_math_in[] = { + {SOCK_BOOLEAN, N_("Boolean")}, + {SOCK_BOOLEAN, N_("Boolean")}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_boolean_math_out[] = { + {SOCK_BOOLEAN, N_("Boolean")}, + {-1, ""}, +}; + +static void node_boolean_math_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + + nodeSetSocketAvailability(sockB, + ELEM(node->custom1, NODE_BOOLEAN_MATH_AND, NODE_BOOLEAN_MATH_OR)); +} + +static void node_boolean_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) +{ + const char *name; + bool enum_label = RNA_enum_name(rna_enum_node_boolean_math_items, node->custom1, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); +} + +void register_node_type_fn_boolean_math() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_BOOLEAN_MATH, "Boolean Math", 0, 0); + node_type_socket_templates(&ntype, fn_node_boolean_math_in, fn_node_boolean_math_out); + node_type_label(&ntype, node_boolean_math_label); + node_type_update(&ntype, node_boolean_math_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_combine_strings.cc b/source/blender/nodes/function/nodes/node_fn_combine_strings.cc new file mode 100644 index 00000000000..1b6091451d9 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_combine_strings.cc @@ -0,0 +1,21 @@ +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_combine_strings_in[] = { + {SOCK_STRING, N_("A")}, + {SOCK_STRING, N_("B")}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_combine_strings_out[] = { + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +void register_node_type_fn_combine_strings() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_COMBINE_STRINGS, "Combine Strings", 0, 0); + node_type_socket_templates(&ntype, fn_node_combine_strings_in, fn_node_combine_strings_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_float_compare.cc b/source/blender/nodes/function/nodes/node_fn_float_compare.cc new file mode 100644 index 00000000000..9788402850b --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_float_compare.cc @@ -0,0 +1,66 @@ +/* + * 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_listbase.h" +#include "BLI_string.h" + +#include "RNA_enum_types.h" + +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_float_compare_in[] = { + {SOCK_FLOAT, N_("A"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_FLOAT, N_("B"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_FLOAT, N_("Epsilon"), 0.001f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_float_compare_out[] = { + {SOCK_BOOLEAN, N_("Result")}, + {-1, ""}, +}; + +static void node_float_compare_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockEpsilon = (bNodeSocket *)BLI_findlink(&node->inputs, 2); + + nodeSetSocketAvailability( + sockEpsilon, ELEM(node->custom1, NODE_FLOAT_COMPARE_EQUAL, NODE_FLOAT_COMPARE_NOT_EQUAL)); +} + +static void node_float_compare_label(bNodeTree *UNUSED(ntree), + bNode *node, + char *label, + int maxlen) +{ + const char *name; + bool enum_label = RNA_enum_name(rna_enum_node_float_compare_items, node->custom1, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); +} + +void register_node_type_fn_float_compare() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_FLOAT_COMPARE, "Boolean Math", 0, 0); + node_type_socket_templates(&ntype, fn_node_float_compare_in, fn_node_float_compare_out); + node_type_label(&ntype, node_float_compare_label); + node_type_update(&ntype, node_float_compare_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc new file mode 100644 index 00000000000..2ac86ee2407 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc @@ -0,0 +1,15 @@ +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_group_instance_id_out[] = { + {SOCK_STRING, N_("Identifier")}, + {-1, ""}, +}; + +void register_node_type_fn_group_instance_id() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_GROUP_INSTANCE_ID, "Group Instance ID", 0, 0); + node_type_socket_templates(&ntype, nullptr, fn_node_group_instance_id_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_switch.cc b/source/blender/nodes/function/nodes/node_fn_switch.cc new file mode 100644 index 00000000000..cb721058875 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_switch.cc @@ -0,0 +1,76 @@ +/* + * 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_listbase.h" +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_switch_in[] = { + {SOCK_BOOLEAN, N_("Switch")}, + + {SOCK_FLOAT, N_("If False"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_INT, N_("If False"), 0, 0, 0, 0, -10000, 10000}, + {SOCK_BOOLEAN, N_("If False")}, + {SOCK_VECTOR, N_("If False"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_STRING, N_("If False")}, + {SOCK_RGBA, N_("If False"), 0.8f, 0.8f, 0.8f, 1.0f}, + {SOCK_OBJECT, N_("If False")}, + {SOCK_IMAGE, N_("If False")}, + + {SOCK_FLOAT, N_("If True"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_INT, N_("If True"), 0, 0, 0, 0, -10000, 10000}, + {SOCK_BOOLEAN, N_("If True")}, + {SOCK_VECTOR, N_("If True"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_STRING, N_("If True")}, + {SOCK_RGBA, N_("If True"), 0.8f, 0.8f, 0.8f, 1.0f}, + {SOCK_OBJECT, N_("If True")}, + {SOCK_IMAGE, N_("If True")}, + + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_switch_out[] = { + {SOCK_FLOAT, N_("Result")}, + {SOCK_INT, N_("Result")}, + {SOCK_BOOLEAN, N_("Result")}, + {SOCK_VECTOR, N_("Result")}, + {SOCK_STRING, N_("Result")}, + {SOCK_RGBA, N_("Result")}, + {SOCK_OBJECT, N_("Result")}, + {SOCK_IMAGE, N_("Result")}, + {-1, ""}, +}; + +static void fn_node_switch_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + int index = 0; + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + nodeSetSocketAvailability(sock, index == 0 || sock->type == node->custom1); + index++; + } + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + nodeSetSocketAvailability(sock, sock->type == node->custom1); + } +} + +void register_node_type_fn_switch() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_SWITCH, "Switch", 0, 0); + node_type_socket_templates(&ntype, fn_node_switch_in, fn_node_switch_out); + node_type_update(&ntype, fn_node_switch_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h index c3314ae3c28..7810e9f1f14 100644 --- a/source/blender/nodes/intern/node_common.h +++ b/source/blender/nodes/intern/node_common.h @@ -26,6 +26,10 @@ #include "DNA_listBase.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bNodeTree; void node_group_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); @@ -33,4 +37,8 @@ bool node_group_poll_instance(struct bNode *node, struct bNodeTree *nodetree); void ntree_update_reroute_nodes(struct bNodeTree *ntree); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 199b469781d..668dd3829cc 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -30,6 +30,7 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BKE_lib_id.h" #include "BKE_node.h" #include "RNA_access.h" @@ -259,6 +260,22 @@ void node_socket_init_default_value(bNodeSocket *sock) sock->default_value = dval; break; } + case SOCK_OBJECT: { + bNodeSocketValueObject *dval = MEM_callocN(sizeof(bNodeSocketValueObject), + "node socket value object"); + dval->value = NULL; + + sock->default_value = dval; + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *dval = MEM_callocN(sizeof(bNodeSocketValueImage), + "node socket value image"); + dval->value = NULL; + + sock->default_value = dval; + break; + } } } @@ -317,6 +334,20 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from) *toval = *fromval; break; } + case SOCK_OBJECT: { + bNodeSocketValueObject *toval = to->default_value; + bNodeSocketValueObject *fromval = from->default_value; + *toval = *fromval; + id_us_plus(&toval->value->id); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *toval = to->default_value; + bNodeSocketValueImage *fromval = from->default_value; + *toval = *fromval; + id_us_plus(&toval->value->id); + break; + } } to->flag |= (from->flag & SOCK_HIDE_VALUE); @@ -467,6 +498,19 @@ static bNodeSocketType *make_socket_type_virtual(void) return stype; } +static bNodeSocketType *make_socket_type_effector(int type) +{ + bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE); + stype->input_link_limit = 0xFFF; + return stype; +} + +static bNodeSocketType *make_socket_type_control_flow(int type) +{ + bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE); + return stype; +} + void register_standard_node_socket_types(void) { /* draw callbacks are set in drawnode.c to avoid bad-level calls */ @@ -499,5 +543,15 @@ void register_standard_node_socket_types(void) nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_OBJECT, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_IMAGE, PROP_NONE)); + + nodeRegisterSocketType(make_socket_type_effector(SOCK_EMITTERS)); + nodeRegisterSocketType(make_socket_type_effector(SOCK_EVENTS)); + nodeRegisterSocketType(make_socket_type_effector(SOCK_FORCES)); + + nodeRegisterSocketType(make_socket_type_control_flow(SOCK_CONTROL_FLOW)); + nodeRegisterSocketType(make_socket_type_virtual()); } diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index a7f09d24a70..61f8fe6809d 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -38,6 +38,10 @@ #include "RNA_access.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bNode; struct bNodeTree; @@ -103,4 +107,8 @@ void node_socket_set_vector(struct bNodeTree *ntree, struct bNodeSocket *sock, const float *value); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 93d03720058..4464a61c48c 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -32,6 +32,11 @@ bool sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) return STREQ(ntree->idname, "ShaderNodeTree"); } +static bool sh_fn_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + return STREQ(ntree->idname, "ShaderNodeTree") || STREQ(ntree->idname, "SimulationNodeTree"); +} + void sh_node_type_base( struct bNodeType *ntype, int type, const char *name, short nclass, short flag) { @@ -42,6 +47,12 @@ void sh_node_type_base( ntype->update_internal_links = node_update_internal_links_default; } +void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + sh_node_type_base(ntype, type, name, nclass, flag); + ntype->poll = sh_fn_poll_default; +} + /* ****** */ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index 8d525c8f23c..8834de0633e 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -72,6 +72,8 @@ bool sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); void sh_node_type_base( struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +void sh_fn_node_type_base( + struct bNodeType *ntype, int type, const char *name, short nclass, short flag); /* ********* exec data struct, remains internal *********** */ diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c index d8f560277f2..cc1968cb1b1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_brightness.c +++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c @@ -46,7 +46,7 @@ void register_node_type_sh_brightcontrast(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_brightcontrast_in, sh_node_brightcontrast_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.c b/source/blender/nodes/shader/nodes/node_shader_clamp.c index c49cfcea8d3..808f9686f0a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_clamp.c +++ b/source/blender/nodes/shader/nodes/node_shader_clamp.c @@ -54,7 +54,7 @@ void register_node_type_sh_clamp(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_clamp_in, sh_node_clamp_out); node_type_init(&ntype, node_shader_init_clamp); node_type_gpu(&ntype, gpu_shader_clamp); diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c index b48838e5f56..747979522d1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_gamma.c +++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c @@ -62,7 +62,7 @@ void register_node_type_sh_gamma(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c index 7a05fc95eec..57ef51c65f6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c @@ -89,7 +89,7 @@ void register_node_type_sh_hue_sat(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out); node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); node_type_exec(&ntype, NULL, NULL, node_shader_exec_hue_sat); diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c index 0d6709a1968..19fa0b0309d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_invert.c +++ b/source/blender/nodes/shader/nodes/node_shader_invert.c @@ -69,7 +69,7 @@ void register_node_type_sh_invert(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_invert); node_type_gpu(&ntype, gpu_shader_invert); diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.c b/source/blender/nodes/shader/nodes/node_shader_map_range.c index d59540cb8fa..5db7983e752 100644 --- a/source/blender/nodes/shader/nodes/node_shader_map_range.c +++ b/source/blender/nodes/shader/nodes/node_shader_map_range.c @@ -81,7 +81,7 @@ void register_node_type_sh_map_range(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_map_range_in, sh_node_map_range_out); node_type_init(&ntype, node_shader_init_map_range); node_type_update(&ntype, node_shader_update_map_range); diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 08578e0e11e..8abebbf5081 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -105,7 +105,7 @@ void register_node_type_sh_math(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out); node_type_label(&ntype, node_math_label); node_type_gpu(&ntype, gpu_shader_math); diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c index 9c318073304..93e88664d1a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c @@ -107,7 +107,7 @@ void register_node_type_sh_mix_rgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_mix_rgb_in, sh_node_mix_rgb_out); node_type_label(&ntype, node_blend_label); node_type_exec(&ntype, NULL, NULL, node_shader_exec_mix_rgb); diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c index 951755be4f3..2c9b77530a2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c @@ -61,7 +61,7 @@ void register_node_type_sh_sephsv(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_sephsv_in, sh_node_sephsv_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_sephsv); node_type_gpu(&ntype, gpu_shader_sephsv); @@ -109,7 +109,7 @@ void register_node_type_sh_combhsv(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_combhsv_in, sh_node_combhsv_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_combhsv); node_type_gpu(&ntype, gpu_shader_combhsv); diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c index f10f80d5c2d..d0dc45dcedd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c @@ -63,7 +63,7 @@ void register_node_type_sh_seprgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_seprgb); node_type_gpu(&ntype, gpu_shader_seprgb); @@ -113,7 +113,7 @@ void register_node_type_sh_combrgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_combrgb); node_type_gpu(&ntype, gpu_shader_combrgb); diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c index 55d5084b132..429b1a3e818 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c @@ -48,7 +48,7 @@ void register_node_type_sh_sepxyz(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_sepxyz_in, sh_node_sepxyz_out); node_type_gpu(&ntype, gpu_shader_sepxyz); @@ -80,7 +80,7 @@ void register_node_type_sh_combxyz(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_combxyz_in, sh_node_combxyz_out); node_type_gpu(&ntype, gpu_shader_combxyz); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c index fa98f9efb74..420c5b75926 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c @@ -137,6 +137,9 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod nodeSetSocketAvailability(inGainSock, tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); + + bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac"); + node_sock_label(outFacSock, "Height"); } void register_node_type_sh_tex_musgrave(void) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c index 7b67c2d1f2e..67268c102c5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c @@ -91,7 +91,7 @@ void register_node_type_sh_tex_noise(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0); node_type_socket_templates(&ntype, sh_node_tex_noise_in, sh_node_tex_noise_out); node_type_init(&ntype, node_shader_init_tex_noise); node_type_storage( diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c index 1789dc44bf1..817ccdc8b6a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c @@ -72,7 +72,8 @@ void register_node_type_sh_tex_white_noise(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0); + sh_fn_node_type_base( + &ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0); node_type_socket_templates(&ntype, sh_node_tex_white_noise_in, sh_node_tex_white_noise_out); node_type_init(&ntype, node_shader_init_tex_white_noise); node_type_gpu(&ntype, gpu_shader_tex_white_noise); diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c index 49f9befdce3..20f280d00c3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c @@ -125,7 +125,7 @@ void register_node_type_sh_valtorgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out); node_type_init(&ntype, node_shader_init_valtorgb); node_type_size_preset(&ntype, NODE_SIZE_LARGE); diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.c b/source/blender/nodes/shader/nodes/node_shader_vector_math.c index 3a6e273eb20..b719fe03d9b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.c @@ -134,7 +134,7 @@ void register_node_type_sh_vect_math(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out); node_type_label(&ntype, node_vector_math_label); node_type_gpu(&ntype, gpu_shader_vector_math); diff --git a/source/blender/nodes/simulation/node_simulation_tree.cc b/source/blender/nodes/simulation/node_simulation_tree.cc new file mode 100644 index 00000000000..3f0e70259d6 --- /dev/null +++ b/source/blender/nodes/simulation/node_simulation_tree.cc @@ -0,0 +1,45 @@ +/* + * 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 <string.h> + +#include "MEM_guardedalloc.h" + +#include "NOD_simulation.h" + +#include "BKE_node.h" + +#include "BLT_translation.h" + +#include "DNA_node_types.h" + +#include "RNA_access.h" + +bNodeTreeType *ntreeType_Simulation; + +void register_node_tree_type_sim(void) +{ + bNodeTreeType *tt = ntreeType_Simulation = (bNodeTreeType *)MEM_callocN( + sizeof(bNodeTreeType), "simulation node tree type"); + tt->type = NTREE_SIMULATION; + strcpy(tt->idname, "SimulationNodeTree"); + strcpy(tt->ui_name, N_("Simulation Editor")); + tt->ui_icon = 0; /* defined in drawnode.c */ + strcpy(tt->ui_description, N_("Simulation nodes")); + tt->rna_ext.srna = &RNA_SimulationNodeTree; + + ntreeTypeAdd(tt); +} diff --git a/source/blender/nodes/simulation/node_simulation_util.cc b/source/blender/nodes/simulation/node_simulation_util.cc new file mode 100644 index 00000000000..ae875335da8 --- /dev/null +++ b/source/blender/nodes/simulation/node_simulation_util.cc @@ -0,0 +1,29 @@ +/* + * 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_simulation_util.h" +#include "node_util.h" + +bool sim_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + return STREQ(ntree->idname, "SimulationNodeTree"); +} + +void sim_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + node_type_base(ntype, type, name, nclass, flag); + ntype->poll = sim_node_poll_default; +} diff --git a/source/blender/nodes/simulation/node_simulation_util.h b/source/blender/nodes/simulation/node_simulation_util.h new file mode 100644 index 00000000000..adbe2ad5e8f --- /dev/null +++ b/source/blender/nodes/simulation/node_simulation_util.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#ifndef __NODE_SIM_UTIL_H__ +#define __NODE_SIM_UTIL_H__ + +#include <string.h> + +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_node_types.h" + +#include "BKE_node.h" + +#include "BLT_translation.h" + +#include "NOD_simulation.h" + +#include "node_util.h" + +void sim_node_type_base( + struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +bool sim_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); + +#endif /* __NODE_SIM_UTIL_H__ */ diff --git a/source/blender/nodes/simulation/nodes/node_sim_common.cc b/source/blender/nodes/simulation/nodes/node_sim_common.cc new file mode 100644 index 00000000000..fbc03905d4f --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_common.cc @@ -0,0 +1,45 @@ +/* + * 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_node.h" + +#include "NOD_simulation.h" + +#include "NOD_common.h" +#include "node_common.h" +#include "node_simulation_util.h" + +void register_node_type_sim_group(void) +{ + static bNodeType ntype; + + node_type_base_custom(&ntype, "SimulationNodeGroup", "Group", 0, 0); + ntype.type = NODE_GROUP; + ntype.poll = sim_node_poll_default; + ntype.poll_instance = node_group_poll_instance; + ntype.insert_link = node_insert_link_default; + ntype.update_internal_links = node_update_internal_links_default; + ntype.rna_ext.srna = RNA_struct_find("SimulationNodeGroup"); + BLI_assert(ntype.rna_ext.srna != NULL); + RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype); + + node_type_socket_templates(&ntype, NULL, NULL); + node_type_size(&ntype, 140, 60, 400); + node_type_label(&ntype, node_group_label); + node_type_group_update(&ntype, node_group_update); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc b/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc new file mode 100644 index 00000000000..e23984dbf34 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc @@ -0,0 +1,38 @@ +/* + * 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_simulation_util.h" + +static bNodeSocketTemplate sim_node_emit_particle_in[] = { + {SOCK_INT, N_("Amount"), 10, 0, 0, 0, 0, 10000000}, + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_emit_particle_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {SOCK_EMITTERS, N_("Emitter")}, + {-1, ""}, +}; + +void register_node_type_sim_emit_particles() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_EMIT_PARTICLES, "Emit Particles", 0, 0); + node_type_socket_templates(&ntype, sim_node_emit_particle_in, sim_node_emit_particle_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc b/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc new file mode 100644 index 00000000000..69f30d1ad0d --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc @@ -0,0 +1,39 @@ +/* + * 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_simulation_util.h" + +static bNodeSocketTemplate sim_node_execute_condition_in[] = { + {SOCK_BOOLEAN, N_("Condition")}, + {SOCK_CONTROL_FLOW, N_("If True")}, + {SOCK_CONTROL_FLOW, N_("If False")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_execute_condition_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +void register_node_type_sim_execute_condition() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_EXECUTE_CONDITION, "Execute Condition", 0, 0); + node_type_socket_templates( + &ntype, sim_node_execute_condition_in, sim_node_execute_condition_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_force.cc b/source/blender/nodes/simulation/nodes/node_sim_force.cc new file mode 100644 index 00000000000..eccd2e4e2ab --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_force.cc @@ -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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_force_in[] = { + {SOCK_VECTOR, N_("Force"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_force_out[] = { + {SOCK_FORCES, N_("Force")}, + {-1, ""}, +}; + +void register_node_type_sim_force() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_FORCE, "Force", 0, 0); + node_type_socket_templates(&ntype, sim_node_force_in, sim_node_force_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc b/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc new file mode 100644 index 00000000000..5944db7e2bc --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc @@ -0,0 +1,38 @@ +/* + * 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_simulation_util.h" + +static bNodeSocketTemplate sim_node_multi_execute_in[] = { + {SOCK_CONTROL_FLOW, "1"}, + {SOCK_CONTROL_FLOW, "2"}, + {SOCK_CONTROL_FLOW, "3"}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_multi_execute_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +void register_node_type_sim_multi_execute() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_MULTI_EXECUTE, "Multi Execute", 0, 0); + node_type_socket_templates(&ntype, sim_node_multi_execute_in, sim_node_multi_execute_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc new file mode 100644 index 00000000000..b6b67ee334e --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc @@ -0,0 +1,52 @@ +/* + * 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_listbase.h" +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_attribute_in[] = { + {SOCK_STRING, N_("Name")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_attribute_out[] = { + {SOCK_FLOAT, N_("Float")}, + {SOCK_INT, N_("Int")}, + {SOCK_BOOLEAN, N_("Boolean")}, + {SOCK_VECTOR, N_("Vector")}, + {SOCK_RGBA, N_("Color")}, + {SOCK_OBJECT, N_("Object")}, + {SOCK_IMAGE, N_("Image")}, + {-1, ""}, +}; + +static void sim_node_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + nodeSetSocketAvailability(sock, sock->type == node->custom1); + } +} + +void register_node_type_sim_particle_attribute() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_ATTRIBUTE, "Particle Attribute", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_attribute_in, sim_node_particle_attribute_out); + node_type_update(&ntype, sim_node_particle_attribute_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc new file mode 100644 index 00000000000..8332a3ecd9f --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc @@ -0,0 +1,37 @@ +/* + * 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_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_birth_event_in[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_birth_event_out[] = { + {SOCK_EVENTS, N_("Event")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_birth_event() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_BIRTH_EVENT, "Particle Birth Event", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_birth_event_in, sim_node_particle_birth_event_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc new file mode 100644 index 00000000000..48671172136 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc @@ -0,0 +1,40 @@ +/* + * 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_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_mesh_collision_event_in[] = { + {SOCK_OBJECT, N_("Object")}, + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_mesh_collision_event_out[] = { + {SOCK_EVENTS, N_("Event")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_mesh_collision_event() +{ + static bNodeType ntype; + + sim_node_type_base( + &ntype, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, "Particle Mesh Collision Event", 0, 0); + node_type_socket_templates(&ntype, + sim_node_particle_mesh_collision_event_in, + sim_node_particle_mesh_collision_event_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc new file mode 100644 index 00000000000..2de7be2d3eb --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc @@ -0,0 +1,40 @@ +/* + * 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_simulation_util.h" + +#include "float.h" + +static bNodeSocketTemplate sim_node_particle_mesh_emitter_in[] = { + {SOCK_OBJECT, N_("Object")}, + {SOCK_FLOAT, N_("Rate"), 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_mesh_emitter_out[] = { + {SOCK_EMITTERS, N_("Emitter")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_mesh_emitter() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_MESH_EMITTER, "Mesh Emitter", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_mesh_emitter_in, sim_node_particle_mesh_emitter_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc new file mode 100644 index 00000000000..159c9b23da1 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc @@ -0,0 +1,39 @@ +/* + * 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_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_simulation_in[] = { + {SOCK_EMITTERS, N_("Emitters")}, + {SOCK_EVENTS, N_("Events")}, + {SOCK_FORCES, N_("Forces")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_simulation_out[] = { + {-1, ""}, +}; + +void register_node_type_sim_particle_simulation() +{ + static bNodeType ntype; + + sim_node_type_base( + &ntype, SIM_NODE_PARTICLE_SIMULATION, "Particle Simulation", NODE_CLASS_OUTPUT, 0); + node_type_socket_templates( + &ntype, sim_node_particle_simulation_in, sim_node_particle_simulation_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc new file mode 100644 index 00000000000..cda8ddeb644 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc @@ -0,0 +1,37 @@ +/* + * 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_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_time_step_event_in[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_time_step_event_out[] = { + {SOCK_EVENTS, N_("Event")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_time_step_event() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_TIME_STEP_EVENT, "Particle Time Step Event", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_time_step_event_in, sim_node_particle_time_step_event_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc new file mode 100644 index 00000000000..8696dbe340c --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc @@ -0,0 +1,57 @@ +/* + * 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_listbase.h" +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_set_particle_attribute_in[] = { + {SOCK_STRING, N_("Name")}, + {SOCK_FLOAT, N_("Float"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_INT, N_("Int"), 0, 0, 0, 0, -10000, 10000}, + {SOCK_BOOLEAN, N_("Boolean")}, + {SOCK_VECTOR, N_("Vector")}, + {SOCK_RGBA, N_("Color")}, + {SOCK_OBJECT, N_("Object")}, + {SOCK_IMAGE, N_("Image")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_set_particle_attribute_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static void sim_node_set_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + int index = 0; + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + if (index >= 1) { + nodeSetSocketAvailability(sock, sock->type == node->custom1); + } + index++; + } +} + +void register_node_type_sim_set_particle_attribute() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_SET_PARTICLE_ATTRIBUTE, "Set Particle Attribute", 0, 0); + node_type_socket_templates( + &ntype, sim_node_set_particle_attribute_in, sim_node_set_particle_attribute_out); + node_type_update(&ntype, sim_node_set_particle_attribute_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc b/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc new file mode 100644 index 00000000000..40e1c43fb69 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_simulation_time.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_simulation_util.h" + +static bNodeSocketTemplate sim_node_time_out[] = { + {SOCK_FLOAT, N_("Time")}, + {-1, ""}, +}; + +void register_node_type_sim_time() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_TIME, "Time", 0, 0); + node_type_socket_templates(&ntype, nullptr, sim_node_time_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 31f67cb1ffa..b3d595cc69b 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -282,7 +282,7 @@ int ntreeTexExecTree(bNodeTree *nodes, float dyt[3], int osatex, const short thread, - Tex *UNUSED(tex), + const Tex *UNUSED(tex), short which_output, int cfra, int preview, diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 76f0f8c8b55..6a951519730 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -23,7 +23,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_cloth_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -38,7 +37,6 @@ extern "C" { #include "BKE_cloth.h" #include "BKE_collision.h" #include "BKE_effect.h" -} #include "BPH_mass_spring.h" #include "implicit.h" diff --git a/source/blender/physics/intern/hair_volume.cpp b/source/blender/physics/intern/hair_volume.cpp index b8783c51fe8..6246bf54f75 100644 --- a/source/blender/physics/intern/hair_volume.cpp +++ b/source/blender/physics/intern/hair_volume.cpp @@ -23,14 +23,12 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_math.h" #include "BLI_utildefines.h" #include "DNA_texture_types.h" #include "BKE_effect.h" -} #include "eigen_utils.h" #include "implicit.h" diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index d4e57f0beb6..18d4c7da534 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -35,12 +35,12 @@ struct bContext; struct bContextDataResult; struct bPythonConstraint; /* DNA_constraint_types.h */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets); diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 726599ff06e..50ae05694eb 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -33,7 +33,7 @@ #include "BLI_math_base.h" #include "BLI_string.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c index a8d8252b231..9240e34bbab 100644 --- a/source/blender/python/intern/bpy_rna_driver.c +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -26,7 +26,7 @@ #include "BLI_utildefines.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "RNA_access.h" diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 6ea0dd52ed7..ace7480ee81 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -930,7 +930,7 @@ PyDoc_STRVAR(Vector_dot_doc, " :arg other: The other vector to perform the dot product with.\n" " :type other: :class:`Vector`\n" " :return: The dot product.\n" - " :rtype: :class:`Vector`\n"); + " :rtype: float\n"); static PyObject *Vector_dot(VectorObject *self, PyObject *value) { float *tvec; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 54296e16834..b963021dfd9 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -40,6 +40,10 @@ struct StampData; struct ViewLayer; struct bMovieHandle; +#ifdef __cplusplus +extern "C" { +#endif + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -386,4 +390,8 @@ struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char * RenderResult *RE_DuplicateRenderResult(RenderResult *rr); +#ifdef __cplusplus +} +#endif + #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index bca3b749192..bdf81354b8d 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -33,18 +33,16 @@ struct ImagePool; struct MTex; /* render_texture.c */ -/* used by particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ -int externtex(const struct MTex *mtex, - const float vec[3], - float *tin, - float *tr, - float *tg, - float *tb, - float *ta, - const int thread, - struct ImagePool *pool, - const bool skip_load_image, - const bool texnode_preview); +bool RE_texture_evaluate(const struct MTex *mtex, + const float vec[3], + const int thread, + struct ImagePool *pool, + const bool skip_load_image, + const bool texnode_preview, + /* Return arguments. */ + float *r_intensity, + float r_rgba[4]) ATTR_NONNULL(1, 2, 7, 8); + void texture_rgb_blend( float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype); float texture_value_blend(float tex, float out, float fact, float facg, int blendtype); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 792b2b7e071..f69ae4dfd5c 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -23,6 +23,10 @@ #ifndef __RE_SHADER_EXT_H__ #define __RE_SHADER_EXT_H__ +#ifdef __cplusplus +extern "C" { +#endif + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is for texture exports */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -75,4 +79,8 @@ int multitex_nodes(struct Tex *tex, struct MTex *mtex, struct ImagePool *pool); +#ifdef __cplusplus +} +#endif + #endif /* __RE_SHADER_EXT_H__ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index f7901ebb7d0..77a482f8546 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2514,7 +2514,7 @@ void RE_RenderAnim(Render *re, { float ctime = BKE_scene_frame_get(scene); AnimData *adt = BKE_animdata_from_id(&scene->id); - BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, ADT_RECALC_ALL, false); + BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, ADT_RECALC_ALL, false); } render_update_depsgraph(re); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index eabba94ef29..ee484924bf9 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -79,7 +79,7 @@ void RE_texture_rng_exit(void) /* ------------------------------------------------------------------------- */ /* this allows colorbanded textures to control normals as well */ -static void tex_normal_derivate(Tex *tex, TexResult *texres) +static void tex_normal_derivate(const Tex *tex, TexResult *texres) { if (tex->flag & TEX_COLORBAND) { float col[4]; @@ -106,7 +106,7 @@ static void tex_normal_derivate(Tex *tex, TexResult *texres) texres->nor[2] = texres->tin - texres->nor[2]; } -static int blend(Tex *tex, const float texvec[3], TexResult *texres) +static int blend(const Tex *tex, const float texvec[3], TexResult *texres) { float x, y, t; @@ -170,7 +170,7 @@ static int blend(Tex *tex, const float texvec[3], TexResult *texres) /* newnoise: all noisebased types now have different noisebases to choose from */ -static int clouds(Tex *tex, const float texvec[3], TexResult *texres) +static int clouds(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -271,7 +271,7 @@ static float tex_tri(float a) } /* computes basic wood intensity value at x,y,z */ -static float wood_int(Tex *tex, float x, float y, float z) +static float wood_int(const Tex *tex, float x, float y, float z) { float wi = 0; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */ @@ -308,7 +308,7 @@ static float wood_int(Tex *tex, float x, float y, float z) return wi; } -static int wood(Tex *tex, const float texvec[3], TexResult *texres) +static int wood(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -329,7 +329,7 @@ static int wood(Tex *tex, const float texvec[3], TexResult *texres) } /* computes basic marble intensity at x,y,z */ -static float marble_int(Tex *tex, float x, float y, float z) +static float marble_int(const Tex *tex, float x, float y, float z) { float n, mi; short wf = tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */ @@ -367,7 +367,7 @@ static float marble_int(Tex *tex, float x, float y, float z) return mi; } -static int marble(Tex *tex, const float texvec[3], TexResult *texres) +static int marble(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -391,7 +391,7 @@ static int marble(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ -static int magic(Tex *tex, const float texvec[3], TexResult *texres) +static int magic(const Tex *tex, const float texvec[3], TexResult *texres) { float x, y, z, turb; int n; @@ -467,7 +467,7 @@ static int magic(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ /* newnoise: stucci also modified to use different noisebasis */ -static int stucci(Tex *tex, const float texvec[3], TexResult *texres) +static int stucci(const Tex *tex, const float texvec[3], TexResult *texres) { float nor[3], b2, ofs; int retval = TEX_INT; @@ -533,7 +533,7 @@ static int stucci(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ /* newnoise: musgrave terrain noise types */ -static float mg_mFractalOrfBmTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_mFractalOrfBmTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float (*mgravefunc)(float, float, float, float, float, float, int); @@ -588,7 +588,7 @@ static float mg_mFractalOrfBmTex(Tex *tex, const float texvec[3], TexResult *tex return rv; } -static float mg_ridgedOrHybridMFTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_ridgedOrHybridMFTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float (*mgravefunc)(float, float, float, float, float, float, float, float, int); @@ -651,7 +651,7 @@ static float mg_ridgedOrHybridMFTex(Tex *tex, const float texvec[3], TexResult * return rv; } -static float mg_HTerrainTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_HTerrainTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -702,7 +702,7 @@ static float mg_HTerrainTex(Tex *tex, const float texvec[3], TexResult *texres) return rv; } -static float mg_distNoiseTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_distNoiseTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -747,7 +747,7 @@ static float mg_distNoiseTex(Tex *tex, const float texvec[3], TexResult *texres) * probably the slowest, especially with minkovsky, bumpmapping, could be done another way. */ -static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) +static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float da[4], pa[12]; /* distance and point coordinate arrays of 4 nearest neighbors */ @@ -761,8 +761,7 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) } voronoi(texvec[0], texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->tin = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->tin = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); if (tex->vn_coltype) { float ca[3]; /* cell color */ @@ -809,14 +808,11 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) /* calculate bumpnormal */ voronoi(texvec[0] + offs, texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[0] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->nor[0] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); voronoi(texvec[0], texvec[1] + offs, texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[1] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->nor[1] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); voronoi(texvec[0], texvec[1], texvec[2] + offs, da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[2] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->nor[2] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); tex_normal_derivate(tex, texres); rv |= TEX_NOR; @@ -835,7 +831,7 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ -static int texnoise(Tex *tex, TexResult *texres, int thread) +static int texnoise(const Tex *tex, TexResult *texres, int thread) { float div = 3.0; int val, ran, loop, shift = 29; @@ -1724,17 +1720,20 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen /* ------------------------------------------------------------------------- */ -int externtex(const MTex *mtex, - const float vec[3], - float *tin, - float *tr, - float *tg, - float *tb, - float *ta, - const int thread, - struct ImagePool *pool, - const bool skip_load_image, - const bool texnode_preview) +/** + * \param pool: Thread pool, may be NULL. + * + * \return True if the texture has color, otherwise false. + */ +bool RE_texture_evaluate(const MTex *mtex, + const float vec[3], + const int thread, + struct ImagePool *pool, + const bool skip_load_image, + const bool texnode_preview, + /* Return arguments. */ + float *r_intensity, + float r_rgba[4]) { Tex *tex; TexResult texr; @@ -1796,11 +1795,11 @@ int externtex(const MTex *mtex, texr.tb = mtex->b; } - *tin = texr.tin; - *tr = texr.tr; - *tg = texr.tg; - *tb = texr.tb; - *ta = texr.ta; + *r_intensity = texr.tin; + r_rgba[0] = texr.tr; + r_rgba[1] = texr.tg; + r_rgba[2] = texr.tb; + r_rgba[3] = texr.ta; return (rgb != 0); } diff --git a/source/blender/shader_fx/intern/FX_shader_blur.c b/source/blender/shader_fx/intern/FX_shader_blur.c index e98205897aa..8881f147af8 100644 --- a/source/blender/shader_fx/intern/FX_shader_blur.c +++ b/source/blender/shader_fx/intern/FX_shader_blur.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -38,7 +38,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Blur = { diff --git a/source/blender/shader_fx/intern/FX_shader_colorize.c b/source/blender/shader_fx/intern/FX_shader_colorize.c index 7438fbf7fa7..5fea2cd0ff8 100644 --- a/source/blender/shader_fx/intern/FX_shader_colorize.c +++ b/source/blender/shader_fx/intern/FX_shader_colorize.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -40,7 +40,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Colorize = { diff --git a/source/blender/shader_fx/intern/FX_shader_flip.c b/source/blender/shader_fx/intern/FX_shader_flip.c index ddf4d201ca7..b915fb8e591 100644 --- a/source/blender/shader_fx/intern/FX_shader_flip.c +++ b/source/blender/shader_fx/intern/FX_shader_flip.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -39,7 +39,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Flip = { diff --git a/source/blender/shader_fx/intern/FX_shader_glow.c b/source/blender/shader_fx/intern/FX_shader_glow.c index a81e69e00a1..1194e95ce79 100644 --- a/source/blender/shader_fx/intern/FX_shader_glow.c +++ b/source/blender/shader_fx/intern/FX_shader_glow.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -47,7 +47,7 @@ static void initData(ShaderFxData *md) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Glow = { diff --git a/source/blender/shader_fx/intern/FX_shader_light.c b/source/blender/shader_fx/intern/FX_shader_light.c index c81d959ebe0..17d2f518d44 100644 --- a/source/blender/shader_fx/intern/FX_shader_light.c +++ b/source/blender/shader_fx/intern/FX_shader_light.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -48,7 +48,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } static void updateDepsgraph(ShaderFxData *md, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/shader_fx/intern/FX_shader_pixel.c b/source/blender/shader_fx/intern/FX_shader_pixel.c index f39649bba07..04bf9ae5b6d 100644 --- a/source/blender/shader_fx/intern/FX_shader_pixel.c +++ b/source/blender/shader_fx/intern/FX_shader_pixel.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -36,7 +36,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Pixel = { diff --git a/source/blender/shader_fx/intern/FX_shader_rim.c b/source/blender/shader_fx/intern/FX_shader_rim.c index a81d2ff2a09..16c6a6716a0 100644 --- a/source/blender/shader_fx/intern/FX_shader_rim.c +++ b/source/blender/shader_fx/intern/FX_shader_rim.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -43,7 +43,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Rim = { diff --git a/source/blender/shader_fx/intern/FX_shader_shadow.c b/source/blender/shader_fx/intern/FX_shader_shadow.c index 6887e988fc7..dcf66ec89e0 100644 --- a/source/blender/shader_fx/intern/FX_shader_shadow.c +++ b/source/blender/shader_fx/intern/FX_shader_shadow.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -59,7 +59,7 @@ static void initData(ShaderFxData *md) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } static void updateDepsgraph(ShaderFxData *fx, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/shader_fx/intern/FX_shader_swirl.c b/source/blender/shader_fx/intern/FX_shader_swirl.c index 8e1e4a5e9fe..990b43748da 100644 --- a/source/blender/shader_fx/intern/FX_shader_swirl.c +++ b/source/blender/shader_fx/intern/FX_shader_swirl.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -48,7 +48,7 @@ static void initData(ShaderFxData *md) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } static void updateDepsgraph(ShaderFxData *fx, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/shader_fx/intern/FX_shader_wave.c b/source/blender/shader_fx/intern/FX_shader_wave.c index a4ad108bc94..7dc72bcb669 100644 --- a/source/blender/shader_fx/intern/FX_shader_wave.c +++ b/source/blender/shader_fx/intern/FX_shader_wave.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -42,7 +42,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Wave = { diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 90ff7bb8f85..22fd55cd49a 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -153,8 +153,8 @@ endif() if(WITH_HEADLESS) add_definitions(-DWITH_HEADLESS) -elseif(WITH_X11) - add_definitions(-DWITH_X11) +elseif(WITH_GHOST_X11) + add_definitions(-DWITH_GHOST_X11) endif() if(WITH_PYTHON) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 2f540262a66..21a6088bfe9 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -617,7 +617,7 @@ int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, const stru void WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op); const int (*WM_gesture_lasso_path_to_array(struct bContext *C, struct wmOperator *op, - int *mcords_tot))[2]; + int *mcoords_len))[2]; int WM_gesture_straightline_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); @@ -872,6 +872,7 @@ void WM_generic_user_data_free(struct wmGenericUserData *user_data); bool WM_xr_session_exists(const wmXrData *xr); bool WM_xr_session_is_ready(const wmXrData *xr); struct wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr); +void WM_xr_session_base_pose_reset(wmXrData *xr); bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3]); bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4]); bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index c7d1c4992e3..4acce793707 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -109,10 +109,6 @@ #ifndef __WM_TYPES_H__ #define __WM_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - struct ID; struct ImBuf; struct bContext; @@ -133,6 +129,10 @@ struct wmWindowManager; /* Include external gizmo API's */ #include "gizmo/WM_gizmo_api.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct wmGenericUserData { void *data; /** When NULL, use #MEM_freeN. */ @@ -310,7 +310,7 @@ typedef struct wmNotifier { #define ND_HISTORY (4 << 16) #define ND_JOB (5 << 16) #define ND_UNDO (6 << 16) -#define ND_XR_DATA_CHANGED (7 << 17) +#define ND_XR_DATA_CHANGED (7 << 16) /* NC_SCREEN */ #define ND_LAYOUTBROWSE (1 << 16) diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 302de6609d0..63ad2e446ea 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -625,8 +625,7 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) bScreen *screen = WM_window_get_active_screen(win); /* Draw screen areas into own frame buffer. */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { CTX_wm_area_set(C, area); /* Compute UI layouts for dynamically size regions. */ @@ -741,8 +740,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) #endif /* Blit non-overlapping area regions. */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->visible && region->overlap == false) { /* Blit from offscreen buffer. */ @@ -753,8 +751,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) /* Draw paint cursors. */ if (wm->paintcursors.first) { - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->visible && region == screen->active_region) { CTX_wm_area_set(C, area); @@ -773,8 +770,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) } /* Blend in overlapping area regions */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->visible && region->overlap) { wm_draw_region_blend(region, 0, true); @@ -914,8 +910,7 @@ static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win) } } - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { for (region = area->regionbase.first; region; region = region->next) { wm_region_test_gizmo_do_draw(C, area, region, true); wm_region_test_render_do_draw(scene, depsgraph, area, region); @@ -962,8 +957,7 @@ static void wm_draw_update_clear_window(bContext *C, wmWindow *win) { bScreen *screen = WM_window_get_active_screen(win); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { wm_region_test_gizmo_do_draw(C, area, region, false); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index cb16550717b..b500370d34d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -524,8 +524,7 @@ void wm_event_do_notifiers(bContext *C) ED_region_do_listen(win, NULL, region, note, scene); } - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { ED_area_do_listen(win, area, note, scene); for (region = area->regionbase.first; region; region = region->next) { ED_region_do_listen(win, area, region, note, scene); @@ -1655,8 +1654,7 @@ static void wm_handler_op_context(bContext *C, wmEventHandler_Op *handler, const else { ScrArea *area = NULL; - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { if (area_iter == handler->context.area) { area = area_iter; break; @@ -2989,8 +2987,7 @@ static ScrArea *area_event_inside(bContext *C, const int xy[2]) bScreen *screen = CTX_wm_screen(C); if (screen) { - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { if (BLI_rcti_isect_pt_v(&area->totrct, xy)) { return area; } @@ -3189,9 +3186,9 @@ void wm_event_do_handlers(bContext *C) } if (is_playing_sound == 0) { - const float time = BKE_sound_sync_scene(scene_eval); + const double time = BKE_sound_sync_scene(scene_eval); if (isfinite(time)) { - int ncfra = time * (float)FPS + 0.5f; + int ncfra = time * FPS + 0.5; if (ncfra != scene->r.cfra) { scene->r.cfra = ncfra; ED_update_for_newframe(CTX_data_main(C), depsgraph); @@ -3287,8 +3284,7 @@ void wm_event_do_handlers(bContext *C) } #endif - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { /* after restoring a screen from SCREENMAXIMIZED we have to wait * with the screen handling till the region coordinates are updated */ if (screen->skip_handling == true) { @@ -3460,8 +3456,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) bool cancel_handler = true; /* find the area with the file selector for this handler */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { if (area->spacetype == SPACE_FILE) { SpaceFile *sfile = area->spacedata.first; @@ -4954,8 +4949,7 @@ void WM_window_cursor_keymap_status_refresh(bContext *C, wmWindow *win) } ScrArea *area = NULL; - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { if (BLI_findindex(&area_iter->regionbase, region) != -1) { area = area_iter; break; diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 71ae44297e7..9aa401722b7 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -320,24 +320,24 @@ static void draw_filled_lasso_px_cb(int x, int x_end, int y, void *user_data) static void draw_filled_lasso(wmGesture *gt) { const short *lasso = (short *)gt->customdata; - const int tot = gt->points; - int(*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__); + const int mcoords_len = gt->points; + int(*mcoords)[2] = MEM_mallocN(sizeof(*mcoords) * (mcoords_len + 1), __func__); int i; rcti rect; float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - for (i = 0; i < tot; i++, lasso += 2) { - moves[i][0] = lasso[0]; - moves[i][1] = lasso[1]; + for (i = 0; i < mcoords_len; i++, lasso += 2) { + mcoords[i][0] = lasso[0]; + mcoords[i][1] = lasso[1]; } - BLI_lasso_boundbox(&rect, (const int(*)[2])moves, tot); + BLI_lasso_boundbox(&rect, (const int(*)[2])mcoords, mcoords_len); BLI_rcti_translate(&rect, gt->winrct.xmin, gt->winrct.ymin); BLI_rcti_isect(>->winrct, &rect, &rect); BLI_rcti_translate(&rect, -gt->winrct.xmin, -gt->winrct.ymin); - /* highly unlikely this will fail, but could crash if (tot == 0) */ + /* Highly unlikely this will fail, but could crash if (mcoords_len == 0). */ if (BLI_rcti_is_empty(&rect) == false) { const int w = BLI_rcti_size_x(&rect); const int h = BLI_rcti_size_y(&rect); @@ -348,8 +348,8 @@ static void draw_filled_lasso(wmGesture *gt) rect.ymin, rect.xmax, rect.ymax, - (const int(*)[2])moves, - tot, + (const int(*)[2])mcoords, + mcoords_len, draw_filled_lasso_px_cb, &lasso_fill_data); @@ -390,7 +390,7 @@ static void draw_filled_lasso(wmGesture *gt) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - MEM_freeN(moves); + MEM_freeN(mcoords); } static void wm_gesture_draw_lasso(wmGesture *gt, bool filled) diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 11beb7d2fd5..9fb368a02b4 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -718,10 +718,10 @@ void WM_gesture_lines_cancel(bContext *C, wmOperator *op) */ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, - int *mcords_tot))[2] + int *r_mcoords_len))[2] { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path"); - int(*mcords)[2] = NULL; + int(*mcoords)[2] = NULL; BLI_assert(prop != NULL); if (prop) { @@ -729,26 +729,26 @@ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), if (len) { int i = 0; - mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__); + mcoords = MEM_mallocN(sizeof(int[2]) * len, __func__); RNA_PROP_BEGIN (op->ptr, itemptr, prop) { float loc[2]; RNA_float_get_array(&itemptr, "loc", loc); - mcords[i][0] = (int)loc[0]; - mcords[i][1] = (int)loc[1]; + mcoords[i][0] = (int)loc[0]; + mcoords[i][1] = (int)loc[1]; i++; } RNA_PROP_END; } - *mcords_tot = len; + *r_mcoords_len = len; } else { - *mcords_tot = 0; + *r_mcoords_len = 0; } /* cast for 'const' */ - return (const int(*)[2])mcords; + return mcoords; } #if 0 diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 17d697840a0..a93d4c7bf37 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -44,6 +44,7 @@ #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "BLI_timer.h" #include "BLI_utildefines.h" @@ -198,7 +199,7 @@ void WM_init_opengl(Main *bmain) opengl_is_init = true; } -static void sound_jack_sync_callback(Main *bmain, int mode, float time) +static void sound_jack_sync_callback(Main *bmain, int mode, double time) { /* Ugly: Blender doesn't like it when the animation is played back during rendering. */ if (G.is_rendering) { @@ -648,6 +649,7 @@ void WM_exit_ex(bContext *C, const bool do_python) DNA_sdna_current_free(); BLI_threadapi_exit(); + BLI_task_scheduler_exit(); /* No need to call this early, rather do it late so that other * pieces of Blender using sound may exit cleanly, see also T50676. */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a7578291a21..ad1f5430872 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1349,17 +1349,8 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op) } uiLayout *col = uiLayoutColumn(layout, false); - - if (op->type->flag & OPTYPE_MACRO) { - for (op = op->macro.first; op; op = op->next) { - uiTemplateOperatorPropertyButs( - C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - } - } - else { - uiTemplateOperatorPropertyButs( - C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - } + uiTemplateOperatorPropertyButs( + C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL); @@ -1794,13 +1785,12 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve } } - PropertyRNA *prop = op->type->prop; int search_type; - if (RNA_property_is_set(op->ptr, prop)) { - search_type = RNA_property_enum_get(op->ptr, prop); + if (STREQ(op->type->idname, "WM_OT_search_menu")) { + search_type = SEARCH_TYPE_MENU; } else { - search_type = U.experimental.use_menu_search ? SEARCH_TYPE_MENU : SEARCH_TYPE_OPERATOR; + search_type = SEARCH_TYPE_OPERATOR; } static struct SearchPopupInit_Data data; @@ -1809,7 +1799,7 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve .size = {UI_searchbox_size_x() * 2, UI_searchbox_size_y()}, }; - UI_popup_block_invoke(C, wm_block_search_menu, &data, NULL); + UI_popup_block_invoke_ex(C, wm_block_search_menu, &data, NULL, false); return OPERATOR_INTERFACE; } @@ -1818,20 +1808,22 @@ static void WM_OT_search_menu(wmOperatorType *ot) { ot->name = "Search Menu"; ot->idname = "WM_OT_search_menu"; - ot->description = "Pop-up a search menu over all available operators in current context"; + ot->description = "Pop-up a search over all menus in the current context"; ot->invoke = wm_search_menu_invoke; ot->exec = wm_search_menu_exec; ot->poll = WM_operator_winactive; +} - static const EnumPropertyItem search_type_items[] = { - {SEARCH_TYPE_OPERATOR, "OPERATOR", 0, "Operator", "Search all operators"}, - {SEARCH_TYPE_MENU, "MENU", 0, "Menu", "Search active menu items"}, - {0, NULL, 0, NULL, NULL}, - }; +static void WM_OT_search_operator(wmOperatorType *ot) +{ + ot->name = "Search Operator"; + ot->idname = "WM_OT_search_operator"; + ot->description = "Pop-up a search over all available operators in current context"; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", search_type_items, SEARCH_TYPE_OPERATOR, "Type", ""); + ot->invoke = wm_search_menu_invoke; + ot->exec = wm_search_menu_exec; + ot->poll = WM_operator_winactive; } static int wm_call_menu_exec(bContext *C, wmOperator *op) @@ -3806,6 +3798,7 @@ void wm_operatortypes_register(void) WM_operatortype_append(WM_OT_operator_defaults); WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); + WM_operatortype_append(WM_OT_search_operator); WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_call_menu_pie); WM_operatortype_append(WM_OT_call_panel); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 84f099b0dbc..948e8d9fb74 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -317,7 +317,13 @@ static void playanim_toscreen( GPU_blend(true); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - imm_draw_box_checker_2d(offs_x, offs_y, offs_x + span_x, offs_y + span_y); + imm_draw_box_checker_2d_ex(offs_x, + offs_y, + offs_x + span_x, + offs_y + span_y, + (const float[4]){0.15, 0.15, 0.15, 1.0}, + (const float[4]){0.20, 0.20, 0.20, 1.0}, + 8); } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 8fb7e47cd45..b1eee7509b7 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -769,19 +769,6 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm) * in practice the window manager will likely move to the correct monitor */ wm_init_state.start_x = 0; wm_init_state.start_y = 0; - -#ifdef WITH_X11 /* X11 */ - /* X11, don't start maximized because we can't figure out the dimensions - * of a single display yet if there are multiple, due to lack of Xinerama - * handling in GHOST. */ - wm_init_state.size_x = min_ii(wm_init_state.size_x, WM_WIN_INIT_SIZE_X); - wm_init_state.size_y = min_ii(wm_init_state.size_y, WM_WIN_INIT_SIZE_Y); - /* pad */ - wm_init_state.start_x = WM_WIN_INIT_PAD; - wm_init_state.start_y = WM_WIN_INIT_PAD; - wm_init_state.size_x -= WM_WIN_INIT_PAD * 2; - wm_init_state.size_y -= WM_WIN_INIT_PAD * 2; -#endif } LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index ce9d79b8e59..45cfe1431d7 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -82,11 +82,4 @@ int wm_window_new_main_exec(bContext *C, struct wmOperator *op); void wm_test_autorun_warning(bContext *C); -/* Initial (unmaximized) size to start with for - * systems that can't find it for themselves (X11). - * Clamped by real desktop limits */ -#define WM_WIN_INIT_SIZE_X 1800 -#define WM_WIN_INIT_SIZE_Y 1000 -#define WM_WIN_INIT_PAD 40 - #endif /* __WM_WINDOW_H__ */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h index b53ae45a29f..9b7e9a15948 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h +++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h @@ -34,11 +34,16 @@ typedef struct wmXrSessionState { float viewer_viewmat[4][4]; float focal_len; + /** Copy of XrSessionSettings.base_pose_ data to detect changes that need + * resetting to base pose. */ + char prev_base_pose_type; /* eXRSessionBasePoseType */ + Object *prev_base_pose_object; /** Copy of XrSessionSettings.flag created on the last draw call, stored to detect changes. */ int prev_settings_flag; /** Copy of wmXrDrawData.eye_position_ofs. */ float prev_eye_position_ofs[3]; + bool force_reset_to_base_pose; bool is_view_data_set; } wmXrSessionState; diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c index dc228d1b18b..e9ff38c5a92 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_session.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c @@ -95,6 +95,11 @@ bool WM_xr_session_exists(const wmXrData *xr) return xr->runtime && xr->runtime->context && xr->runtime->session_state.is_started; } +void WM_xr_session_base_pose_reset(wmXrData *xr) +{ + xr->runtime->session_state.force_reset_to_base_pose = true; +} + /** * Check if the session is running, according to the OpenXR definition. */ @@ -154,6 +159,17 @@ static void wm_xr_session_draw_data_populate(wmXrData *xr_data, wm_xr_session_base_pose_calc(r_draw_data->scene, settings, &r_draw_data->base_pose); } +static bool wm_xr_session_draw_data_needs_reset_to_base_pose(const wmXrSessionState *state, + const XrSessionSettings *settings) +{ + if (state->force_reset_to_base_pose) { + return true; + } + return ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) && + ((state->prev_base_pose_type != settings->base_pose_type) || + (state->prev_base_pose_object != settings->base_pose_object)); +} + void wm_xr_session_draw_data_update(const wmXrSessionState *state, const XrSessionSettings *settings, const GHOST_XrDrawViewInfo *draw_view, @@ -166,7 +182,8 @@ void wm_xr_session_draw_data_update(const wmXrSessionState *state, /* Set the eye position offset, it's used to offset the base pose when changing positional * tracking. */ - if (!state->is_view_data_set) { + if (!state->is_view_data_set || + wm_xr_session_draw_data_needs_reset_to_base_pose(state, settings)) { /* Always use the exact base pose with no offset when starting the session. */ copy_v3_fl(draw_data->eye_position_ofs, 0.0f); } @@ -223,6 +240,8 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, copy_v3_v3(state->prev_eye_position_ofs, draw_data->eye_position_ofs); state->prev_settings_flag = settings->flag; + state->prev_base_pose_type = settings->base_pose_type; + state->prev_base_pose_object = settings->base_pose_object; state->is_view_data_set = true; } diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 4b51f9738b3..b3e83b1412f 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -687,6 +687,17 @@ elseif(WIN32) ) endif() + if(WITH_WINDOWS_PDB) + if(WITH_WINDOWS_STRIPPED_PDB) + # Icky hack for older cmake from https://stackoverflow.com/a/21198501 + # $<CONFIG> will work in newer cmake but the version currently (3.12) + # on the buildbot does not support this endavour. + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}/blender_public.pdb DESTINATION . RENAME blender.pdb) + else() + install(FILES $<TARGET_PDB_FILE:blender> DESTINATION . RENAME blender.pdb) + endif() + endif() + if(WITH_PYTHON) string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) @@ -803,7 +814,20 @@ elseif(WIN32) DESTINATION "." ) endif() - + if(WITH_TBB) + install( + FILES + ${LIBDIR}/tbb/lib/tbb.dll + DESTINATION "." + CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel + ) + install( + FILES + ${LIBDIR}/tbb/lib/debug/tbb_debug.dll + DESTINATION "." + CONFIGURATIONS Debug + ) + endif() if(WITH_TBB_MALLOC_PROXY) install( FILES @@ -1085,6 +1109,20 @@ endif() # the use of vcpkg if(WIN32) set_target_properties(blender PROPERTIES VS_GLOBAL_VcpkgEnabled "false") + set_target_properties(blender PROPERTIES + PDB_NAME "blender_private" + PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>") + if (WITH_WINDOWS_PDB AND WITH_WINDOWS_STRIPPED_PDB) + # This is slightly messy, but single target generators like ninja will not have the + # CMAKE_CFG_INTDIR variable and multitarget generators like msbuild will not have + # CMAKE_BUILD_TYPE. This can be simplified by target_link_options and the $<CONFIG> + # generator expression in newer cmake (2.13+) but until that time this fill have suffice. + if(CMAKE_BUILD_TYPE) + set_property(TARGET blender APPEND PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/blender_public.pdb") + else() + set_property(TARGET blender APPEND PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/blender_public.pdb") + endif() + endif() endif() # ----------------------------------------------------------------------------- diff --git a/source/creator/creator.c b/source/creator/creator.c index 6c4af7be95e..ea64184c826 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -43,6 +43,7 @@ #include "BLI_args.h" #include "BLI_string.h" #include "BLI_system.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -401,6 +402,9 @@ int main(int argc, G.factory_startup = true; #endif + /* After parsing number of threads argument. */ + BLI_task_scheduler_init(); + #ifdef WITH_FFMPEG IMB_ffmpeg_init(); #endif diff --git a/source/creator/creator_signals.c b/source/creator/creator_signals.c index 7f7a03f0465..dbf947a86fd 100644 --- a/source/creator/creator_signals.c +++ b/source/creator/creator_signals.c @@ -190,97 +190,25 @@ static void sig_handle_crash(int signum) } # ifdef WIN32 -LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) +extern LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) { - switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { - case EXCEPTION_ACCESS_VIOLATION: - fputs("Error : EXCEPTION_ACCESS_VIOLATION\n", stderr); - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - fputs("Error : EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr); - break; - case EXCEPTION_BREAKPOINT: - fputs("Error : EXCEPTION_BREAKPOINT\n", stderr); - break; - case EXCEPTION_DATATYPE_MISALIGNMENT: - fputs("Error : EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr); - break; - case EXCEPTION_FLT_DENORMAL_OPERAND: - fputs("Error : EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr); - break; - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - fputs("Error : EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr); - break; - case EXCEPTION_FLT_INEXACT_RESULT: - fputs("Error : EXCEPTION_FLT_INEXACT_RESULT\n", stderr); - break; - case EXCEPTION_FLT_INVALID_OPERATION: - fputs("Error : EXCEPTION_FLT_INVALID_OPERATION\n", stderr); - break; - case EXCEPTION_FLT_OVERFLOW: - fputs("Error : EXCEPTION_FLT_OVERFLOW\n", stderr); - break; - case EXCEPTION_FLT_STACK_CHECK: - fputs("Error : EXCEPTION_FLT_STACK_CHECK\n", stderr); - break; - case EXCEPTION_FLT_UNDERFLOW: - fputs("Error : EXCEPTION_FLT_UNDERFLOW\n", stderr); - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - fputs("Error : EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr); - break; - case EXCEPTION_IN_PAGE_ERROR: - fputs("Error : EXCEPTION_IN_PAGE_ERROR\n", stderr); - break; - case EXCEPTION_INT_DIVIDE_BY_ZERO: - fputs("Error : EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr); - break; - case EXCEPTION_INT_OVERFLOW: - fputs("Error : EXCEPTION_INT_OVERFLOW\n", stderr); - break; - case EXCEPTION_INVALID_DISPOSITION: - fputs("Error : EXCEPTION_INVALID_DISPOSITION\n", stderr); - break; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - fputs("Error : EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr); - break; - case EXCEPTION_PRIV_INSTRUCTION: - fputs("Error : EXCEPTION_PRIV_INSTRUCTION\n", stderr); - break; - case EXCEPTION_SINGLE_STEP: - fputs("Error : EXCEPTION_SINGLE_STEP\n", stderr); - break; - case EXCEPTION_STACK_OVERFLOW: - fputs("Error : EXCEPTION_STACK_OVERFLOW\n", stderr); - break; - default: - fputs("Error : Unrecognized Exception\n", stderr); - break; - } - - fflush(stderr); - - /* If this is a stack overflow then we can't walk the stack, so just show + /* If this is a stack overflow then we can't walk the stack, so just try to show * where the error happened */ - if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) { HMODULE mod; CHAR modulename[MAX_PATH]; LPVOID address = ExceptionInfo->ExceptionRecord->ExceptionAddress; - + fprintf(stderr, "Error : EXCEPTION_STACK_OVERFLOW\n"); fprintf(stderr, "Address : 0x%p\n", address); if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &mod)) { if (GetModuleFileName(mod, modulename, MAX_PATH)) { fprintf(stderr, "Module : %s\n", modulename); } } - - fflush(stderr); - -# ifdef NDEBUG - TerminateProcess(GetCurrentProcess(), SIGSEGV); -# else + } + else { + BLI_windows_handle_exception(ExceptionInfo); sig_handle_crash(SIGSEGV); -# endif } return EXCEPTION_EXECUTE_HANDLER; diff --git a/source/tools b/source/tools -Subproject 35dd27ded664b1068e773c27988ee221f3ce39d +Subproject 8a36c2833db48ed78c436ee19534ce5cf3b2eee diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 966572b23e7..80d749c7040 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,15 +14,27 @@ endif() # Path to Blender and Python executables for all platforms. if(MSVC) set(TEST_BLENDER_EXE ${TEST_INSTALL_DIR}/blender.exe) - set(TEST_PYTHON_EXE "${TEST_INSTALL_DIR}/${BLENDER_VERSION_MAJOR}.${BLENDER_VERSION_MINOR}/python/bin/python$<$<CONFIG:Debug>:_d>") + set(_default_test_python_exe "${TEST_INSTALL_DIR}/${BLENDER_VERSION_MAJOR}.${BLENDER_VERSION_MINOR}/python/bin/python$<$<CONFIG:Debug>:_d>") elseif(APPLE) set(TEST_BLENDER_EXE ${TEST_INSTALL_DIR}/Blender.app/Contents/MacOS/Blender) - set(TEST_PYTHON_EXE) + set(_default_test_python_exe ${PYTHON_EXECUTABLE}) else() set(TEST_BLENDER_EXE ${TEST_INSTALL_DIR}/blender) - set(TEST_PYTHON_EXE) + set(_default_test_python_exe ${PYTHON_EXECUTABLE}) endif() +# The installation directory's Python is the best one to use. However, it can only be there after the install step, +# which means that Python will never be there on a fresh system. To suit different needs, the user can pass +# -DTEST_PYTHON_EXE=/path/to/python to CMake. +if (NOT TEST_PYTHON_EXE) + set(TEST_PYTHON_EXE ${_default_test_python_exe}) + message(STATUS "Tests: Using Python executable: ${TEST_PYTHON_EXE}") +elseif(NOT EXISTS ${TEST_PYTHON_EXE}) + message(FATAL_ERROR "Tests: TEST_PYTHON_EXE ${TEST_PYTHON_EXE} does not exist") +endif() +unset(_default_test_python_exe) + + # For testing with Valgrind # set(TEST_BLENDER_EXE valgrind --track-origins=yes --error-limit=no ${TEST_BLENDER_EXE}) diff --git a/tests/gtests/CMakeLists.txt b/tests/gtests/CMakeLists.txt index bcf77fb6de7..c02bad471ff 100644 --- a/tests/gtests/CMakeLists.txt +++ b/tests/gtests/CMakeLists.txt @@ -12,6 +12,7 @@ if(WITH_GTESTS) remove_strict_flags() add_subdirectory(testing) + add_subdirectory(blenkernel) add_subdirectory(blenlib) add_subdirectory(blenloader) add_subdirectory(guardedalloc) diff --git a/tests/gtests/alembic/abc_matrix_test.cc b/tests/gtests/alembic/abc_matrix_test.cc index 59ccd57937a..9b16eb108be 100644 --- a/tests/gtests/alembic/abc_matrix_test.cc +++ b/tests/gtests/alembic/abc_matrix_test.cc @@ -1,7 +1,7 @@ #include "testing/testing.h" // Keep first since utildefines defines AT which conflicts with STL -#include "intern/abc_util.h" +#include "intern/abc_axis_conversion.h" extern "C" { #include "BLI_math.h" diff --git a/tests/gtests/blenkernel/BKE_armature_test.cc b/tests/gtests/blenkernel/BKE_armature_test.cc new file mode 100644 index 00000000000..ed6045081d4 --- /dev/null +++ b/tests/gtests/blenkernel/BKE_armature_test.cc @@ -0,0 +1,89 @@ +/* + * 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) 2020 Blender Foundation + * All rights reserved. + */ + +#include "BKE_armature.h" + +#include "BLI_math.h" + +#include "testing/testing.h" + +static const float FLOAT_EPSILON = 1.2e-7; + +TEST(mat3_vec_to_roll, UnitMatrix) +{ + float unit_matrix[3][3]; + float roll; + + unit_m3(unit_matrix); + + // Any vector with a unit matrix should return zero roll. + mat3_vec_to_roll(unit_matrix, unit_matrix[0], &roll); + EXPECT_FLOAT_EQ(0.0f, roll); + + mat3_vec_to_roll(unit_matrix, unit_matrix[1], &roll); + EXPECT_FLOAT_EQ(0.0f, roll); + + mat3_vec_to_roll(unit_matrix, unit_matrix[2], &roll); + EXPECT_FLOAT_EQ(0.0f, roll); + + { + // Non-unit vector. + float vector[3] = {1.0f, 1.0f, 1.0f}; + mat3_vec_to_roll(unit_matrix, vector, &roll); + EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON); + + // Normalized version of the above vector. + normalize_v3(vector); + mat3_vec_to_roll(unit_matrix, vector, &roll); + EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON); + } +} + +TEST(mat3_vec_to_roll, Rotationmatrix) +{ + float rotation_matrix[3][3]; + float roll; + + const float rot_around_x[3] = {1.234f, 0.0f, 0.0f}; + eul_to_mat3(rotation_matrix, rot_around_x); + + { + const float unit_axis_x[3] = {1.0f, 0.0f, 0.0f}; + mat3_vec_to_roll(rotation_matrix, unit_axis_x, &roll); + EXPECT_NEAR(1.234f, roll, FLOAT_EPSILON); + } + + { + const float unit_axis_y[3] = {0.0f, 1.0f, 0.0f}; + mat3_vec_to_roll(rotation_matrix, unit_axis_y, &roll); + EXPECT_NEAR(0, roll, FLOAT_EPSILON); + } + + { + const float unit_axis_z[3] = {0.0f, 0.0f, 1.0f}; + mat3_vec_to_roll(rotation_matrix, unit_axis_z, &roll); + EXPECT_NEAR(0, roll, FLOAT_EPSILON); + } + + { + const float between_x_and_y[3] = {1.0f, 1.0f, 0.0f}; + mat3_vec_to_roll(rotation_matrix, between_x_and_y, &roll); + EXPECT_NEAR(0.57158958f, roll, FLOAT_EPSILON); + } +} diff --git a/tests/gtests/blenkernel/BKE_fcurve_test.cc b/tests/gtests/blenkernel/BKE_fcurve_test.cc new file mode 100644 index 00000000000..d28c5075bd8 --- /dev/null +++ b/tests/gtests/blenkernel/BKE_fcurve_test.cc @@ -0,0 +1,211 @@ +/* + * 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) 2020 by Blender Foundation. + */ +#include "testing/testing.h" + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BKE_fcurve.h" + +#include "ED_keyframing.h" + +#include "DNA_anim_types.h" +} + +// Epsilon for floating point comparisons. +static const float EPSILON = 1e-7f; + +TEST(evaluate_fcurve, EmptyFCurve) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + EXPECT_EQ(evaluate_fcurve(fcu, 47.0f), 0.0f); + free_fcurve(fcu); +} + +TEST(evaluate_fcurve, OnKeys) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + + insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF); + insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF); + insert_vert_fcurve(fcu, 3.0f, 19.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF); + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.0f), 7.0f, EPSILON); // hits 'on or before first' function + EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f), 13.0f, EPSILON); // hits 'between' function + EXPECT_NEAR(evaluate_fcurve(fcu, 3.0f), 19.0f, EPSILON); // hits 'on or after last' function + + /* Also test within a specific time epsilon of the keys, as this was an issue in T39207. + * This epsilon is just slightly smaller than the epsilon given to binarysearch_bezt_index_ex() + * in fcurve_eval_between_keyframes(), so it should hit the "exact" code path. */ + float time_epsilon = 0.00008f; + EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f - time_epsilon), 13.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f + time_epsilon), 13.0f, EPSILON); + + free_fcurve(fcu); +} + +TEST(evaluate_fcurve, InterpolationConstant) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].ipo = BEZT_IPO_CONST; + fcu->bezt[1].ipo = BEZT_IPO_CONST; + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 7.0f, EPSILON); + + free_fcurve(fcu); +} + +TEST(evaluate_fcurve, InterpolationLinear) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].ipo = BEZT_IPO_LIN; + fcu->bezt[1].ipo = BEZT_IPO_LIN; + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 8.5f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 10.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 11.5f, EPSILON); + + free_fcurve(fcu); +} + +TEST(evaluate_fcurve, InterpolationBezier) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + EXPECT_EQ(fcu->bezt[0].ipo, BEZT_IPO_BEZ); + EXPECT_EQ(fcu->bezt[1].ipo, BEZT_IPO_BEZ); + + // Test with default handles. + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.8297067f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 10.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 12.170294f, EPSILON); + + // Test with modified handles. + fcu->bezt[0].vec[0][0] = 0.71855f; // left handle X + fcu->bezt[0].vec[0][1] = 6.22482f; // left handle Y + fcu->bezt[0].vec[2][0] = 1.35148f; // right handle X + fcu->bezt[0].vec[2][1] = 7.96806f; // right handle Y + + fcu->bezt[1].vec[0][0] = 1.66667f; // left handle X + fcu->bezt[1].vec[0][1] = 10.4136f; // left handle Y + fcu->bezt[1].vec[2][0] = 2.33333f; // right handle X + fcu->bezt[1].vec[2][1] = 15.5864f; // right handle Y + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.945497f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 9.3495407f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 11.088551f, EPSILON); + + free_fcurve(fcu); +} + +TEST(evaluate_fcurve, InterpolationBounce) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].ipo = BEZT_IPO_BOUNCE; + fcu->bezt[1].ipo = BEZT_IPO_BOUNCE; + + fcu->bezt[0].easing = BEZT_IPO_EASE_IN; + fcu->bezt[1].easing = BEZT_IPO_EASE_AUTO; + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.4f), 8.3649998f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.5f), 8.4062500f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.8f), 11.184999f, EPSILON); + + free_fcurve(fcu); +} + +TEST(evaluate_fcurve, ExtrapolationLinearKeys) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + fcu->bezt[0].ipo = BEZT_IPO_LIN; + fcu->bezt[1].ipo = BEZT_IPO_LIN; + + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 5.5f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 0.50f), 4.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), -8.0f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 17.5f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 22.0f, EPSILON); + + fcu->extend = FCURVE_EXTRAPOLATE_CONSTANT; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 7.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), 7.0f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 13.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 13.0f, EPSILON); + + free_fcurve(fcu); +} + +TEST(evaluate_fcurve, ExtrapolationBezierKeys) +{ + FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve")); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].vec[0][0] = 0.71855f; // left handle X + fcu->bezt[0].vec[0][1] = 6.22482f; // left handle Y + fcu->bezt[0].vec[2][0] = 1.35148f; // right handle X + fcu->bezt[0].vec[2][1] = 7.96806f; // right handle Y + + fcu->bezt[1].vec[0][0] = 1.66667f; // left handle X + fcu->bezt[1].vec[0][1] = 10.4136f; // left handle Y + fcu->bezt[1].vec[2][0] = 2.33333f; // right handle X + fcu->bezt[1].vec[2][1] = 15.5864f; // right handle Y + + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 6.3114409f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -0.50f), 2.8686447f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 18.81946f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 24.63892f, EPSILON); + + fcu->extend = FCURVE_EXTRAPOLATE_CONSTANT; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 7.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), 7.0f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 13.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 13.0f, EPSILON); + + free_fcurve(fcu); +} diff --git a/intern/string/CMakeLists.txt b/tests/gtests/blenkernel/CMakeLists.txt index 8c400f320ae..5cf4c7a27af 100644 --- a/intern/string/CMakeLists.txt +++ b/tests/gtests/blenkernel/CMakeLists.txt @@ -14,25 +14,31 @@ # 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) 2006, Blender Foundation +# The Original Code is Copyright (C) 2020, Blender Foundation # All rights reserved. # ***** END GPL LICENSE BLOCK ***** set(INC . + .. + ../../../source/blender/blenkernel + ../../../source/blender/blenlib + ../../../source/blender/editors/include + ../../../source/blender/makesdna + ../../../source/blender/makesrna + ../../../intern/guardedalloc + ../../../intern/atomic ) -set(INC_SYS +setup_libdirs() +include_directories(${INC}) -) - -set(SRC - intern/STR_String.cpp +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}") - STR_String.h -) - -set(LIB -) +if(WITH_BUILDINFO) + set(BUILDINFO buildinfoobj) +endif() -blender_add_lib(bf_intern_string "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") +BLENDER_TEST(BKE_armature "bf_blenloader;bf_blenkernel;bf_blenlib;${BUILDINFO}") +BLENDER_TEST(BKE_fcurve "bf_blenloader;bf_blenkernel;bf_editor_animation;${BUILDINFO}") diff --git a/tests/gtests/blenlib/BLI_array_ref_test.cc b/tests/gtests/blenlib/BLI_array_ref_test.cc index aacd6113161..7a1f54e7458 100644 --- a/tests/gtests/blenlib/BLI_array_ref_test.cc +++ b/tests/gtests/blenlib/BLI_array_ref_test.cc @@ -1,5 +1,5 @@ -#include "BLI_array_ref.h" -#include "BLI_vector.h" +#include "BLI_array_ref.hh" +#include "BLI_vector.hh" #include "testing/testing.h" using namespace BLI; diff --git a/tests/gtests/blenlib/BLI_array_test.cc b/tests/gtests/blenlib/BLI_array_test.cc index dd09c2d20f8..b1aa24aa808 100644 --- a/tests/gtests/blenlib/BLI_array_test.cc +++ b/tests/gtests/blenlib/BLI_array_test.cc @@ -1,4 +1,4 @@ -#include "BLI_array_cxx.h" +#include "BLI_array.hh" #include "testing/testing.h" using namespace BLI; diff --git a/tests/gtests/blenlib/BLI_index_range_test.cc b/tests/gtests/blenlib/BLI_index_range_test.cc index 60da18b6baf..b12502f0d97 100644 --- a/tests/gtests/blenlib/BLI_index_range_test.cc +++ b/tests/gtests/blenlib/BLI_index_range_test.cc @@ -1,5 +1,5 @@ -#include "BLI_index_range.h" -#include "BLI_vector.h" +#include "BLI_index_range.hh" +#include "BLI_vector.hh" #include "testing/testing.h" using BLI::ArrayRef; diff --git a/tests/gtests/blenlib/BLI_linear_allocator_test.cc b/tests/gtests/blenlib/BLI_linear_allocator_test.cc new file mode 100644 index 00000000000..0c67d1e76c9 --- /dev/null +++ b/tests/gtests/blenlib/BLI_linear_allocator_test.cc @@ -0,0 +1,113 @@ +#include "BLI_linear_allocator.hh" +#include "testing/testing.h" + +using namespace BLI; + +static bool is_aligned(void *ptr, uint alignment) +{ + BLI_assert(is_power_of_2_i(alignment)); + return (POINTER_AS_UINT(ptr) & (alignment - 1)) == 0; +} + +TEST(linear_allocator, AllocationAlignment) +{ + LinearAllocator<> allocator; + + EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 8), 8)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 16), 16)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 64), 64)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 64), 64)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 8), 8)); + EXPECT_TRUE(is_aligned(allocator.allocate(10, 128), 128)); +} + +TEST(linear_allocator, PackedAllocation) +{ + LinearAllocator<> allocator; + BLI::AlignedBuffer<256, 32> buffer; + allocator.provide_buffer(buffer); + + uintptr_t ptr1 = (uintptr_t)allocator.allocate(10, 4); /* 0 - 10 */ + uintptr_t ptr2 = (uintptr_t)allocator.allocate(10, 4); /* 12 - 22 */ + uintptr_t ptr3 = (uintptr_t)allocator.allocate(8, 32); /* 32 - 40 */ + uintptr_t ptr4 = (uintptr_t)allocator.allocate(16, 8); /* 40 - 56 */ + uintptr_t ptr5 = (uintptr_t)allocator.allocate(1, 8); /* 56 - 57 */ + uintptr_t ptr6 = (uintptr_t)allocator.allocate(1, 4); /* 60 - 61 */ + uintptr_t ptr7 = (uintptr_t)allocator.allocate(1, 1); /* 61 - 62 */ + + EXPECT_EQ(ptr2 - ptr1, 12); /* 12 - 0 = 12 */ + EXPECT_EQ(ptr3 - ptr2, 20); /* 32 - 12 = 20 */ + EXPECT_EQ(ptr4 - ptr3, 8); /* 40 - 32 = 8 */ + EXPECT_EQ(ptr5 - ptr4, 16); /* 56 - 40 = 16 */ + EXPECT_EQ(ptr6 - ptr5, 4); /* 60 - 56 = 4 */ + EXPECT_EQ(ptr7 - ptr6, 1); /* 61 - 60 = 1 */ +} + +TEST(linear_allocator, CopyString) +{ + LinearAllocator<> allocator; + BLI::AlignedBuffer<256, 1> buffer; + allocator.provide_buffer(buffer); + + StringRefNull ref1 = allocator.copy_string("Hello"); + StringRefNull ref2 = allocator.copy_string("World"); + + EXPECT_EQ(ref1, "Hello"); + EXPECT_EQ(ref2, "World"); + EXPECT_EQ(ref2.data() - ref1.data(), 6); +} + +TEST(linear_allocator, AllocateArray) +{ + LinearAllocator<> allocator; + + MutableArrayRef<int> array = allocator.allocate_array<int>(5); + EXPECT_EQ(array.size(), 5); +} + +TEST(linear_allocator, Construct) +{ + LinearAllocator<> allocator; + + std::array<int, 5> values = {1, 2, 3, 4, 5}; + Vector<int> *vector = allocator.construct<Vector<int>>(values); + EXPECT_EQ(vector->size(), 5); + EXPECT_EQ((*vector)[3], 4); + vector->~Vector(); +} + +TEST(linear_allocator, ConstructElementsAndPointerArray) +{ + LinearAllocator<> allocator; + + std::array<int, 7> values = {1, 2, 3, 4, 5, 6, 7}; + ArrayRef<Vector<int> *> vectors = allocator.construct_elements_and_pointer_array<Vector<int>>( + 5, values); + + EXPECT_EQ(vectors.size(), 5); + EXPECT_EQ(vectors[3]->size(), 7); + EXPECT_EQ((*vectors[2])[5], 6); + + for (Vector<int> *vector : vectors) { + vector->~Vector(); + } +} + +TEST(linear_allocator, ConstructArrayCopy) +{ + LinearAllocator<> allocator; + + Vector<int> values = {1, 2, 3}; + MutableArrayRef<int> array1 = allocator.construct_array_copy(values.as_ref()); + MutableArrayRef<int> array2 = allocator.construct_array_copy(values.as_ref()); + EXPECT_NE(array1.begin(), array2.begin()); + EXPECT_EQ(array1.size(), 3); + EXPECT_EQ(array2.size(), 3); + EXPECT_EQ(array1[1], 2); + EXPECT_EQ(array2[2], 3); +} diff --git a/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc b/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc index 9934d1a3337..023d02e5075 100644 --- a/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc +++ b/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc @@ -63,9 +63,9 @@ struct IndexedNode { int index; }; -void concurrent_insert(TaskPool *__restrict pool, void *taskdata, int /*threadid*/) +void concurrent_insert(TaskPool *__restrict pool, void *taskdata) { - LockfreeLinkList *list = (LockfreeLinkList *)BLI_task_pool_userdata(pool); + LockfreeLinkList *list = (LockfreeLinkList *)BLI_task_pool_user_data(pool); CHECK_NOTNULL(list); IndexedNode *node = (IndexedNode *)MEM_mallocN(sizeof(IndexedNode), "test node"); node->index = POINTER_AS_INT(taskdata); @@ -76,14 +76,12 @@ void concurrent_insert(TaskPool *__restrict pool, void *taskdata, int /*threadid TEST(LockfreeLinkList, InsertMultipleConcurrent) { - static const int num_threads = 512; static const int num_nodes = 655360; /* Initialize list. */ LockfreeLinkList list; BLI_linklist_lockfree_init(&list); /* Initialize task scheduler and pool. */ - TaskScheduler *scheduler = BLI_task_scheduler_create(num_threads); - TaskPool *pool = BLI_task_pool_create_suspended(scheduler, &list, TASK_PRIORITY_HIGH); + TaskPool *pool = BLI_task_pool_create_suspended(&list, TASK_PRIORITY_HIGH); /* Push tasks to the pool. */ for (int i = 0; i < num_nodes; ++i) { BLI_task_pool_push(pool, concurrent_insert, POINTER_FROM_INT(i), false, NULL); @@ -112,5 +110,4 @@ TEST(LockfreeLinkList, InsertMultipleConcurrent) /* Cleanup data. */ BLI_linklist_lockfree_free(&list, MEM_freeN); BLI_task_pool_free(pool); - BLI_task_scheduler_free(scheduler); } diff --git a/tests/gtests/blenlib/BLI_map_test.cc b/tests/gtests/blenlib/BLI_map_test.cc index 7be23157e94..5a19216fa7c 100644 --- a/tests/gtests/blenlib/BLI_map_test.cc +++ b/tests/gtests/blenlib/BLI_map_test.cc @@ -1,5 +1,5 @@ -#include "BLI_map.h" -#include "BLI_set.h" +#include "BLI_map.hh" +#include "BLI_set.hh" #include "testing/testing.h" using BLI::Map; @@ -9,16 +9,20 @@ TEST(map, DefaultConstructor) { IntFloatMap map; EXPECT_EQ(map.size(), 0); + EXPECT_TRUE(map.is_empty()); } TEST(map, AddIncreasesSize) { IntFloatMap map; EXPECT_EQ(map.size(), 0); + EXPECT_TRUE(map.is_empty()); map.add(2, 5.0f); EXPECT_EQ(map.size(), 1); + EXPECT_FALSE(map.is_empty()); map.add(6, 2.0f); EXPECT_EQ(map.size(), 2); + EXPECT_FALSE(map.is_empty()); } TEST(map, Contains) @@ -209,6 +213,17 @@ TEST(map, AddOverride) EXPECT_EQ(map.lookup(3), 7.0f); } +TEST(map, LookupOrAddDefault) +{ + IntFloatMap map; + map.lookup_or_add_default(3) = 6; + EXPECT_EQ(map.lookup(3), 6); + map.lookup_or_add_default(5) = 2; + EXPECT_EQ(map.lookup(5), 2); + map.lookup_or_add_default(3) += 4; + EXPECT_EQ(map.lookup(3), 10); +} + TEST(map, MoveConstructorSmall) { IntFloatMap map1; diff --git a/tests/gtests/blenlib/BLI_optional_test.cc b/tests/gtests/blenlib/BLI_optional_test.cc index a25a3cbd588..e0dec5681fe 100644 --- a/tests/gtests/blenlib/BLI_optional_test.cc +++ b/tests/gtests/blenlib/BLI_optional_test.cc @@ -1,4 +1,4 @@ -#include "BLI_optional.h" +#include "BLI_optional.hh" #include "testing/testing.h" #include <string> diff --git a/tests/gtests/blenlib/BLI_set_test.cc b/tests/gtests/blenlib/BLI_set_test.cc index 555140f805c..90c052d7d2b 100644 --- a/tests/gtests/blenlib/BLI_set_test.cc +++ b/tests/gtests/blenlib/BLI_set_test.cc @@ -1,5 +1,5 @@ -#include "BLI_set.h" -#include "BLI_vector.h" +#include "BLI_set.hh" +#include "BLI_vector.hh" #include "testing/testing.h" using BLI::Set; @@ -10,6 +10,7 @@ TEST(set, Defaultconstructor) { IntSet set; EXPECT_EQ(set.size(), 0); + EXPECT_TRUE(set.is_empty()); } TEST(set, ContainsNotExistant) @@ -22,8 +23,10 @@ TEST(set, ContainsExistant) { IntSet set; EXPECT_FALSE(set.contains(5)); + EXPECT_TRUE(set.is_empty()); set.add(5); EXPECT_TRUE(set.contains(5)); + EXPECT_FALSE(set.is_empty()); } TEST(set, AddMany) @@ -155,16 +158,6 @@ TEST(set, AddMultipleNew) EXPECT_TRUE(a.contains(6)); } -TEST(set, ToSmallVector) -{ - IntSet a = {5, 2, 8}; - BLI::Vector<int> vec = a.to_small_vector(); - EXPECT_EQ(vec.size(), 3); - EXPECT_TRUE(vec.contains(5)); - EXPECT_TRUE(vec.contains(2)); - EXPECT_TRUE(vec.contains(8)); -} - TEST(set, Iterator) { IntSet set = {1, 3, 2, 5, 4}; @@ -201,3 +194,11 @@ TEST(set, UniquePtrValues) EXPECT_EQ(set.size(), 3); } + +TEST(set, Clear) +{ + Set<int> set = {3, 4, 6, 7}; + EXPECT_EQ(set.size(), 4); + set.clear(); + EXPECT_EQ(set.size(), 0); +} diff --git a/tests/gtests/blenlib/BLI_stack_cxx_test.cc b/tests/gtests/blenlib/BLI_stack_cxx_test.cc index 6376259927b..e49872f8643 100644 --- a/tests/gtests/blenlib/BLI_stack_cxx_test.cc +++ b/tests/gtests/blenlib/BLI_stack_cxx_test.cc @@ -1,4 +1,4 @@ -#include "BLI_stack_cxx.h" +#include "BLI_stack.hh" #include "testing/testing.h" using BLI::Stack; diff --git a/tests/gtests/blenlib/BLI_string_map_test.cc b/tests/gtests/blenlib/BLI_string_map_test.cc index 4cb67d5fbac..6acad0ce581 100644 --- a/tests/gtests/blenlib/BLI_string_map_test.cc +++ b/tests/gtests/blenlib/BLI_string_map_test.cc @@ -1,5 +1,5 @@ -#include "BLI_string_map.h" -#include "BLI_vector.h" +#include "BLI_string_map.hh" +#include "BLI_vector.hh" #include "testing/testing.h" using namespace BLI; @@ -232,3 +232,44 @@ TEST(string_map, UniquePtrValues) std::unique_ptr<int> *b = map.lookup_ptr("A"); EXPECT_EQ(a.get(), b->get()); } + +TEST(string_map, AddOrModify) +{ + StringMap<int> map; + auto create_func = [](int *value) { + *value = 10; + return true; + }; + auto modify_func = [](int *value) { + *value += 5; + return false; + }; + EXPECT_TRUE(map.add_or_modify("Hello", create_func, modify_func)); + EXPECT_EQ(map.lookup("Hello"), 10); + EXPECT_FALSE(map.add_or_modify("Hello", create_func, modify_func)); + EXPECT_EQ(map.lookup("Hello"), 15); +} + +TEST(string_map, LookupOrAdd) +{ + StringMap<int> map; + auto return_5 = []() { return 5; }; + auto return_8 = []() { return 8; }; + + int &a = map.lookup_or_add("A", return_5); + EXPECT_EQ(a, 5); + EXPECT_EQ(map.lookup_or_add("A", return_8), 5); + EXPECT_EQ(map.lookup_or_add("B", return_8), 8); +} + +TEST(string_map, LookupOrAddDefault) +{ + StringMap<std::string> map; + + std::string &a = map.lookup_or_add_default("A"); + EXPECT_EQ(a.size(), 0); + a += "Test"; + EXPECT_EQ(a.size(), 4); + std::string &b = map.lookup_or_add_default("A"); + EXPECT_EQ(b, "Test"); +} diff --git a/tests/gtests/blenlib/BLI_string_ref_test.cc b/tests/gtests/blenlib/BLI_string_ref_test.cc index a268bf3215a..393f28d4fc1 100644 --- a/tests/gtests/blenlib/BLI_string_ref_test.cc +++ b/tests/gtests/blenlib/BLI_string_ref_test.cc @@ -1,5 +1,5 @@ -#include "BLI_string_ref.h" -#include "BLI_vector.h" +#include "BLI_string_ref.hh" +#include "BLI_vector.hh" #include "testing/testing.h" using BLI::StringRef; @@ -237,3 +237,14 @@ TEST(string_ref, Substr) EXPECT_EQ(ref.substr(3, 4), "lo w"); EXPECT_EQ(ref.substr(6, 5), "world"); } + +TEST(string_ref, Copy) +{ + StringRef ref("hello"); + char dst[10]; + memset(dst, 0xFF, 10); + ref.copy(dst); + EXPECT_EQ(dst[5], '\0'); + EXPECT_EQ(dst[6], 0xFF); + EXPECT_EQ(ref, dst); +} diff --git a/tests/gtests/blenlib/BLI_task_performance_test.cc b/tests/gtests/blenlib/BLI_task_performance_test.cc index db596340464..06e832bdb5e 100644 --- a/tests/gtests/blenlib/BLI_task_performance_test.cc +++ b/tests/gtests/blenlib/BLI_task_performance_test.cc @@ -36,92 +36,6 @@ static uint gen_pseudo_random_number(uint num) return ((num & 255) << 6) + 1; } -/* *** Parallel iterations over range of indices. *** */ - -static void task_parallel_range_func(void *UNUSED(userdata), - int index, - const TaskParallelTLS *__restrict UNUSED(tls)) -{ - const uint limit = gen_pseudo_random_number((uint)index); - for (uint i = (uint)index; i < limit;) { - i += gen_pseudo_random_number(i); - } -} - -static void task_parallel_range_test_do(const char *id, - const int num_items, - const bool use_threads) -{ - TaskParallelSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = use_threads; - - double averaged_timing = 0.0; - for (int i = 0; i < NUM_RUN_AVERAGED; i++) { - const double init_time = PIL_check_seconds_timer(); - for (int j = 0; j < 10; j++) { - BLI_task_parallel_range(i + j, i + j + num_items, NULL, task_parallel_range_func, &settings); - } - averaged_timing += PIL_check_seconds_timer() - init_time; - } - - printf("\t%s: non-pooled done in %fs on average over %d runs\n", - id, - averaged_timing / NUM_RUN_AVERAGED, - NUM_RUN_AVERAGED); - - averaged_timing = 0.0; - for (int i = 0; i < NUM_RUN_AVERAGED; i++) { - const double init_time = PIL_check_seconds_timer(); - TaskParallelRangePool *range_pool = BLI_task_parallel_range_pool_init(&settings); - for (int j = 0; j < 10; j++) { - BLI_task_parallel_range_pool_push( - range_pool, i + j, i + j + num_items, NULL, task_parallel_range_func, &settings); - } - BLI_task_parallel_range_pool_work_and_wait(range_pool); - BLI_task_parallel_range_pool_free(range_pool); - averaged_timing += PIL_check_seconds_timer() - init_time; - } - - printf("\t%s: pooled done in %fs on average over %d runs\n", - id, - averaged_timing / NUM_RUN_AVERAGED, - NUM_RUN_AVERAGED); -} - -TEST(task, RangeIter10KNoThread) -{ - task_parallel_range_test_do( - "Range parallel iteration - Single thread - 10K items", 10000, false); -} - -TEST(task, RangeIter10k) -{ - task_parallel_range_test_do("Range parallel iteration - Threaded - 10K items", 10000, true); -} - -TEST(task, RangeIter100KNoThread) -{ - task_parallel_range_test_do( - "Range parallel iteration - Single thread - 100K items", 100000, false); -} - -TEST(task, RangeIter100k) -{ - task_parallel_range_test_do("Range parallel iteration - Threaded - 100K items", 100000, true); -} - -TEST(task, RangeIter1000KNoThread) -{ - task_parallel_range_test_do( - "Range parallel iteration - Single thread - 1000K items", 1000000, false); -} - -TEST(task, RangeIter1000k) -{ - task_parallel_range_test_do("Range parallel iteration - Threaded - 1000K items", 1000000, true); -} - /* *** Parallel iterations over double-linked list items. *** */ static void task_listbase_light_iter_func(void *UNUSED(userdata), diff --git a/tests/gtests/blenlib/BLI_task_test.cc b/tests/gtests/blenlib/BLI_task_test.cc index d4ab9de13c4..ed300b3f238 100644 --- a/tests/gtests/blenlib/BLI_task_test.cc +++ b/tests/gtests/blenlib/BLI_task_test.cc @@ -27,17 +27,19 @@ static void task_range_iter_func(void *userdata, int index, const TaskParallelTL // printf("%d, %d, %d\n", index, data[index], *((int *)tls->userdata_chunk)); } -static void task_range_iter_finalize_func(void *__restrict userdata, - void *__restrict userdata_chunk) +static void task_range_iter_reduce_func(const void *__restrict UNUSED(userdata), + void *__restrict join_v, + void *__restrict userdata_chunk) { - int *data = (int *)userdata; - data[NUM_ITEMS] += *(int *)userdata_chunk; + int *join = (int *)join_v; + int *chunk = (int *)userdata_chunk; + *join += *chunk; // printf("%d, %d\n", data[NUM_ITEMS], *((int *)userdata_chunk)); } TEST(task, RangeIter) { - int data[NUM_ITEMS + 1] = {0}; + int data[NUM_ITEMS] = {0}; int sum = 0; BLI_threadapi_init(); @@ -48,11 +50,11 @@ TEST(task, RangeIter) settings.userdata_chunk = ∑ settings.userdata_chunk_size = sizeof(sum); - settings.func_finalize = task_range_iter_finalize_func; + settings.func_reduce = task_range_iter_reduce_func; BLI_task_parallel_range(0, NUM_ITEMS, data, task_range_iter_func, &settings); - /* Those checks should ensure us all items of the listbase were processed once, and only once - + /* Those checks should ensure us all items of the listbase were processed once, and only once * as expected. */ int expected_sum = 0; @@ -60,79 +62,7 @@ TEST(task, RangeIter) EXPECT_EQ(data[i], i); expected_sum += i; } - EXPECT_EQ(data[NUM_ITEMS], expected_sum); - - BLI_threadapi_exit(); -} - -TEST(task, RangeIterPool) -{ - const int num_tasks = 10; - int data[num_tasks][NUM_ITEMS + 1] = {{0}}; - int sum = 0; - - BLI_threadapi_init(); - - TaskParallelSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.min_iter_per_thread = 1; - - TaskParallelRangePool *range_pool = BLI_task_parallel_range_pool_init(&settings); - - for (int j = 0; j < num_tasks; j++) { - settings.userdata_chunk = ∑ - settings.userdata_chunk_size = sizeof(sum); - settings.func_finalize = task_range_iter_finalize_func; - - BLI_task_parallel_range_pool_push( - range_pool, 0, NUM_ITEMS, data[j], task_range_iter_func, &settings); - } - - BLI_task_parallel_range_pool_work_and_wait(range_pool); - - /* Those checks should ensure us all items of the listbase were processed once, and only once - - * as expected. */ - - for (int j = 0; j < num_tasks; j++) { - int expected_sum = 0; - for (int i = 0; i < NUM_ITEMS; i++) { - // EXPECT_EQ(data[j][i], i); - expected_sum += i; - } - EXPECT_EQ(data[j][NUM_ITEMS], expected_sum); - } - - /* A pool can be re-used untill it is freed. */ - - for (int j = 0; j < num_tasks; j++) { - memset(data[j], 0, sizeof(data[j])); - } - sum = 0; - - for (int j = 0; j < num_tasks; j++) { - settings.userdata_chunk = ∑ - settings.userdata_chunk_size = sizeof(sum); - settings.func_finalize = task_range_iter_finalize_func; - - BLI_task_parallel_range_pool_push( - range_pool, 0, NUM_ITEMS, data[j], task_range_iter_func, &settings); - } - - BLI_task_parallel_range_pool_work_and_wait(range_pool); - - BLI_task_parallel_range_pool_free(range_pool); - - /* Those checks should ensure us all items of the listbase were processed once, and only once - - * as expected. */ - - for (int j = 0; j < num_tasks; j++) { - int expected_sum = 0; - for (int i = 0; i < NUM_ITEMS; i++) { - // EXPECT_EQ(data[j][i], i); - expected_sum += i; - } - EXPECT_EQ(data[j][NUM_ITEMS], expected_sum); - } + EXPECT_EQ(sum, expected_sum); BLI_threadapi_exit(); } diff --git a/tests/gtests/blenlib/BLI_vector_set_test.cc b/tests/gtests/blenlib/BLI_vector_set_test.cc index 5ec51337aa7..bfdd47ccb13 100644 --- a/tests/gtests/blenlib/BLI_vector_set_test.cc +++ b/tests/gtests/blenlib/BLI_vector_set_test.cc @@ -1,4 +1,4 @@ -#include "BLI_vector_set.h" +#include "BLI_vector_set.hh" #include "testing/testing.h" using BLI::VectorSet; @@ -8,6 +8,7 @@ TEST(vector_set, DefaultConstructor) { IntVectorSet set; EXPECT_EQ(set.size(), 0); + EXPECT_TRUE(set.is_empty()); } TEST(vector_set, InitializerListConstructor_WithoutDuplicates) @@ -39,6 +40,17 @@ TEST(vector_set, Copy) EXPECT_EQ(set2.index(2), 1); } +TEST(vector_set, CopyAssignment) +{ + IntVectorSet set1 = {1, 2, 3}; + IntVectorSet set2 = {}; + set2 = set1; + EXPECT_EQ(set1.size(), 3); + EXPECT_EQ(set2.size(), 3); + EXPECT_EQ(set1.index(2), 1); + EXPECT_EQ(set2.index(2), 1); +} + TEST(vector_set, Move) { IntVectorSet set1 = {1, 2, 3}; @@ -47,11 +59,22 @@ TEST(vector_set, Move) EXPECT_EQ(set2.size(), 3); } +TEST(vector_set, MoveAssignment) +{ + IntVectorSet set1 = {1, 2, 3}; + IntVectorSet set2 = {}; + set2 = std::move(set1); + EXPECT_EQ(set1.size(), 0); + EXPECT_EQ(set2.size(), 3); +} + TEST(vector_set, AddNewIncreasesSize) { IntVectorSet set; + EXPECT_TRUE(set.is_empty()); EXPECT_EQ(set.size(), 0); set.add(5); + EXPECT_FALSE(set.is_empty()); EXPECT_EQ(set.size(), 1); } diff --git a/tests/gtests/blenlib/BLI_vector_test.cc b/tests/gtests/blenlib/BLI_vector_test.cc index 2402ee9627f..e5a1ca2b200 100644 --- a/tests/gtests/blenlib/BLI_vector_test.cc +++ b/tests/gtests/blenlib/BLI_vector_test.cc @@ -1,4 +1,4 @@ -#include "BLI_vector.h" +#include "BLI_vector.hh" #include "testing/testing.h" #include <forward_list> @@ -45,7 +45,7 @@ struct TestListValue { int value; }; -TEST(vector, IntrusiveListBaseConstructor) +TEST(vector, ListBaseConstructor) { TestListValue *value1 = new TestListValue{0, 0, 4}; TestListValue *value2 = new TestListValue{0, 0, 5}; @@ -55,7 +55,7 @@ TEST(vector, IntrusiveListBaseConstructor) BLI_addtail(&list, value1); BLI_addtail(&list, value2); BLI_addtail(&list, value3); - Vector<TestListValue *> vec(list, true); + Vector<TestListValue *> vec(list); EXPECT_EQ(vec.size(), 3); EXPECT_EQ(vec[0]->value, 4); @@ -345,14 +345,14 @@ TEST(vector, RemoveLast) EXPECT_EQ(vec.size(), 0); } -TEST(vector, Empty) +TEST(vector, IsEmpty) { IntVector vec; - EXPECT_TRUE(vec.empty()); + EXPECT_TRUE(vec.is_empty()); vec.append(1); - EXPECT_FALSE(vec.empty()); + EXPECT_FALSE(vec.is_empty()); vec.remove_last(); - EXPECT_TRUE(vec.empty()); + EXPECT_TRUE(vec.is_empty()); } TEST(vector, RemoveReorder) @@ -368,7 +368,7 @@ TEST(vector, RemoveReorder) vec.remove_and_reorder(0); EXPECT_EQ(vec[0], 7); vec.remove_and_reorder(0); - EXPECT_TRUE(vec.empty()); + EXPECT_TRUE(vec.is_empty()); } TEST(vector, RemoveFirstOccurrenceAndReorder) diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt index 119b54fa0d4..a0621448630 100644 --- a/tests/gtests/blenlib/CMakeLists.txt +++ b/tests/gtests/blenlib/CMakeLists.txt @@ -52,6 +52,7 @@ BLENDER_TEST(BLI_heap "bf_blenlib") BLENDER_TEST(BLI_heap_simple "bf_blenlib") BLENDER_TEST(BLI_index_range "bf_blenlib") BLENDER_TEST(BLI_kdopbvh "bf_blenlib;bf_intern_numaapi") +BLENDER_TEST(BLI_linear_allocator "bf_blenlib") BLENDER_TEST(BLI_linklist_lockfree "bf_blenlib;bf_intern_numaapi") BLENDER_TEST(BLI_listbase "bf_blenlib") BLENDER_TEST(BLI_map "bf_blenlib") diff --git a/tests/gtests/usd/abstract_hierarchy_iterator_test.cc b/tests/gtests/usd/abstract_hierarchy_iterator_test.cc index 56d8100c30a..160dd52f39a 100644 --- a/tests/gtests/usd/abstract_hierarchy_iterator_test.cc +++ b/tests/gtests/usd/abstract_hierarchy_iterator_test.cc @@ -29,7 +29,7 @@ extern "C" { #include <set> /* Mapping from ID.name to set of export hierarchy path. Duplicated objects can be exported - * multiple times, hence the set. */ + * multiple times with different export paths, hence the set. */ typedef std::map<std::string, std::set<std::string>> created_writers; using namespace USD; diff --git a/tests/gtests/usd/hierarchy_context_order_test.cc b/tests/gtests/usd/hierarchy_context_order_test.cc index 2068ea26227..4111fc7511e 100644 --- a/tests/gtests/usd/hierarchy_context_order_test.cc +++ b/tests/gtests/usd/hierarchy_context_order_test.cc @@ -44,9 +44,9 @@ TEST_F(HierarchyContextOrderTest, ObjectPointerTest) ctx_b.object = fake_pointer(2); ctx_b.duplicator = nullptr; - EXPECT_EQ(true, ctx_a < ctx_b); - EXPECT_EQ(false, ctx_b < ctx_a); - EXPECT_EQ(false, ctx_a < ctx_a); + EXPECT_LT(ctx_a, ctx_b); + EXPECT_FALSE(ctx_b < ctx_a); + EXPECT_FALSE(ctx_a < ctx_a); } TEST_F(HierarchyContextOrderTest, DuplicatorPointerTest) @@ -61,9 +61,9 @@ TEST_F(HierarchyContextOrderTest, DuplicatorPointerTest) ctx_b.duplicator = fake_pointer(1); ctx_b.export_name = "B"; - EXPECT_EQ(true, ctx_a < ctx_b); - EXPECT_EQ(false, ctx_b < ctx_a); - EXPECT_EQ(false, ctx_a < ctx_a); + EXPECT_LT(ctx_a, ctx_b); + EXPECT_FALSE(ctx_b < ctx_a); + EXPECT_FALSE(ctx_a < ctx_a); } TEST_F(HierarchyContextOrderTest, ExportParentTest) @@ -76,9 +76,9 @@ TEST_F(HierarchyContextOrderTest, ExportParentTest) ctx_b.object = fake_pointer(1); ctx_b.export_parent = fake_pointer(2); - EXPECT_EQ(true, ctx_a < ctx_b); - EXPECT_EQ(false, ctx_b < ctx_a); - EXPECT_EQ(false, ctx_a < ctx_a); + EXPECT_LT(ctx_a, ctx_b); + EXPECT_FALSE(ctx_b < ctx_a); + EXPECT_FALSE(ctx_a < ctx_a); } TEST_F(HierarchyContextOrderTest, TransitiveTest) @@ -107,17 +107,17 @@ TEST_F(HierarchyContextOrderTest, TransitiveTest) ctx_d.duplicator = nullptr; ctx_d.export_name = "D"; - EXPECT_EQ(true, ctx_a < ctx_b); - EXPECT_EQ(true, ctx_a < ctx_c); - EXPECT_EQ(true, ctx_a < ctx_d); - EXPECT_EQ(true, ctx_b < ctx_c); - EXPECT_EQ(true, ctx_b < ctx_d); - EXPECT_EQ(true, ctx_c < ctx_d); - - EXPECT_EQ(false, ctx_b < ctx_a); - EXPECT_EQ(false, ctx_c < ctx_a); - EXPECT_EQ(false, ctx_d < ctx_a); - EXPECT_EQ(false, ctx_c < ctx_b); - EXPECT_EQ(false, ctx_d < ctx_b); - EXPECT_EQ(false, ctx_d < ctx_c); + EXPECT_LT(ctx_a, ctx_b); + EXPECT_LT(ctx_a, ctx_c); + EXPECT_LT(ctx_a, ctx_d); + EXPECT_LT(ctx_b, ctx_c); + EXPECT_LT(ctx_b, ctx_d); + EXPECT_LT(ctx_c, ctx_d); + + EXPECT_FALSE(ctx_b < ctx_a); + EXPECT_FALSE(ctx_c < ctx_a); + EXPECT_FALSE(ctx_d < ctx_a); + EXPECT_FALSE(ctx_c < ctx_b); + EXPECT_FALSE(ctx_d < ctx_b); + EXPECT_FALSE(ctx_d < ctx_c); } diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 2d6dc4af40e..a3df01fdbe2 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -48,18 +48,14 @@ endfunction() # Run Python script outside Blender. function(add_python_test testname testscript) - if(MSVC) - add_test( - NAME ${testname} - COMMAND ${TEST_PYTHON_EXE} ${testscript} ${ARGN} - ) - else() - add_test( - NAME ${testname} - COMMAND ${testscript} ${ARGN} - ) + if(NOT TEST_PYTHON_EXE) + message(FATAL_ERROR "No Python configured for running tests, set TEST_PYTHON_EXE.") endif() + add_test( + NAME ${testname} + COMMAND ${TEST_PYTHON_EXE} ${testscript} ${ARGN} + ) set_tests_properties(${testname} PROPERTIES ENVIRONMENT LSAN_OPTIONS=exitcode=0) endfunction() diff --git a/tests/python/alembic_tests.py b/tests/python/alembic_tests.py index 9de1bc06d84..8c0315f1b68 100755..100644 --- a/tests/python/alembic_tests.py +++ b/tests/python/alembic_tests.py @@ -76,7 +76,7 @@ class AbstractAlembicTest(AbstractBlenderRunnerTest): output = output.replace('\r\n', '\n').replace('\r', '\n') if proc.returncode: - raise AbcPropError('Error %d running abcls:\n%s' % (proc.returncode, output)) + raise AbcPropError('Error %d running %s:\n%s' % (proc.returncode, ' '.join(command), output)) # Mapping from value type to callable that can convert a string to Python values. converters = { diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py index 79ba11fdd44..79ba11fdd44 100755..100644 --- a/tests/python/cycles_render_tests.py +++ b/tests/python/cycles_render_tests.py diff --git a/tests/python/eevee_render_tests.py b/tests/python/eevee_render_tests.py index a7130136d0a..a7130136d0a 100755..100644 --- a/tests/python/eevee_render_tests.py +++ b/tests/python/eevee_render_tests.py diff --git a/tests/python/ffmpeg_tests.py b/tests/python/ffmpeg_tests.py index 92734b5bc7d..92734b5bc7d 100755..100644 --- a/tests/python/ffmpeg_tests.py +++ b/tests/python/ffmpeg_tests.py diff --git a/tests/python/opengl_draw_tests.py b/tests/python/opengl_draw_tests.py index ab4df63afd9..ab4df63afd9 100755..100644 --- a/tests/python/opengl_draw_tests.py +++ b/tests/python/opengl_draw_tests.py diff --git a/tests/python/workbench_render_tests.py b/tests/python/workbench_render_tests.py index 155b54098a8..155b54098a8 100755..100644 --- a/tests/python/workbench_render_tests.py +++ b/tests/python/workbench_render_tests.py |