diff options
author | Rohan Rathi <rohanrathi08@gmail.com> | 2018-05-29 08:40:54 +0300 |
---|---|---|
committer | Rohan Rathi <rohanrathi08@gmail.com> | 2018-05-29 08:40:54 +0300 |
commit | 842245ac55ceca67863cdad252d8959cefb789c5 (patch) | |
tree | 3301dd7fc5324ccd8b2ceea0d389f7d55b413fa8 | |
parent | 5d2d36b0686d7253f9d61c00a63d273aba17677a (diff) | |
parent | 6946c413402c05a838e98a3823bf926df8cfe8d1 (diff) |
Merge branch 'blender2.8' into soc-2018-bevel
319 files changed, 7434 insertions, 2254 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 74e6596de82..02aa3697d00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1548,7 +1548,12 @@ else() endif() # Visual Studio has all standards it supports available by default -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "Intel") +# Clang on windows copies this behavior and does not support these switches +if( + CMAKE_COMPILER_IS_GNUCC OR + (CMAKE_C_COMPILER_ID MATCHES "Clang" AND (NOT MSVC)) OR + (CMAKE_C_COMPILER_ID MATCHES "Intel") +) # Use C99 + GNU extensions, works with GCC, Clang, ICC if(WITH_C11) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") diff --git a/build_files/build_environment/patches/boost.diff b/build_files/build_environment/patches/boost.diff index ea3ec035518..41b40d7a915 100644 --- a/build_files/build_environment/patches/boost.diff +++ b/build_files/build_environment/patches/boost.diff @@ -13,3 +13,25 @@ -# pragma message("Unknown compiler version - please run the configure tests and report the results") -# endif -#endif +--- a/boost/type_traits/has_nothrow_assign.hpp 2015-12-13 05:49:42 -0700 ++++ b/boost/type_traits/has_nothrow_assign.hpp 2018-05-27 11:11:02 -0600 +@@ -24,7 +24,7 @@ + #include <boost/type_traits/remove_reference.hpp> + #endif + #endif +-#if defined(__GNUC__) || defined(__SUNPRO_CC) ++#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__clang__) + #include <boost/type_traits/is_const.hpp> + #include <boost/type_traits/is_volatile.hpp> + #include <boost/type_traits/is_assignable.hpp> +--- a/boost/type_traits/has_nothrow_constructor.hpp 2015-12-13 05:49:42 -0700 ++++ b/boost/type_traits/has_nothrow_constructor.hpp 2018-05-27 11:11:02 -0600 +@@ -17,7 +17,7 @@ + #if defined(BOOST_MSVC) || defined(BOOST_INTEL) + #include <boost/type_traits/has_trivial_constructor.hpp> + #endif +-#if defined(__GNUC__ ) || defined(__SUNPRO_CC) ++#if defined(__GNUC__ ) || defined(__SUNPRO_CC) || defined(__clang__) + #include <boost/type_traits/is_default_constructible.hpp> + #endif + diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff index fcb5ec4165f..960a2506374 100644 --- a/build_files/build_environment/patches/osl.diff +++ b/build_files/build_environment/patches/osl.diff @@ -10,3 +10,29 @@ diff -Naur osl/src/external_osl/src/cmake/flexbison.cmake osl_bak/src/external_o MAIN_DEPENDENCY ${flexsrc} DEPENDS ${${compiler_headers}} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) +--- a/src/include/OSL/oslconfig.h 2016-10-31 16:48:19 -0600 ++++ b/src/include/OSL/oslconfig.h 2018-05-27 11:18:08 -0600 +@@ -44,12 +44,18 @@ + // same if another packages is compiling against OSL and using these headers + // (OSL may be C++11 but the client package may be older, or vice versa -- + // use these two symbols to differentiate these cases, when important). +-#if (__cplusplus >= 201402L) +-# define OSL_CPLUSPLUS_VERSION 14 +-#elif (__cplusplus >= 201103L) +-# define OSL_CPLUSPLUS_VERSION 11 ++ ++// Force C++03 for MSVC in blender since svn the libraries are build with that ++#if !defined(_MSC_VER) ++ #if (__cplusplus >= 201402L) ++ # define OSL_CPLUSPLUS_VERSION 14 ++ #elif (__cplusplus >= 201103L) ++ # define OSL_CPLUSPLUS_VERSION 11 ++ #else ++ # define OSL_CPLUSPLUS_VERSION 3 /* presume C++03 */ ++ #endif + #else +-# define OSL_CPLUSPLUS_VERSION 3 /* presume C++03 */ ++ # define OSL_CPLUSPLUS_VERSION 3 /* presume C++03 */ + #endif + + // Symbol export defines diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 7e978a71ad4..c14f6013394 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -29,7 +29,15 @@ if(NOT MSVC) message(FATAL_ERROR "Compiler is unsupported") endif() -# Libraries configuration for Windows when compiling with MSVC. +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set(MSVC_CLANG On) + set(MSVC_REDIST_DIR $ENV{VCToolsRedistDir}) + if (DEFINED MSVC_REDIST_DIR) + file(TO_CMAKE_PATH ${MSVC_REDIST_DIR} MSVC_REDIST_DIR) + else() + message("Unable to detect the Visual Studio redist directory, copying of the runtime dlls will not work, try running from the visual studio developer prompt.") + endif() +endif() set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_FOLDERS}) @@ -119,8 +127,18 @@ set(CMAKE_INSTALL_OPENMP_LIBRARIES ${WITH_OPENMP}) set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .) include(InstallRequiredSystemLibraries) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP") +remove_cc_flag("/MDd" "/MD") + +if(MSVC_CLANG) # Clangs version of cl doesn't support all flags + if(NOT WITH_CXX11) # C++11 is on by default in clang-cl and can't be turned off, if c++11 is not enabled in blender repress some c++11 related warnings. + set(CXX_WARN_FLAGS "-Wno-inconsistent-missing-override") + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP") +endif() set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") diff --git a/build_files/windows/autodetect_msvc.cmd b/build_files/windows/autodetect_msvc.cmd new file mode 100644 index 00000000000..6fce3829e7b --- /dev/null +++ b/build_files/windows/autodetect_msvc.cmd @@ -0,0 +1,17 @@ +echo No explicit msvc version requested, autodetecting version. + +call "%~dp0\detect_msvc2013.cmd" +if %ERRORLEVEL% EQU 0 goto DetectionComplete + +call "%~dp0\detect_msvc2015.cmd" +if %ERRORLEVEL% EQU 0 goto DetectionComplete + +call "%~dp0\detect_msvc2017.cmd" +if %ERRORLEVEL% EQU 0 goto DetectionComplete + +echo Compiler Detection failed. Use verbose switch for more information. +exit /b 1 + +:DetectionComplete +echo Compiler Detection successfull, detected VS%BUILD_VS_YEAR% +exit /b 0
\ No newline at end of file diff --git a/build_files/windows/build_msbuild.cmd b/build_files/windows/build_msbuild.cmd new file mode 100644 index 00000000000..6ca5f1b0df8 --- /dev/null +++ b/build_files/windows/build_msbuild.cmd @@ -0,0 +1,26 @@ +if "%NOBUILD%"=="1" goto EOF +echo %TIME% > %BUILD_DIR%\buildtime.txt +msbuild ^ + %BUILD_DIR%\Blender.sln ^ + /target:build ^ + /property:Configuration=%BUILD_TYPE% ^ + /maxcpucount:2 ^ + /verbosity:minimal ^ + /p:platform=%MSBUILD_PLATFORM% ^ + /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log + if errorlevel 1 ( + echo Error during build, see %BUILD_DIR%\Build.log for details + exit /b 1 + ) + +msbuild ^ + %BUILD_DIR%\INSTALL.vcxproj ^ + /property:Configuration=%BUILD_TYPE% ^ + /verbosity:minimal ^ + /p:platform=%MSBUILD_PLATFORM% + if errorlevel 1 ( + echo Error during install phase + exit /b 1 + ) +echo %TIME% >> %BUILD_DIR%\buildtime.txt +:EOF
\ No newline at end of file diff --git a/build_files/windows/build_ninja.cmd b/build_files/windows/build_ninja.cmd new file mode 100644 index 00000000000..4f1a5408c28 --- /dev/null +++ b/build_files/windows/build_ninja.cmd @@ -0,0 +1,16 @@ +if "%NOBUILD%"=="1" goto EOF +set HAS_ERROR= +cd %BUILD_DIR% +echo %TIME% > buildtime.txt +ninja install +if errorlevel 1 ( + set HAS_ERROR=1 + ) +echo %TIME% >>buildtime.txt +cd %BLENDER_DIR% + +if "%HAS_ERROR%" == "1" ( + echo Error during build + exit /b 1 +) +:EOF
\ No newline at end of file diff --git a/build_files/windows/check_libraries.cmd b/build_files/windows/check_libraries.cmd new file mode 100644 index 00000000000..c8aad7c9adb --- /dev/null +++ b/build_files/windows/check_libraries.cmd @@ -0,0 +1,54 @@ +if "%BUILD_VS_YEAR%"=="2013" set BUILD_VS_LIBDIRPOST=vc12 +if "%BUILD_VS_YEAR%"=="2015" set BUILD_VS_LIBDIRPOST=vc14 +if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc14 + +if "%BUILD_ARCH%"=="x64" ( + set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST% +) else if "%BUILD_ARCH%"=="x86" ( + set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST% +) +set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%" + +if NOT "%verbose%" == "" ( + echo Library Directory = "%BUILD_VS_LIBDIR%" +) +if NOT EXIST %BUILD_VS_LIBDIR% ( + rem libs not found, but svn is on the system + echo + if not "%SVN%"=="" ( + echo. + echo The required external libraries in %BUILD_VS_LIBDIR% are missing + echo. + set /p GetLibs= "Would you like to download them? (y/n)" + if /I "!GetLibs!"=="Y" ( + echo. + echo Downloading %BUILD_VS_SVNDIR% libraries, please wait. + echo. +:RETRY + "%SVN%" checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR% + if errorlevel 1 ( + set /p LibRetry= "Error during donwload, retry? y/n" + if /I "!LibRetry!"=="Y" ( + cd %BUILD_VS_LIBDIR% + "%SVN%" cleanup + cd %BLENDER_DIR% + goto RETRY + ) + echo. + echo Error: Download of external libraries failed. + echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in + echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successfull blender build + echo. + exit /b 1 + ) + ) + ) +) + +if NOT EXIST %BUILD_VS_LIBDIR% ( + echo. + echo Error: Required libraries not found at "%BUILD_VS_LIBDIR%" + echo This is needed for building, aborting! + echo. + exit /b 1 +)
\ No newline at end of file diff --git a/build_files/windows/check_spaces_in_path.cmd b/build_files/windows/check_spaces_in_path.cmd new file mode 100644 index 00000000000..2e9300ae6d5 --- /dev/null +++ b/build_files/windows/check_spaces_in_path.cmd @@ -0,0 +1,6 @@ +set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =% + +if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" ( + echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting.... + exit /b 1 +)
\ No newline at end of file diff --git a/build_files/windows/check_submodules.cmd b/build_files/windows/check_submodules.cmd new file mode 100644 index 00000000000..c0c64148dd7 --- /dev/null +++ b/build_files/windows/check_submodules.cmd @@ -0,0 +1,20 @@ +if NOT exist "%BLENDER_DIR%/source/tools" ( + echo Checking out sub-modules + if not "%GIT%" == "" ( + "%GIT%" submodule update --init --recursive --progress + if errorlevel 1 goto FAIL + "%GIT%" submodule foreach git checkout master + if errorlevel 1 goto FAIL + "%GIT%" submodule foreach git pull --rebase origin master + if errorlevel 1 goto FAIL + goto EOF + ) else ( + echo Blender submodules not found, and git not found in path to retrieve them. + goto FAIL + ) +) +goto EOF + +:FAIL +exit /b 1 +:EOF
\ No newline at end of file diff --git a/build_files/windows/configure_msbuild.cmd b/build_files/windows/configure_msbuild.cmd new file mode 100644 index 00000000000..f06f3e317ee --- /dev/null +++ b/build_files/windows/configure_msbuild.cmd @@ -0,0 +1,67 @@ +set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%WINDOWS_ARCH%" %TESTS_CMAKE_ARGS% + +if "%BUILD_ARCH%"=="x64" ( + set MSBUILD_PLATFORM=x64 +) else if "%BUILD_ARCH%"=="x86" ( + set MSBUILD_PLATFORM=win32 + if "%WITH_CLANG%"=="1" ( + echo Clang not supported for X86 + exit /b 1 + ) +) + +if "%WITH_CLANG%"=="1" ( + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -T"LLVM-vs2017" +) + +if NOT EXIST %BUILD_DIR%\nul ( + mkdir %BUILD_DIR% +) + +if "%MUST_CLEAN%"=="1" ( + echo Cleaning %BUILD_DIR% + msbuild ^ + %BUILD_DIR%\Blender.sln ^ + /target:clean ^ + /property:Configuration=%BUILD_TYPE% ^ + /verbosity:minimal ^ + /p:platform=%MSBUILD_PLATFORM% +) + +if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1 +if "%NOBUILD%"=="1" set MUST_CONFIGURE=1 + +if "%MUST_CONFIGURE%"=="1" ( + + if NOT "%verbose%" == "" ( + echo %CMAKE% %BUILD_CMAKE_ARGS% -H%BLENDER_DIR% -B%BUILD_DIR% + ) + + cmake ^ + %BUILD_CMAKE_ARGS% ^ + -H%BLENDER_DIR% ^ + -B%BUILD_DIR% + + if %ERRORLEVEL% NEQ 0 ( + echo "Configuration Failed" + exit /b 1 + ) +) + +echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd +echo "%CMAKE%" . >> %BUILD_DIR%\rebuild.cmd +echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd +echo msbuild ^ + %BUILD_DIR%\Blender.sln ^ + /target:build ^ + /property:Configuration=%BUILD_TYPE% ^ + /maxcpucount:2 ^ + /verbosity:minimal ^ + /p:platform=%MSBUILD_PLATFORM% ^ + /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log >> %BUILD_DIR%\rebuild.cmd +echo msbuild ^ + %BUILD_DIR%\INSTALL.vcxproj ^ + /property:Configuration=%BUILD_TYPE% ^ + /verbosity:minimal ^ + /p:platform=%MSBUILD_PLATFORM% >> %BUILD_DIR%\rebuild.cmd +echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
\ No newline at end of file diff --git a/build_files/windows/configure_ninja.cmd b/build_files/windows/configure_ninja.cmd new file mode 100644 index 00000000000..f882ca3dbf0 --- /dev/null +++ b/build_files/windows/configure_ninja.cmd @@ -0,0 +1,64 @@ +set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Ninja" %TESTS_CMAKE_ARGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% + +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 + if DEFINED LLVM_DIR ( + if NOT "%verbose%" == "" ( + echo LLVM Detected at "%LLVM_DIR%" + ) + goto DetectionComplete + ) + + REM Check 32 bits + for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C + if DEFINED LLVM_DIR ( + if NOT "%verbose%" == "" ( + echo LLVM Detected at "%LLVM_DIR%" + ) + goto DetectionComplete + ) + echo LLVM not found + exit /b 1 + +:DetectionComplete + set CC=%LLVM_DIR%\bin\clang-cl + set CXX=%LLVM_DIR%\bin\clang-cl + rem build and tested against 2017 15.7 + set CFLAGS=-m64 -fmsc-version=1914 + set CXXFLAGS=-m64 -fmsc-version=1914 +) + +if NOT "%verbose%" == "" ( + echo BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% +) + +if NOT EXIST %BUILD_DIR%\nul ( + mkdir %BUILD_DIR% +) + +if "%MUST_CLEAN%"=="1" ( + echo Cleaning %BUILD_DIR% + cd %BUILD_DIR% + %CMAKE% cmake --build . --config Clean +) + +if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1 +if "%NOBUILD%"=="1" set MUST_CONFIGURE=1 + +if "%MUST_CONFIGURE%"=="1" ( + cmake ^ + %BUILD_CMAKE_ARGS% ^ + -H%BLENDER_DIR% ^ + -B%BUILD_DIR% + + if %ERRORLEVEL% NEQ 0 ( + echo "Configuration Failed" + exit /b 1 + ) +) + +echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd +echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd +echo ninja install >> %BUILD_DIR%\rebuild.cmd +echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
\ No newline at end of file diff --git a/build_files/windows/detect_architecture.cmd b/build_files/windows/detect_architecture.cmd new file mode 100644 index 00000000000..cd211668b7f --- /dev/null +++ b/build_files/windows/detect_architecture.cmd @@ -0,0 +1,16 @@ +if "%BUILD_ARCH%"=="" ( + if "%PROCESSOR_ARCHITECTURE%" == "AMD64" ( + set WINDOWS_ARCH= Win64 + set BUILD_ARCH=x64 + ) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" ( + set WINDOWS_ARCH= Win64 + set BUILD_ARCH=x64 + ) else ( + set WINDOWS_ARCH= + set BUILD_ARCH=x86 + ) +) else if "%BUILD_ARCH%"=="x64" ( + set WINDOWS_ARCH= Win64 +) else if "%BUILD_ARCH%"=="x86" ( + set WINDOWS_ARCH= +) diff --git a/build_files/windows/detect_msvc2013.cmd b/build_files/windows/detect_msvc2013.cmd new file mode 100644 index 00000000000..5688d31c4b6 --- /dev/null +++ b/build_files/windows/detect_msvc2013.cmd @@ -0,0 +1,3 @@ +set BUILD_VS_VER=12 +set BUILD_VS_YEAR=2013 +call "%~dp0\detect_msvc_classic.cmd"
\ No newline at end of file diff --git a/build_files/windows/detect_msvc2015.cmd b/build_files/windows/detect_msvc2015.cmd new file mode 100644 index 00000000000..0818d1dfffc --- /dev/null +++ b/build_files/windows/detect_msvc2015.cmd @@ -0,0 +1,3 @@ +set BUILD_VS_VER=14 +set BUILD_VS_YEAR=2015 +call "%~dp0\detect_msvc_classic.cmd"
\ No newline at end of file diff --git a/build_files/windows/detect_msvc2017.cmd b/build_files/windows/detect_msvc2017.cmd new file mode 100644 index 00000000000..6a82adb5a4d --- /dev/null +++ b/build_files/windows/detect_msvc2017.cmd @@ -0,0 +1,70 @@ +if NOT "%verbose%" == "" ( + echo Detecting msvc 2017 +) +set BUILD_VS_VER=15 +set ProgramFilesX86=%ProgramFiles(x86)% +if not exist "%ProgramFilesX86%" set ProgramFilesX86=%ProgramFiles% + +set vs_where=%ProgramFilesX86%\Microsoft Visual Studio\Installer\vswhere.exe +if not exist "%vs_where%" ( + if NOT "%verbose%" == "" ( + echo Visual Studio 2017 ^(15.2 or newer^) is not detected + goto FAIL + ) +) +for /f "usebackq tokens=1* delims=: " %%i in (`"%vs_where%" -latest %VSWHERE_ARGS% -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64`) do ( + if /i "%%i"=="installationPath" set VS_InstallDir=%%j +) + +if "%VS_InstallDir%"=="" ( + if NOT "%verbose%" == "" ( + echo Visual Studio is detected but the "Desktop development with C++" workload has not been instlled + goto FAIL + ) +) + +set VCVARS=%VS_InstallDir%\VC\Auxiliary\Build\vcvarsall.bat +if exist "%VCVARS%" ( + call "%VCVARS%" %BUILD_ARCH% +) else ( + if NOT "%verbose%" == "" ( + echo "%VCVARS%" not found + ) + goto FAIL +) + +rem try msbuild +msbuild /version > NUL +if errorlevel 1 ( + if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% msbuild not found + ) + goto FAIL +) + +if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% msbuild found +) + +REM try the c++ compiler +cl 2> NUL 1>&2 +if errorlevel 1 ( + if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler not found + ) + goto FAIL +) + +if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler found +) + +if NOT "%verbose%" == "" ( + echo Visual Studio 2017 is detected successfully +) +goto EOF + +:FAIL +exit /b 1 + +:EOF diff --git a/build_files/windows/detect_msvc_classic.cmd b/build_files/windows/detect_msvc_classic.cmd new file mode 100644 index 00000000000..61bfcf92ddf --- /dev/null +++ b/build_files/windows/detect_msvc_classic.cmd @@ -0,0 +1,69 @@ +if NOT "%verbose%" == "" ( + echo Detecting msvc %BUILD_VS_YEAR% +) +set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC" +for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v ProductDir 2^>nul`) DO set MSVC_VC_DIR=%%C +if DEFINED MSVC_VC_DIR ( + if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% on Win64 detected at "%MSVC_VC_DIR%" + ) + goto msvc_detect_finally +) + +REM Check 32 bits +set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC" +for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v ProductDir 2^>nul`) DO set MSVC_VC_DIR=%%C +if DEFINED MSVC_VC_DIR ( + if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% on Win32 detected at "%MSVC_VC_DIR%" + ) + goto msvc_detect_finally +) +if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% not found. +) +goto FAIL +:msvc_detect_finally +set VCVARS=%MSVC_VC_DIR%\vcvarsall.bat +if not exist "%VCVARS%" ( + echo "%VCVARS%" not found. + goto FAIL +) + +call "%vcvars%" %BUILD_ARCH% + +rem try msbuild +msbuild /version > NUL +if errorlevel 1 ( + if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% msbuild not found + ) + goto FAIL +) + +if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% msbuild found +) + +REM try the c++ compiler +cl 2> NUL 1>&2 +if errorlevel 1 ( + if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler not found + ) + goto FAIL +) + +if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler found +) +goto DetectionComplete + +:FAIL +exit /b 1 + +:DetectionComplete +if NOT "%verbose%" == "" ( + echo Visual Studio %BUILD_VS_YEAR% Detected successfuly +) +exit /b 0 diff --git a/build_files/windows/find_dependencies.cmd b/build_files/windows/find_dependencies.cmd new file mode 100644 index 00000000000..219e9801831 --- /dev/null +++ b/build_files/windows/find_dependencies.cmd @@ -0,0 +1,13 @@ +REM find all dependencies and set the corresponding environement variables. +for %%X in (svn.exe) do (set SVN=%%~$PATH:X) +for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X) +for %%X in (git.exe) do (set GIT=%%~$PATH:X) +if NOT "%verbose%" == "" ( + echo svn : %SVN% + echo cmake : %CMAKE% + echo git : %GIT% +) +if "%CMAKE%" == "" ( + echo Cmake not found in path, required for building, exiting... + exit /b 1 +)
\ No newline at end of file diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd new file mode 100644 index 00000000000..016bc875c3b --- /dev/null +++ b/build_files/windows/parse_arguments.cmd @@ -0,0 +1,81 @@ +set BUILD_DIR=%BLENDER_DIR%..\build_windows +set BUILD_TYPE=Release +:argv_loop +if NOT "%1" == "" ( + + REM Help Message + if "%1" == "help" ( + set SHOW_HELP=1 + goto EOF + ) + REM Build Types + if "%1" == "debug" ( + set BUILD_TYPE=Debug + REM Build Configurations + ) else if "%1" == "noge" ( + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_GAMEENGINE=OFF -DWITH_PLAYER=OFF + set BUILD_NGE=_noge + ) else if "%1" == "builddir" ( + set BUILD_DIR_OVERRRIDE="%BLENDER_DIR%..\%2" + shift /1 + ) else if "%1" == "with_tests" ( + set TESTS_CMAKE_ARGS=-DWITH_GTESTS=On + ) else if "%1" == "full" ( + set TARGET=Full + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ + -C"%BLENDER_DIR%\build_files\cmake\config\blender_full.cmake" + ) else if "%1" == "lite" ( + set TARGET=Lite + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_lite.cmake" + ) else if "%1" == "cycles" ( + set TARGET=Cycles + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\cycles_standalone.cmake" + ) else if "%1" == "headless" ( + set TARGET=Headless + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_headless.cmake" + ) else if "%1" == "bpy" ( + set TARGET=Bpy + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake" + ) else if "%1" == "clang" ( + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% + set WITH_CLANG=1 + ) else if "%1" == "release" ( + set TARGET=Release + ) else if "%1" == "x86" ( + set BUILD_ARCH=x86 + ) else if "%1" == "x64" ( + set BUILD_ARCH=x64 + ) else if "%1" == "2017" ( + set BUILD_VS_YEAR=2017 + ) else if "%1" == "2017pre" ( + set BUILD_VS_YEAR=2017 + set VSWHERE_ARGS=-prerelease + ) else if "%1" == "2015" ( + set BUILD_VS_YEAR=2015 + ) else if "%1" == "2013" ( + set BUILD_VS_YEAR=2013 + ) else if "%1" == "packagename" ( + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2" + shift /1 + ) else if "%1" == "nobuild" ( + set NOBUILD=1 + ) else if "%1" == "showhash" ( + SET BUILD_SHOW_HASHES=1 + REM Non-Build Commands + ) else if "%1" == "update" ( + SET BUILD_UPDATE=1 + ) else if "%1" == "ninja" ( + SET BUILD_WITH_NINJA=1 + ) else if "%1" == "clean" ( + set MUST_CLEAN=1 + ) else if "%1" == "verbose" ( + set VERBOSE=1 + ) else ( + echo Command "%1" unknown, aborting! + exit /b 1 + ) + shift /1 + goto argv_loop +) +:EOF +exit /b 0
\ No newline at end of file diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd new file mode 100644 index 00000000000..d9a50a7f809 --- /dev/null +++ b/build_files/windows/reset_variables.cmd @@ -0,0 +1,24 @@ +rem reset all variables so they do not get accidentally get carried over from previous builds +set BUILD_DIR_OVERRRIDE= +set BUILD_CMAKE_ARGS= +set BUILD_ARCH= +set BUILD_VS_VER= +set BUILD_VS_YEAR= +set BUILD_VS_LIBDIRPOST= +set BUILD_VS_LIBDIR= +set BUILD_VS_SVNDIR= +set BUILD_NGE= +set KEY_NAME= +set MSBUILD_PLATFORM= +set MUST_CLEAN= +set NOBUILD= +set TARGET= +set VERBOSE= +set WINDOWS_ARCH= +set TESTS_CMAKE_ARGS= +set VSWHERE_ARGS= +set BUILD_UPDATE= +set BUILD_SHOW_HASHES= +set SHOW_HELP= +set BUILD_WITH_NINJA= +set WITH_CLANG=
\ No newline at end of file diff --git a/build_files/windows/set_build_dir.cmd b/build_files/windows/set_build_dir.cmd new file mode 100644 index 00000000000..8842a52eb5b --- /dev/null +++ b/build_files/windows/set_build_dir.cmd @@ -0,0 +1,4 @@ +set BUILD_DIR=%BUILD_DIR%_%TARGET%%BUILD_NGE%_%BUILD_ARCH%_vc%BUILD_VS_VER%_%BUILD_TYPE% +if NOT "%BUILD_DIR_OVERRRIDE%"=="" ( + set BUILD_DIR=%BUILD_DIR_OVERRRIDE% +)
\ No newline at end of file diff --git a/build_files/windows/show_hashes.cmd b/build_files/windows/show_hashes.cmd new file mode 100644 index 00000000000..ff036733946 --- /dev/null +++ b/build_files/windows/show_hashes.cmd @@ -0,0 +1,12 @@ +if "%GIT%" == "" ( + echo Git not found, cannot show hashes. + goto EOF +) +cd "%BLENDER_DIR%" +for /f "delims=" %%i in ('%GIT% rev-parse HEAD') do echo Branch_hash=%%i +cd "%BLENDER_DIR%/release/datafiles/locale" +for /f "delims=" %%i in ('%GIT% rev-parse HEAD') do echo Locale_hash=%%i +cd "%BLENDER_DIR%/release/scripts/addons" +for /f "delims=" %%i in ('%GIT% rev-parse HEAD') do echo Addons_Hash=%%i +cd "%BLENDER_DIR%" +:EOF
\ No newline at end of file diff --git a/build_files/windows/show_help.cmd b/build_files/windows/show_help.cmd new file mode 100644 index 00000000000..0524e8a84fc --- /dev/null +++ b/build_files/windows/show_help.cmd @@ -0,0 +1,29 @@ +echo. +echo Convenience targets +echo - release ^(identical to the official blender.org builds^) +echo - full ^(same as release minus the cuda kernels^) +echo - lite +echo - headless +echo - cycles +echo - bpy +echo. +echo Utilities ^(not associated with building^) +echo - clean ^(Target must be set^) +echo - update +echo - nobuild ^(only generate project files^) +echo - showhash ^(Show git hashes of source tree^) +echo. +echo Configuration options +echo - verbose ^(enable diagnostic output during configuration^) +echo - with_tests ^(enable building unit tests^) +echo - noge ^(disable building game enginge and player^) +echo - debug ^(Build an unoptimized debuggable build^) +echo - packagename [newname] ^(override default cpack package name^) +echo - buildir [newdir] ^(override default build folder^) +echo - x86 ^(override host auto-detect and build 32 bit code^) +echo - x64 ^(override host auto-detect and build 64 bit code^) +echo - 2013 ^(build with visual studio 2013^) +echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL] +echo - 2017 ^(build with visual studio 2017^) [EXPERIMENTAL] +echo - 2017pre ^(build with visual studio 2017 pre-release^) [EXPERIMENTAL] +echo. diff --git a/build_files/windows/update_sources.cmd b/build_files/windows/update_sources.cmd new file mode 100644 index 00000000000..22d93fabb95 --- /dev/null +++ b/build_files/windows/update_sources.cmd @@ -0,0 +1,16 @@ +if "%SVN%" == "" ( + echo svn not found, cannot update libraries + goto UPDATE_GIT +) +"%SVN%" up "%BLENDER_DIR%/../lib/*" + +:UPDATE_GIT + +if "%GIT%" == "" ( + echo Git not found, cannot update code + goto EOF +) +"%GIT%" pull --rebase +"%GIT%" submodule foreach git pull --rebase origin master + +:EOF
\ No newline at end of file diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h index fc8ae50fed7..cb535e1b78f 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h @@ -335,7 +335,7 @@ template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { _mm_p template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) +#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && !defined(__clang__) // The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010 // Direct of the struct members fixed bug #62. template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { return a.m128_f32[0]; } diff --git a/extern/Eigen3/patches/blender.diff b/extern/Eigen3/patches/blender.diff new file mode 100644 index 00000000000..3d7ba6e7006 --- /dev/null +++ b/extern/Eigen3/patches/blender.diff @@ -0,0 +1,12 @@ +diff -Naur c:\blender-git\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h k:\BlenderGit\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h +--- c:\blender-git\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h 2018-05-25 13:29:14 -0600 ++++ k:\BlenderGit\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h 2018-05-26 19:56:36 -0600 +@@ -335,7 +335,7 @@ + template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } + template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } + +-#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) ++#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && !defined(__clang__) + // The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010 + // Direct of the struct members fixed bug #62. + template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { return a.m128_f32[0]; } diff --git a/extern/bullet2/patches/blender.patch b/extern/bullet2/patches/blender.patch index 96357ddd315..cb3bf2ba38a 100644 --- a/extern/bullet2/patches/blender.patch +++ b/extern/bullet2/patches/blender.patch @@ -1,3 +1,34 @@ +diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h +--- a/extern/bullet2/src/LinearMath/btScalar.h ++++ b/extern/bullet2/src/LinearMath/btScalar.h +@@ -16,6 +16,9 @@ + + #ifndef BT_SCALAR_H + #define BT_SCALAR_H ++#if defined(_MSC_VER) && defined(__clang__) /* clang supplies it's own overloads already */ ++#define BT_NO_SIMD_OPERATOR_OVERLOADS ++#endif + + #ifdef BT_MANAGED_CODE + //Aligned data types not supported in managed code +@@ -83,7 +86,7 @@ + #ifdef BT_USE_SSE + + #if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default) +- #define BT_ALLOW_SSE4 ++ //#define BT_ALLOW_SSE4 //disable this cause blender targets sse2 + #endif //(_MSC_FULL_VER >= 160040219) + + //BT_USE_SSE_IN_API is disabled under Windows by default, because +@@ -102,7 +105,7 @@ + #endif //__MINGW32__ + + #ifdef BT_DEBUG +- #ifdef _MSC_VER ++ #if defined(_MSC_VER) && !defined(__clang__) + #include <stdio.h> + #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }} + #else//_MSC_VER diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index be9eca6..ec40c96 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index 0bfd255bdb4..898669f86e2 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -16,6 +16,9 @@ subject to the following restrictions: #ifndef BT_SCALAR_H #define BT_SCALAR_H +#if defined(_MSC_VER) && defined(__clang__) /* clang supplies it's own overloads already */ +#define BT_NO_SIMD_OPERATOR_OVERLOADS +#endif #ifdef BT_MANAGED_CODE //Aligned data types not supported in managed code @@ -83,7 +86,7 @@ inline int btGetVersion() #ifdef BT_USE_SSE #if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default) - #define BT_ALLOW_SSE4 + //#define BT_ALLOW_SSE4 //disable this cause blender targets sse2 #endif //(_MSC_FULL_VER >= 160040219) //BT_USE_SSE_IN_API is disabled under Windows by default, because @@ -102,7 +105,7 @@ inline int btGetVersion() #endif //__MINGW32__ #ifdef BT_DEBUG - #ifdef _MSC_VER + #if defined(_MSC_VER) && !defined(__clang__) #include <stdio.h> #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }} #else//_MSC_VER diff --git a/intern/atomic/intern/atomic_ops_msvc.h b/intern/atomic/intern/atomic_ops_msvc.h index c24a9095735..39ed4efe3a8 100644 --- a/intern/atomic/intern/atomic_ops_msvc.h +++ b/intern/atomic/intern/atomic_ops_msvc.h @@ -40,7 +40,11 @@ #include <windows.h> #include <intrin.h> -/******************************************************************************/ +#if defined (__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wincompatible-pointer-types" +#endif + /* 64-bit operations. */ #if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8) /* Unsigned */ @@ -205,4 +209,9 @@ ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b) #endif } + +#if defined (__clang__) +# pragma GCC diagnostic pop +#endif + #endif /* __ATOMIC_OPS_MSVC_H__ */ diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index c3305ac3dd8..100a52625d1 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -31,7 +31,7 @@ elseif(NOT WITH_CPU_SSE) set(CXX_HAS_SSE FALSE) set(CXX_HAS_AVX FALSE) set(CXX_HAS_AVX2 FALSE) -elseif(WIN32 AND MSVC) +elseif(WIN32 AND MSVC AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CXX_HAS_SSE TRUE) set(CXX_HAS_AVX TRUE) set(CXX_HAS_AVX2 TRUE) @@ -306,7 +306,7 @@ if(WITH_CYCLES_CUDA_BINARIES AND (NOT WITH_CYCLES_CUBIN_COMPILER)) elseif(${CUDA_VERSION} EQUAL "9.1") set(MAX_MSVC 1911) endif() - if(NOT MSVC_VERSION LESS ${MAX_MSVC}) + if(NOT MSVC_VERSION LESS ${MAX_MSVC} OR CMAKE_C_COMPILER_ID MATCHES "Clang") message(STATUS "nvcc not supported for this compiler version, using cycles_cubin_cc instead.") set(WITH_CYCLES_CUBIN_COMPILER ON) endif() diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py index 19f2ecc9d1a..dd92ce642d4 100644 --- a/intern/cycles/blender/addon/osl.py +++ b/intern/cycles/blender/addon/osl.py @@ -112,7 +112,8 @@ def update_script_node(node, report): if ok: # now update node with new sockets - ok = _cycles.osl_update_node(node.id_data.as_pointer(), node.as_pointer(), oso_path) + data = bpy.data.as_pointer() + ok = _cycles.osl_update_node(data, node.id_data.as_pointer(), node.as_pointer(), oso_path) if not ok: report({'ERROR'}, "OSL query failed to open " + oso_path) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index eeb059f79f1..f7749c16400 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -909,9 +909,9 @@ class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel): col.prop(lamp, "shape", text="") sub = col.column(align=True) - if lamp.shape == 'SQUARE': + if lamp.shape in {'SQUARE', 'DISK'}: sub.prop(lamp, "size") - elif lamp.shape == 'RECTANGLE': + elif lamp.shape in {'RECTANGLE', 'ELLIPSE'}: sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") @@ -1604,7 +1604,7 @@ classes = ( def register(): from bpy.utils import register_class - bpy.types.RENDER_PT_render.append(draw_device) + bpy.types.RENDER_PT_context.append(draw_device) bpy.types.VIEW3D_HT_header.append(draw_pause) for panel in get_panels(): @@ -1617,7 +1617,7 @@ def register(): def unregister(): from bpy.utils import unregister_class - bpy.types.RENDER_PT_render.remove(draw_device) + bpy.types.RENDER_PT_context.remove(draw_device) bpy.types.VIEW3D_HT_header.remove(draw_pause) for panel in get_panels(): diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index d0df8e1800f..090682c8e14 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -162,10 +162,24 @@ void BlenderSync::sync_light(BL::Object& b_parent, light->axisu = transform_get_column(&tfm, 0); light->axisv = transform_get_column(&tfm, 1); light->sizeu = b_area_lamp.size(); - if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE) - light->sizev = b_area_lamp.size_y(); - else - light->sizev = light->sizeu; + switch(b_area_lamp.shape()) { + case BL::AreaLamp::shape_SQUARE: + light->sizev = light->sizeu; + light->round = false; + break; + case BL::AreaLamp::shape_RECTANGLE: + light->sizev = b_area_lamp.size_y(); + light->round = false; + break; + case BL::AreaLamp::shape_DISK: + light->sizev = light->sizeu; + light->round = true; + break; + case BL::AreaLamp::shape_ELLIPSE: + light->sizev = b_area_lamp.size_y(); + light->round = true; + break; + } light->type = LIGHT_AREA; break; } diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 56c19c1827a..84b90cb53de 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -410,13 +410,17 @@ static PyObject *available_devices_func(PyObject * /*self*/, PyObject * /*args*/ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) { - PyObject *pynodegroup, *pynode; + PyObject *pydata, *pynodegroup, *pynode; const char *filepath = NULL; - if(!PyArg_ParseTuple(args, "OOs", &pynodegroup, &pynode, &filepath)) + if(!PyArg_ParseTuple(args, "OOOs", &pydata, &pynodegroup, &pynode, &filepath)) return NULL; /* RNA */ + PointerRNA dataptr; + RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr); + BL::BlendData b_data(dataptr); + PointerRNA nodeptr; RNA_pointer_create((ID*)PyLong_AsVoidPtr(pynodegroup), &RNA_ShaderNodeScript, (void*)PyLong_AsVoidPtr(pynode), &nodeptr); BL::ShaderNodeScript b_node(nodeptr); @@ -514,7 +518,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) b_sock = b_node.outputs[param->name.string()]; /* remove if type no longer matches */ if(b_sock && b_sock.bl_idname() != socket_type) { - b_node.outputs.remove(b_sock); + b_node.outputs.remove(b_data, b_sock); b_sock = BL::NodeSocket(PointerRNA_NULL); } } @@ -522,7 +526,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) b_sock = b_node.inputs[param->name.string()]; /* remove if type no longer matches */ if(b_sock && b_sock.bl_idname() != socket_type) { - b_node.inputs.remove(b_sock); + b_node.inputs.remove(b_data, b_sock); b_sock = BL::NodeSocket(PointerRNA_NULL); } } @@ -530,9 +534,9 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) if(!b_sock) { /* create new socket */ if(param->isoutput) - b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); + b_sock = b_node.outputs.create(b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str()); else - b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); + b_sock = b_node.inputs.create(b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str()); /* set default value */ if(data_type == BL::NodeSocket::type_VALUE) { @@ -566,7 +570,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) { - b_node.inputs.remove(*b_input); + b_node.inputs.remove(b_data, *b_input); removed = true; break; } @@ -574,7 +578,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) { - b_node.outputs.remove(*b_output); + b_node.outputs.remove(b_data, *b_output); removed = true; break; } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index cc2a6824190..8847d651b02 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -811,6 +811,22 @@ static ShaderNode *add_node(Scene *scene, get_tex_mapping(&sky->tex_mapping, b_texture_mapping); node = sky; } + else if(b_node.is_a(&RNA_ShaderNodeTexIES)) { + BL::ShaderNodeTexIES b_ies_node(b_node); + IESLightNode *ies = new IESLightNode(); + switch(b_ies_node.mode()) { + case BL::ShaderNodeTexIES::mode_EXTERNAL: + ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath()); + break; + case BL::ShaderNodeTexIES::mode_INTERNAL: + ies->ies = get_text_datablock_content(b_ies_node.ies().ptr); + if(ies->ies.empty()) { + ies->ies = "\n"; + } + break; + } + node = ies; + } else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) { BL::ShaderNodeNormalMap b_normal_map_node(b_node); NormalMapNode *nmap = new NormalMapNode(); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index a8379914b83..8a874b7063e 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -468,6 +468,21 @@ static inline string blender_absolute_path(BL::BlendData& b_data, return path; } +static inline string get_text_datablock_content(const PointerRNA& ptr) +{ + if(ptr.data == NULL) { + return ""; + } + + string content; + BL::Text::lines_iterator iter; + for(iter.begin(ptr); iter; ++iter) { + content += iter->body() + "\n"; + } + + return content; +} + /* Texture Space */ static inline void mesh_texture_space(BL::Mesh& b_mesh, diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h index 7d46e31ce24..15d34a79bb8 100644 --- a/intern/cycles/graph/node_type.h +++ b/intern/cycles/graph/node_type.h @@ -73,12 +73,13 @@ struct SocketType INTERNAL = (1 << 2) | (1 << 3), LINK_TEXTURE_GENERATED = (1 << 4), - LINK_TEXTURE_UV = (1 << 5), - LINK_INCOMING = (1 << 6), - LINK_NORMAL = (1 << 7), - LINK_POSITION = (1 << 8), - LINK_TANGENT = (1 << 9), - DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) + LINK_TEXTURE_NORMAL = (1 << 5), + LINK_TEXTURE_UV = (1 << 6), + LINK_INCOMING = (1 << 7), + LINK_NORMAL = (1 << 8), + LINK_POSITION = (1 << 9), + LINK_TANGENT = (1 << 10), + DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) }; ustring name; diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 9b7f4e00084..457602ae4e7 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -178,6 +178,7 @@ set(SRC_SVM_HEADERS svm/svm_geometry.h svm/svm_gradient.h svm/svm_hsv.h + svm/svm_ies.h svm/svm_image.h svm/svm_invert.h svm/svm_light_path.h diff --git a/intern/cycles/kernel/filter/filter_reconstruction.h b/intern/cycles/kernel/filter/filter_reconstruction.h index b7bf322f9ce..58740d5b06a 100644 --- a/intern/cycles/kernel/filter/filter_reconstruction.h +++ b/intern/cycles/kernel/filter/filter_reconstruction.h @@ -61,8 +61,13 @@ ccl_device_inline void kernel_filter_construct_gramian(int x, int y, make_int2(x+dx, y+dy), buffer + q_offset, pass_stride, *rank, design_row, transform, stride); +#ifdef __KERNEL_GPU__ math_trimatrix_add_gramian_strided(XtWX, (*rank)+1, design_row, weight, stride); math_vec3_add_strided(XtWY, (*rank)+1, design_row, weight * q_color, stride); +#else + math_trimatrix_add_gramian(XtWX, (*rank)+1, design_row, weight); + math_vec3_add(XtWY, (*rank)+1, design_row, weight * q_color); +#endif } ccl_device_inline void kernel_filter_finalize(int x, int y, diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index efab69ee37d..b1be0b2155a 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -44,7 +44,7 @@ typedef struct LightSample { * * Note: light_p is modified when sample_coord is true. */ -ccl_device_inline float area_light_sample(float3 P, +ccl_device_inline float rect_light_sample(float3 P, float3 *light_p, float3 axisu, float3 axisv, float randu, float randv, @@ -125,6 +125,60 @@ ccl_device_inline float area_light_sample(float3 P, return 0.0f; } +ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv) +{ + to_unit_disk(&randu, &randv); + return ru*randu + rv*randv; +} + +ccl_device float3 disk_light_sample(float3 v, float randu, float randv) +{ + float3 ru, rv; + + make_orthonormals(v, &ru, &rv); + + return ellipse_sample(ru, rv, randu, randv); +} + +ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv) +{ + return normalize(D + disk_light_sample(D, randu, randv)*radius); +} + +ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv) +{ + return disk_light_sample(normalize(P - center), randu, randv)*radius; +} + +ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls) +{ + float3 I = ls->Ng; + + float attenuation = dot(dir, I); + + if(attenuation <= spot_angle) { + attenuation = 0.0f; + } + else { + float t = attenuation - spot_angle; + + if(t < spot_smooth && spot_smooth != 0.0f) + attenuation *= smoothstepf(t/spot_smooth); + } + + return attenuation; +} + +ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t) +{ + float cos_pi = dot(Ng, I); + + if(cos_pi <= 0.0f) + return 0.0f; + + return t*t/cos_pi; +} + /* Background Light */ #ifdef __BACKGROUND_MIS__ @@ -170,7 +224,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res); /* importance-sampled V direction */ - float dv = (randv - cdf_v.y) / (cdf_next_v.y - cdf_v.y); + float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv); float v = (index_v + dv) / res; /* this is basically std::lower_bound as used by pbrt */ @@ -196,7 +250,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + res); /* importance-sampled U direction */ - float du = (randu - cdf_u.y) / (cdf_next_u.y - cdf_u.y); + float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu); float u = (index_u + du) / res; /* compute pdf */ @@ -295,11 +349,19 @@ ccl_device_inline float background_portal_pdf(KernelGlobals *kg, const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); + bool is_round = (klight->area.invarea < 0.0f); - if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL)) + if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL, is_round)) continue; - portal_pdf += area_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false); + if(is_round) { + float t; + float3 D = normalize_len(lightpos - P, &t); + portal_pdf += fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t); + } + else { + portal_pdf += rect_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false); + } } if(ignore_portal >= 0) { @@ -349,15 +411,26 @@ ccl_device float3 background_portal_sample(KernelGlobals *kg, const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); - - *pdf = area_light_sample(P, &lightpos, - axisu, axisv, - randu, randv, - true); + bool is_round = (klight->area.invarea < 0.0f); + + float3 D; + if(is_round) { + lightpos += ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv); + float t; + D = normalize_len(lightpos - P, &t); + *pdf = fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t); + } + else { + *pdf = rect_light_sample(P, &lightpos, + axisu, axisv, + randu, randv, + true); + D = normalize(lightpos - P); + } *pdf /= num_possible; *sampled_portal = p; - return normalize(lightpos - P); + return D; } portal--; @@ -458,55 +531,6 @@ ccl_device float background_light_pdf(KernelGlobals *kg, float3 P, float3 direct /* Regular Light */ -ccl_device float3 disk_light_sample(float3 v, float randu, float randv) -{ - float3 ru, rv; - - make_orthonormals(v, &ru, &rv); - to_unit_disk(&randu, &randv); - - return ru*randu + rv*randv; -} - -ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv) -{ - return normalize(D + disk_light_sample(D, randu, randv)*radius); -} - -ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv) -{ - return disk_light_sample(normalize(P - center), randu, randv)*radius; -} - -ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls) -{ - float3 I = ls->Ng; - - float attenuation = dot(dir, I); - - if(attenuation <= spot_angle) { - attenuation = 0.0f; - } - else { - float t = attenuation - spot_angle; - - if(t < spot_smooth && spot_smooth != 0.0f) - attenuation *= smoothstepf(t/spot_smooth); - } - - return attenuation; -} - -ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t) -{ - float cos_pi = dot(Ng, I); - - if(cos_pi <= 0.0f) - return 0.0f; - - return t*t/cos_pi; -} - ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, int lamp, float randu, float randv, @@ -601,26 +625,39 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, float3 D = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]); + float invarea = fabsf(klight->area.invarea); + bool is_round = (klight->area.invarea < 0.0f); if(dot(ls->P - P, D) > 0.0f) { return false; } - float3 inplane = ls->P; - ls->pdf = area_light_sample(P, &ls->P, - axisu, axisv, - randu, randv, - true); + float3 inplane; + + if(is_round) { + inplane = ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv); + ls->P += inplane; + ls->pdf = invarea; + } + else { + inplane = ls->P; + ls->pdf = rect_light_sample(P, &ls->P, + axisu, axisv, + randu, randv, + true); + inplane = ls->P - inplane; + } - inplane = ls->P - inplane; ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f; ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f; ls->Ng = D; ls->D = normalize_len(ls->P - P, &ls->t); - float invarea = klight->area.invarea; ls->eval_fac = 0.25f*invarea; + if(is_round) { + ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t); + } } } @@ -731,7 +768,8 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, } else if(type == LIGHT_AREA) { /* area light */ - float invarea = klight->area.invarea; + float invarea = fabsf(klight->area.invarea); + bool is_round = (klight->area.invarea < 0.0f); if(invarea == 0.0f) return false; @@ -754,14 +792,20 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, if(!ray_quad_intersect(P, D, 0.0f, t, light_P, axisu, axisv, Ng, &ls->P, &ls->t, - &ls->u, &ls->v)) + &ls->u, &ls->v, + is_round)) { return false; } ls->D = D; ls->Ng = Ng; - ls->pdf = area_light_sample(P, &light_P, axisu, axisv, 0, 0, false); + if(is_round) { + ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t); + } + else { + ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false); + } ls->eval_fac = 0.25f*invarea; } else { diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 9047b93a0b2..a7b8c492ee9 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -81,5 +81,8 @@ KERNEL_TEX(uint, __sobol_directions) /* image textures */ KERNEL_TEX(TextureInfo, __texture_info) +/* ies lights */ +KERNEL_TEX(float, __ies) + #undef KERNEL_TEX diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h index 56c38d8101c..7bf833eadbc 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h @@ -349,7 +349,7 @@ template<typename T> struct TextureInterpolator { * Only happens for AVX2 kernel and global __KERNEL_SSE__ vectorization * enabled. */ -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) static ccl_always_inline #else static ccl_never_inline diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 0c5e5e30e47..32d86b7192a 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -956,9 +956,15 @@ bool OSLRenderServices::texture(ustring filename, status = true; } } + else if(filename[1] == 'l') { + /* IES light. */ + int slot = atoi(filename.c_str() + 2); + result[0] = kernel_ies_interp(kg, slot, s, t); + status = true; + } else { /* Packed texture. */ - int slot = atoi(filename.c_str() + 1); + int slot = atoi(filename.c_str() + 2); float4 rgba = kernel_tex_image_interp(kg, slot, s, 1.0f - t); result[0] = rgba[0]; diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 6ec651a96d8..b28d017c1c2 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC_OSL node_principled_volume.osl node_holdout.osl node_hsv.osl + node_ies_light.osl node_image_texture.osl node_invert.osl node_layer_weight.osl diff --git a/intern/cycles/kernel/shaders/node_ies_light.osl b/intern/cycles/kernel/shaders/node_ies_light.osl new file mode 100644 index 00000000000..a0954e3a444 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_ies_light.osl @@ -0,0 +1,42 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stdosl.h" +#include "node_texture.h" + +/* IES Light */ + +shader node_ies_light( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + int slot = 0, + float Strength = 1.0, + point Vector = I, + output float Fac = 0.0) +{ + point p = Vector; + + if (use_mapping) { + p = transform(mapping, p); + } + + p = normalize(p); + + float v_angle = acos(-p[2]); + float h_angle = atan2(p[0], p[1]) + M_PI; + + Fac = Strength * texture(format("@l%d", slot), h_angle, v_angle); +} diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl index f309ef7c6f3..c5fcbc311d3 100644 --- a/intern/cycles/kernel/shaders/node_math.osl +++ b/intern/cycles/kernel/shaders/node_math.osl @@ -95,6 +95,8 @@ shader node_math( Value = safe_modulo(Value1, Value2); else if (type == "absolute") Value = fabs(Value1); + else if (type == "arctan2") + Value = atan2(Value1, Value2); if (use_clamp) Value = clamp(Value, 0.0, 1.0); diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 39cd5da7b12..bfa146f2d93 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -157,6 +157,7 @@ CCL_NAMESPACE_END #include "kernel/svm/svm_camera.h" #include "kernel/svm/svm_geometry.h" #include "kernel/svm/svm_hsv.h" +#include "kernel/svm/svm_ies.h" #include "kernel/svm/svm_image.h" #include "kernel/svm/svm_gamma.h" #include "kernel/svm/svm_brightness.h" @@ -421,6 +422,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a case NODE_LIGHT_FALLOFF: svm_node_light_falloff(sd, stack, node); break; + case NODE_IES: + svm_node_ies(kg, sd, stack, node, &offset); + break; # endif /* __EXTRA_NODES__ */ #endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */ diff --git a/intern/cycles/kernel/svm/svm_ies.h b/intern/cycles/kernel/svm/svm_ies.h new file mode 100644 index 00000000000..6130c3348b0 --- /dev/null +++ b/intern/cycles/kernel/svm/svm_ies.h @@ -0,0 +1,110 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +/* IES Light */ + +ccl_device_inline float interpolate_ies_vertical(KernelGlobals *kg, int ofs, int v, int v_num, float v_frac, int h) +{ + /* Since lookups are performed in spherical coordinates, clamping the coordinates at the low end of v + * (corresponding to the north pole) would result in artifacts. + * The proper way of dealing with this would be to lookup the corresponding value on the other side of the pole, + * but since the horizontal coordinates might be nonuniform, this would require yet another interpolation. + * Therefore, the assumtion is made that the light is going to be symmetrical, which means that we can just take + * the corresponding value at the current horizontal coordinate. */ + +#define IES_LOOKUP(v) kernel_tex_fetch(__ies, ofs+h*v_num+(v)) + /* If v is zero, assume symmetry and read at v=1 instead of v=-1. */ + float a = IES_LOOKUP((v == 0)? 1 : v-1); + float b = IES_LOOKUP(v); + float c = IES_LOOKUP(v+1); + float d = IES_LOOKUP(min(v+2, v_num-1)); +#undef IES_LOOKUP + + return cubic_interp(a, b, c, d, v_frac); +} + +ccl_device_inline float kernel_ies_interp(KernelGlobals *kg, int slot, float h_angle, float v_angle) +{ + /* Find offset of the IES data in the table. */ + int ofs = __float_as_int(kernel_tex_fetch(__ies, slot)); + if(ofs == -1) { + return 100.0f; + } + + int h_num = __float_as_int(kernel_tex_fetch(__ies, ofs++)); + int v_num = __float_as_int(kernel_tex_fetch(__ies, ofs++)); + +#define IES_LOOKUP_ANGLE_H(h) kernel_tex_fetch(__ies, ofs+(h)) +#define IES_LOOKUP_ANGLE_V(v) kernel_tex_fetch(__ies, ofs+h_num+(v)) + + /* Check whether the angle is within the bounds of the IES texture. */ + if(v_angle >= IES_LOOKUP_ANGLE_V(v_num-1)) { + return 0.0f; + } + kernel_assert(v_angle >= IES_LOOKUP_ANGLE_V(0)); + kernel_assert(h_angle >= IES_LOOKUP_ANGLE_H(0)); + kernel_assert(h_angle <= IES_LOOKUP_ANGLE_H(h_num-1)); + + /* Lookup the angles to find the table position. */ + int h_i, v_i; + /* TODO(lukas): Consider using bisection. Probably not worth it for the vast majority of IES files. */ + for(h_i = 0; IES_LOOKUP_ANGLE_H(h_i+1) < h_angle; h_i++); + for(v_i = 0; IES_LOOKUP_ANGLE_V(v_i+1) < v_angle; v_i++); + + float h_frac = inverse_lerp(IES_LOOKUP_ANGLE_H(h_i), IES_LOOKUP_ANGLE_H(h_i+1), h_angle); + float v_frac = inverse_lerp(IES_LOOKUP_ANGLE_V(v_i), IES_LOOKUP_ANGLE_V(v_i+1), v_angle); + +#undef IES_LOOKUP_ANGLE_H +#undef IES_LOOKUP_ANGLE_V + + /* Skip forward to the actual intensity data. */ + ofs += h_num+v_num; + + /* Perform cubic interpolation along the horizontal coordinate to get the intensity value. + * If h_i is zero, just wrap around since the horizontal angles always go over the full circle. + * However, the last entry (360°) equals the first one, so we need to wrap around to the one before that. */ + float a = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i == 0)? h_num-2 : h_i-1); + float b = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i); + float c = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i+1); + /* Same logic here, wrap around to the second element if necessary. */ + float d = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i+2 == h_num)? 1 : h_i+2); + + /* Cubic interpolation can result in negative values, so get rid of them. */ + return max(cubic_interp(a, b, c, d, h_frac), 0.0f); +} + +ccl_device void svm_node_ies(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) +{ + uint vector_offset, strength_offset, fac_offset, dummy, slot = node.z; + decode_node_uchar4(node.y, &strength_offset, &vector_offset, &fac_offset, &dummy); + + float3 vector = stack_load_float3(stack, vector_offset); + float strength = stack_load_float_default(stack, strength_offset, node.w); + + vector = normalize(vector); + float v_angle = safe_acosf(-vector.z); + float h_angle = atan2f(vector.x, vector.y) + M_PI_F; + + float fac = strength * kernel_ies_interp(kg, slot, h_angle, v_angle); + + if(stack_valid(fac_offset)) { + stack_store_float(stack, fac_offset, fac); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 1ce7777aac3..8e6bc73ddc7 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -92,6 +92,8 @@ ccl_device float svm_math(NodeMath type, float Fac1, float Fac2) Fac = safe_modulo(Fac1, Fac2); else if(type == NODE_MATH_ABSOLUTE) Fac = fabsf(Fac1); + else if(type == NODE_MATH_ARCTAN2) + Fac = atan2f(Fac1, Fac2); else if(type == NODE_MATH_CLAMP) Fac = saturate(Fac1); else diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 4c3a5975fb8..ac24d23ecd2 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -136,6 +136,7 @@ typedef enum ShaderNodeType { NODE_DISPLACEMENT, NODE_VECTOR_DISPLACEMENT, NODE_PRINCIPLED_VOLUME, + NODE_IES, } ShaderNodeType; typedef enum NodeAttributeType { @@ -259,6 +260,7 @@ typedef enum NodeMath { NODE_MATH_GREATER_THAN, NODE_MATH_MODULO, NODE_MATH_ABSOLUTE, + NODE_MATH_ARCTAN2, NODE_MATH_CLAMP /* used for the clamp UI option */ } NodeMath; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 096de878e51..59e1a12c3a1 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -774,6 +774,12 @@ void ShaderGraph::default_inputs(bool do_osl) connect(texco->output("Generated"), input); } + if(input->flags() & SocketType::LINK_TEXTURE_NORMAL) { + if(!texco) + texco = new TextureCoordinateNode(); + + connect(texco->output("Normal"), input); + } else if(input->flags() & SocketType::LINK_TEXTURE_UV) { if(!texco) texco = new TextureCoordinateNode(); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 8dec7e4ea64..d45d4543e16 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -25,6 +25,8 @@ #include "render/shader.h" #include "util/util_foreach.h" +#include "util/util_hash.h" +#include "util/util_path.h" #include "util/util_progress.h" #include "util/util_logging.h" @@ -117,6 +119,7 @@ NODE_DEFINE(Light) SOCKET_FLOAT(sizeu, "Size U", 1.0f); SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_FLOAT(sizev, "Size V", 1.0f); + SOCKET_BOOLEAN(round, "Round", false); SOCKET_INT(map_resolution, "Map Resolution", 512); @@ -175,6 +178,9 @@ LightManager::LightManager() LightManager::~LightManager() { + foreach(IESSlot *slot, ies_slots) { + delete slot; + } } bool LightManager::has_background_light(Scene *scene) @@ -730,12 +736,15 @@ void LightManager::device_update_points(Device *, float3 axisu = light->axisu*(light->sizeu*light->size); float3 axisv = light->axisv*(light->sizev*light->size); float area = len(axisu)*len(axisv); - float invarea = (area > 0.0f)? 1.0f/area: 1.0f; + if(light->round) { + area *= -M_PI_4_F; + } + float invarea = (area != 0.0f)? 1.0f/area: 1.0f; float3 dir = light->dir; dir = safe_normalize(dir); - if(light->use_mis && area > 0.0f) + if(light->use_mis && area != 0.0f) shader_id |= SHADER_USE_MIS; klights[light_index].co[0] = co.x; @@ -803,7 +812,10 @@ void LightManager::device_update_points(Device *, float3 axisu = light->axisu*(light->sizeu*light->size); float3 axisv = light->axisv*(light->sizev*light->size); float area = len(axisu)*len(axisv); - float invarea = (area > 0.0f)? 1.0f/area: 1.0f; + if(light->round) { + area *= -M_PI_4_F; + } + float invarea = (area != 0.0f)? 1.0f/area: 1.0f; float3 dir = light->dir; dir = safe_normalize(dir); @@ -858,6 +870,9 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce device_update_background(device, dscene, scene, progress); if(progress.get_cancel()) return; + device_update_ies(dscene); + if(progress.get_cancel()) return; + if(use_light_visibility != scene->film->use_light_visibility) { scene->film->use_light_visibility = use_light_visibility; scene->film->tag_update(scene); @@ -872,6 +887,7 @@ void LightManager::device_free(Device *, DeviceScene *dscene) dscene->lights.free(); dscene->light_background_marginal_cdf.free(); dscene->light_background_conditional_cdf.free(); + dscene->ies_lights.free(); } void LightManager::tag_update(Scene * /*scene*/) @@ -879,5 +895,121 @@ void LightManager::tag_update(Scene * /*scene*/) need_update = true; } +int LightManager::add_ies_from_file(ustring filename) +{ + string content; + + /* If the file can't be opened, call with an empty line */ + if(filename.empty() || !path_read_text(filename.c_str(), content)) { + content = "\n"; + } + + return add_ies(ustring(content)); +} + +int LightManager::add_ies(ustring content) +{ + uint hash = hash_string(content.c_str()); + + thread_scoped_lock ies_lock(ies_mutex); + + /* Check whether this IES already has a slot. */ + size_t slot; + for(slot = 0; slot < ies_slots.size(); slot++) { + if(ies_slots[slot]->hash == hash) { + ies_slots[slot]->users++; + return slot; + } + } + + /* Try to find an empty slot for the new IES. */ + for(slot = 0; slot < ies_slots.size(); slot++) { + if(ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) { + break; + } + } + + /* If there's no free slot, add one. */ + if(slot == ies_slots.size()) { + ies_slots.push_back(new IESSlot()); + } + + ies_slots[slot]->ies.load(content); + ies_slots[slot]->users = 1; + ies_slots[slot]->hash = hash; + + need_update = true; + + return slot; +} + +void LightManager::remove_ies(int slot) +{ + thread_scoped_lock ies_lock(ies_mutex); + + if(slot < 0 || slot >= ies_slots.size()) { + assert(false); + return; + } + + assert(ies_slots[slot]->users > 0); + ies_slots[slot]->users--; + + /* If the slot has no more users, update the device to remove it. */ + need_update |= (ies_slots[slot]->users == 0); +} + +void LightManager::device_update_ies(DeviceScene *dscene) +{ + /* Clear empty slots. */ + foreach(IESSlot *slot, ies_slots) { + if(slot->users == 0) { + slot->hash = 0; + slot->ies.clear(); + } + } + + /* Shrink the slot table by removing empty slots at the end. */ + int slot_end; + for(slot_end = ies_slots.size(); slot_end; slot_end--) { + if(ies_slots[slot_end-1]->users > 0) { + /* If the preceding slot has users, we found the new end of the table. */ + break; + } + else { + /* The slot will be past the new end of the table, so free it. */ + delete ies_slots[slot_end-1]; + } + } + ies_slots.resize(slot_end); + + if(ies_slots.size() > 0) { + int packed_size = 0; + foreach(IESSlot *slot, ies_slots) { + packed_size += slot->ies.packed_size(); + } + + /* ies_lights starts with an offset table that contains the offset of every slot, + * or -1 if the slot is invalid. + * Following that table, the packed valid IES lights are stored. */ + float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size); + + int offset = ies_slots.size(); + for(int i = 0; i < ies_slots.size(); i++) { + int size = ies_slots[i]->ies.packed_size(); + if(size > 0) { + data[i] = __int_as_float(offset); + ies_slots[i]->ies.pack(data + offset); + offset += size; + } + else { + data[i] = __int_as_float(-1); + } + } + + dscene->ies_lights.copy_to_device(); + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 97b7b971c73..acbbdd15ddf 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -21,6 +21,8 @@ #include "graph/node.h" +#include "util/util_ies.h" +#include "util/util_thread.h" #include "util/util_types.h" #include "util/util_vector.h" @@ -49,6 +51,7 @@ public: float sizeu; float3 axisv; float sizev; + bool round; Transform tfm; @@ -86,6 +89,11 @@ public: LightManager(); ~LightManager(); + /* IES texture management */ + int add_ies(ustring ies); + int add_ies_from_file(ustring filename); + void remove_ies(int slot); + void device_update(Device *device, DeviceScene *dscene, Scene *scene, @@ -115,9 +123,19 @@ protected: DeviceScene *dscene, Scene *scene, Progress& progress); + void device_update_ies(DeviceScene *dscene); /* Check whether light manager can use the object as a light-emissive. */ bool object_usable_as_light(Object *object); + + struct IESSlot { + IESFile ies; + uint hash; + int users; + }; + + vector<IESSlot*> ies_slots; + thread_mutex ies_mutex; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 01399c85bc0..3dad4d1a346 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -16,6 +16,7 @@ #include "render/image.h" #include "render/integrator.h" +#include "render/light.h" #include "render/nodes.h" #include "render/scene.h" #include "render/svm.h" @@ -384,10 +385,10 @@ void ImageTextureNode::compile(OSLCompiler& compiler) /* TODO(sergey): It's not so simple to pass custom attribute * to the texture() function in order to make builtin images * support more clear. So we use special file name which is - * "@<slot_number>" and check whether file name matches this + * "@i<slot_number>" and check whether file name matches this * mask in the OSLRenderServices::texture(). */ - compiler.parameter("filename", string_printf("@%d", slot).c_str()); + compiler.parameter("filename", string_printf("@i%d", slot).c_str()); } if(is_linear || color_space != NODE_COLOR_SPACE_COLOR) compiler.parameter("color_space", "linear"); @@ -567,7 +568,7 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler) compiler.parameter(this, "filename"); } else { - compiler.parameter("filename", string_printf("@%d", slot).c_str()); + compiler.parameter("filename", string_printf("@i%d", slot).c_str()); } compiler.parameter(this, "projection"); if(is_linear || color_space != NODE_COLOR_SPACE_COLOR) @@ -954,6 +955,97 @@ void VoronoiTextureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_voronoi_texture"); } +/* IES Light */ + +NODE_DEFINE(IESLightNode) +{ + NodeType* type = NodeType::add("ies_light", create, NodeType::SHADER); + + TEXTURE_MAPPING_DEFINE(IESLightNode); + + SOCKET_STRING(ies, "IES", ustring()); + SOCKET_STRING(filename, "File Name", ustring()); + + SOCKET_IN_FLOAT(strength, "Strength", 1.0f); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_NORMAL); + + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} + +IESLightNode::IESLightNode() +: TextureNode(node_type) +{ + light_manager = NULL; + slot = -1; +} + +ShaderNode *IESLightNode::clone() const +{ + IESLightNode *node = new IESLightNode(*this); + + node->light_manager = NULL; + node->slot = -1; + + return node; +} + +IESLightNode::~IESLightNode() +{ + if(light_manager) { + light_manager->remove_ies(slot); + } +} + +void IESLightNode::get_slot() +{ + assert(light_manager); + + if(slot == -1) { + if(ies.empty()) { + slot = light_manager->add_ies_from_file(filename); + } + else { + slot = light_manager->add_ies(ies); + } + } +} + +void IESLightNode::compile(SVMCompiler& compiler) +{ + light_manager = compiler.light_manager; + get_slot(); + + ShaderInput *strength_in = input("Strength"); + ShaderInput *vector_in = input("Vector"); + ShaderOutput *fac_out = output("Fac"); + + int vector_offset = tex_mapping.compile_begin(compiler, vector_in); + + compiler.add_node(NODE_IES, + compiler.encode_uchar4( + compiler.stack_assign_if_linked(strength_in), + vector_offset, + compiler.stack_assign(fac_out), + 0), + slot, + __float_as_int(strength)); + + tex_mapping.compile_end(compiler, vector_in, vector_offset); +} + +void IESLightNode::compile(OSLCompiler& compiler) +{ + light_manager = compiler.light_manager; + get_slot(); + + tex_mapping.compile(compiler); + + compiler.parameter("slot", slot); + compiler.add(this, "node_ies_light"); +} + /* Musgrave Texture */ NODE_DEFINE(MusgraveTextureNode) @@ -1470,7 +1562,7 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler) } if(slot != -1) { - compiler.parameter("filename", string_printf("@%d", slot).c_str()); + compiler.parameter("filename", string_printf("@i%d", slot).c_str()); } if(space == NODE_TEX_VOXEL_SPACE_WORLD) { compiler.parameter("mapping", tfm); @@ -4953,6 +5045,7 @@ NODE_DEFINE(MathNode) type_enum.insert("greater_than", NODE_MATH_GREATER_THAN); type_enum.insert("modulo", NODE_MATH_MODULO); type_enum.insert("absolute", NODE_MATH_ABSOLUTE); + type_enum.insert("arctan2", NODE_MATH_ARCTAN2); SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD); SOCKET_BOOLEAN(use_clamp, "Use Clamp", false); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 58c3d472cd3..35a7df690c3 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -25,6 +25,7 @@ CCL_NAMESPACE_BEGIN class ImageManager; +class LightManager; class Scene; class Shader; @@ -281,6 +282,27 @@ public: } }; +class IESLightNode : public TextureNode { +public: + SHADER_NODE_NO_CLONE_CLASS(IESLightNode) + + ~IESLightNode(); + ShaderNode *clone() const; + virtual int get_group() { return NODE_GROUP_LEVEL_2; } + + ustring filename; + ustring ies; + + float strength; + float3 vector; + +private: + LightManager *light_manager; + int slot; + + void get_slot(); +}; + class MappingNode : public ShaderNode { public: SHADER_NODE_CLASS(MappingNode) diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index f1a22350060..dde622bff8a 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -99,7 +99,9 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene * compile shaders alternating */ thread_scoped_lock lock(ss_mutex); - OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager); + OSLCompiler compiler((void*)this, (void*)ss, + scene->image_manager, + scene->light_manager); compiler.background = (shader == scene->default_background); compiler.compile(scene, og, shader); @@ -546,11 +548,14 @@ OSLNode *OSLShaderManager::osl_node(const std::string& filepath, /* Graph Compiler */ -OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_) +OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, + ImageManager *image_manager_, + LightManager *light_manager_) { manager = manager_; shadingsys = shadingsys_; image_manager = image_manager_; + light_manager = light_manager_; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; background = false; diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 95e35dd857b..7a3208c402a 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -120,7 +120,9 @@ protected: class OSLCompiler { public: - OSLCompiler(void *manager, void *shadingsys, ImageManager *image_manager); + OSLCompiler(void *manager, void *shadingsys, + ImageManager *image_manager, + LightManager *light_manager); void compile(Scene *scene, OSLGlobals *og, Shader *shader); void add(ShaderNode *node, const char *name, bool isfilepath = false); @@ -146,6 +148,7 @@ public: bool background; ImageManager *image_manager; + LightManager *light_manager; private: #ifdef WITH_OSL diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index ba47e3ab6f8..b35cdbd3db5 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -76,7 +76,8 @@ DeviceScene::DeviceScene(Device *device) svm_nodes(device, "__svm_nodes", MEM_TEXTURE), shaders(device, "__shaders", MEM_TEXTURE), lookup_table(device, "__lookup_table", MEM_TEXTURE), - sobol_directions(device, "__sobol_directions", MEM_TEXTURE) + sobol_directions(device, "__sobol_directions", MEM_TEXTURE), + ies_lights(device, "__ies", MEM_TEXTURE) { memset(&data, 0, sizeof(data)); } diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 04bd4735a86..6c67433c9fc 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -119,6 +119,9 @@ public: /* integrator */ device_vector<uint> sobol_directions; + /* ies lights */ + device_vector<float> ies_lights; + KernelData data; DeviceScene(Device *device); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index c5b4060d5c3..eb8a35a271f 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -58,7 +58,7 @@ void SVMShaderManager::device_update_shader(Scene *scene, svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); SVMCompiler::Summary summary; - SVMCompiler compiler(scene->shader_manager, scene->image_manager); + SVMCompiler compiler(scene->shader_manager, scene->image_manager, scene->light_manager); compiler.background = (shader == scene->default_background); compiler.compile(scene, shader, svm_nodes, 0, &summary); @@ -154,10 +154,13 @@ void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *s /* Graph Compiler */ -SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_manager_) +SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, + ImageManager *image_manager_, + LightManager *light_manager_) { shader_manager = shader_manager_; image_manager = image_manager_; + light_manager = light_manager_; max_stack_use = 0; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 18be0fa9a22..7cf1e4ad791 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -95,7 +95,9 @@ public: string full_report() const; }; - SVMCompiler(ShaderManager *shader_manager, ImageManager *image_manager); + SVMCompiler(ShaderManager *shader_manager, + ImageManager *image_manager, + LightManager *light_manager); void compile(Scene *scene, Shader *shader, array<int4>& svm_nodes, @@ -125,6 +127,7 @@ public: ImageManager *image_manager; ShaderManager *shader_manager; + LightManager *light_manager; bool background; protected: diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index 24043e2231b..3b690860d53 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -11,6 +11,7 @@ set(INC_SYS set(SRC util_aligned_malloc.cpp util_debug.cpp + util_ies.cpp util_logging.cpp util_math_cdf.cpp util_md5.cpp @@ -45,6 +46,7 @@ set(SRC_HEADERS util_guarded_allocator.h util_half.h util_hash.h + util_ies.h util_image.h util_image_impl.h util_list.h diff --git a/intern/cycles/util/util_ies.cpp b/intern/cycles/util/util_ies.cpp new file mode 100644 index 00000000000..e068957325b --- /dev/null +++ b/intern/cycles/util/util_ies.cpp @@ -0,0 +1,396 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "util/util_foreach.h" +#include "util/util_ies.h" +#include "util/util_math.h" +#include "util/util_string.h" + +CCL_NAMESPACE_BEGIN + +bool IESFile::load(ustring ies) +{ + clear(); + if(!parse(ies) || !process()) { + clear(); + return false; + } + return true; +} + +void IESFile::clear() +{ + intensity.clear(); + v_angles.clear(); + h_angles.clear(); +} + +int IESFile::packed_size() +{ + if(v_angles.size() && h_angles.size() > 0) { + return 2 + h_angles.size() + v_angles.size() + h_angles.size()*v_angles.size(); + } + return 0; +} + +void IESFile::pack(float *data) +{ + if(v_angles.size() && h_angles.size()) { + *(data++) = __int_as_float(h_angles.size()); + *(data++) = __int_as_float(v_angles.size()); + + memcpy(data, &h_angles[0], h_angles.size()*sizeof(float)); + data += h_angles.size(); + memcpy(data, &v_angles[0], v_angles.size()*sizeof(float)); + data += v_angles.size(); + + for(int h = 0; h < intensity.size(); h++) { + memcpy(data, &intensity[h][0], v_angles.size()*sizeof(float)); + data += v_angles.size(); + } + } +} + +class IESTextParser { +public: + vector<char> text; + char *data; + + IESTextParser(ustring str) + : text(str.begin(), str.end()) + { + std::replace(text.begin(), text.end(), ',', ' '); + data = strstr(&text[0], "\nTILT="); + } + + bool eof() { + return (data == NULL) || (data[0] == '\0'); + } + + double get_double() { + if(eof()) { + return 0.0; + } + char *old_data = data; + double val = strtod(data, &data); + if(data == old_data) { + data = NULL; + return 0.0; + } + return val; + } + + long get_long() { + if(eof()) { + return 0; + } + char *old_data = data; + long val = strtol(data, &data, 10); + if(data == old_data) { + data = NULL; + return 0; + } + return val; + } +}; + +bool IESFile::parse(ustring ies) +{ + if(ies.empty()) { + return false; + } + + IESTextParser parser(ies); + if(parser.eof()) { + return false; + } + + /* Handle the tilt data block. */ + if(strncmp(parser.data, "\nTILT=INCLUDE", 13) == 0) { + parser.data += 13; + parser.get_double(); /* Lamp to Luminaire geometry */ + int num_tilt = parser.get_long(); /* Amount of tilt angles and factors */ + /* Skip over angles and factors. */ + for(int i = 0; i < 2*num_tilt; i++) { + parser.get_double(); + } + } + else { + /* Skip to next line. */ + parser.data = strstr(parser.data+1, "\n"); + } + + if(parser.eof()) { + return false; + } + parser.data++; + + parser.get_long(); /* Number of lamps */ + parser.get_double(); /* Lumens per lamp */ + double factor = parser.get_double(); /* Candela multiplier */ + int v_angles_num = parser.get_long(); /* Number of vertical angles */ + int h_angles_num = parser.get_long(); /* Number of horizontal angles */ + type = (IESType) parser.get_long(); /* Photometric type */ + + /* TODO(lukas): Test whether the current type B processing can also deal with type A files. + * In theory the only difference should be orientation which we ignore anyways, but with IES you never know... + */ + if(type != TYPE_B && type != TYPE_C) { + return false; + } + + parser.get_long(); /* Unit of the geometry data */ + parser.get_double(); /* Width */ + parser.get_double(); /* Length */ + parser.get_double(); /* Height */ + factor *= parser.get_double(); /* Ballast factor */ + factor *= parser.get_double(); /* Ballast-Lamp Photometric factor */ + parser.get_double(); /* Input Watts */ + + /* Intensity values in IES files are specified in candela (lumen/sr), a photometric quantity. + * Cycles expects radiometric quantities, though, which requires a conversion. + * However, the Luminous efficacy (ratio of lumens per Watt) depends on the spectral distribution + * of the light source since lumens take human perception into account. + * Since this spectral distribution is not known from the IES file, a typical one must be assumed. + * The D65 standard illuminant has a Luminous efficacy of 177.83, which is used here to convert to Watt/sr. + * A more advanced approach would be to add a Blackbody Temperature input to the node and numerically + * integrate the Luminous efficacy from the resulting spectral distribution. + * Also, the Watt/sr value must be multiplied by 4*pi to get the Watt value that Cycles expects + * for lamp strength. Therefore, the conversion here uses 4*pi/177.83 as a Candela to Watt factor. + */ + factor *= 0.0706650768394; + + v_angles.reserve(v_angles_num); + for(int i = 0; i < v_angles_num; i++) { + v_angles.push_back((float) parser.get_double()); + } + + h_angles.reserve(h_angles_num); + for(int i = 0; i < h_angles_num; i++) { + h_angles.push_back((float) parser.get_double()); + } + + intensity.resize(h_angles_num); + for(int i = 0; i < h_angles_num; i++) { + intensity[i].reserve(v_angles_num); + for(int j = 0; j < v_angles_num; j++) { + intensity[i].push_back((float) (factor * parser.get_double())); + } + } + + return !parser.eof(); +} + +bool IESFile::process_type_b() +{ + vector<vector<float> > newintensity; + newintensity.resize(v_angles.size()); + for(int i = 0; i < v_angles.size(); i++) { + newintensity[i].reserve(h_angles.size()); + for(int j = 0; j < h_angles.size(); j++) { + newintensity[i].push_back(intensity[j][i]); + } + } + intensity.swap(newintensity); + h_angles.swap(v_angles); + + float h_first = h_angles[0], h_last = h_angles[h_angles.size()-1]; + if(h_last != 90.0f) { + return false; + } + + if(h_first == 0.0f) { + /* The range in the file corresponds to 90°-180°, we need to mirror that to get the + * full 180° range. */ + vector<float> new_h_angles; + vector<vector<float> > new_intensity; + int hnum = h_angles.size(); + new_h_angles.reserve(2*hnum-1); + new_intensity.reserve(2*hnum-1); + for(int i = hnum-1; i > 0; i--) { + new_h_angles.push_back(90.0f - h_angles[i]); + new_intensity.push_back(intensity[i]); + } + for(int i = 0; i < hnum; i++) { + new_h_angles.push_back(90.0f + h_angles[i]); + new_intensity.push_back(intensity[i]); + } + h_angles.swap(new_h_angles); + intensity.swap(new_intensity); + } + else if(h_first == -90.0f) { + /* We have full 180° coverage, so just shift to match the angle range convention. */ + for(int i = 0; i < h_angles.size(); i++) { + h_angles[i] += 90.0f; + } + } + /* To get correct results with the cubic interpolation in the kernel, the horizontal range + * has to cover all 360°. Therefore, we copy the 0° entry to 360° to ensure full coverage + * and seamless interpolation. */ + h_angles.push_back(360.0f); + intensity.push_back(intensity[0]); + + float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1]; + if(v_last != 90.0f) { + return false; + } + + if(v_first == 0.0f) { + /* The range in the file corresponds to 90°-180°, we need to mirror that to get the + * full 180° range. */ + vector<float> new_v_angles; + int hnum = h_angles.size(); + int vnum = v_angles.size(); + new_v_angles.reserve(2*vnum-1); + for(int i = vnum-1; i > 0; i--) { + new_v_angles.push_back(90.0f - v_angles[i]); + } + for(int i = 0; i < vnum; i++) { + new_v_angles.push_back(90.0f + v_angles[i]); + } + for(int i = 0; i < hnum; i++) { + vector<float> new_intensity; + new_intensity.reserve(2*vnum-1); + for(int j = vnum-2; j >= 0; j--) { + new_intensity.push_back(intensity[i][j]); + } + new_intensity.insert(new_intensity.end(), intensity[i].begin(), intensity[i].end()); + intensity[i].swap(new_intensity); + } + v_angles.swap(new_v_angles); + } + else if(v_first == -90.0f) { + /* We have full 180° coverage, so just shift to match the angle range convention. */ + for(int i = 0; i < v_angles.size(); i++) { + v_angles[i] += 90.0f; + } + } + + return true; +} + +bool IESFile::process_type_c() +{ + if(h_angles[0] == 90.0f) { + /* Some files are stored from 90° to 270°, so we just rotate them to the regular 0°-180° range here. */ + for(int i = 0; i < v_angles.size(); i++) { + h_angles[i] -= 90.0f; + } + } + + if(h_angles[0] != 0.0f) { + return false; + } + + if(h_angles.size() == 1) { + h_angles.push_back(360.0f); + intensity.push_back(intensity[0]); + } + + if(h_angles[h_angles.size()-1] == 90.0f) { + /* Only one quadrant is defined, so we need to mirror twice (from one to two, then to four). + * Since the two->four mirroring step might also be required if we get an input of two quadrants, + * we only do the first mirror here and later do the second mirror in either case. */ + int hnum = h_angles.size(); + for(int i = hnum-2; i >= 0; i--) { + h_angles.push_back(180.0f - h_angles[i]); + intensity.push_back(intensity[i]); + } + } + + if(h_angles[h_angles.size()-1] == 180.0f) { + /* Mirror half to the full range. */ + int hnum = h_angles.size(); + for(int i = hnum-2; i >= 0; i--) { + h_angles.push_back(360.0f - h_angles[i]); + intensity.push_back(intensity[i]); + } + } + + /* Some files skip the 360° entry (contrary to standard) because it's supposed to be identical to the 0° entry. + * If the file has a discernible order in its spacing, just fix this. */ + if(h_angles[h_angles.size()-1] != 360.0f) { + int hnum = h_angles.size(); + float last_step = h_angles[hnum-1]-h_angles[hnum-2]; + float first_step = h_angles[1]-h_angles[0]; + float difference = 360.0f - h_angles[hnum-1]; + if(last_step == difference || first_step == difference) { + h_angles.push_back(360.0f); + intensity.push_back(intensity[0]); + } + else { + return false; + } + } + + float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1]; + if(v_first == 90.0f) { + if(v_last == 180.0f) { + /* Flip to ensure that vertical angles always start at 0°. */ + for(int i = 0; i < v_angles.size(); i++) { + v_angles[i] = 180.0f - v_angles[i]; + } + } + else { + return false; + } + } + else if(v_first != 0.0f) { + return false; + } + + return true; +} + +bool IESFile::process() +{ + if(h_angles.size() == 0 || v_angles.size() == 0) { + return false; + } + + if(type == TYPE_B) { + if(!process_type_b()) { + return false; + } + } + else { + assert(type == TYPE_C); + if(!process_type_c()) { + return false; + } + } + + assert(v_angles[0] == 0.0f); + assert(h_angles[0] == 0.0f); + assert(h_angles[h_angles.size()-1] == 360.0f); + + /* Convert from deg to rad. */ + for(int i = 0; i < v_angles.size(); i++) { + v_angles[i] *= M_PI_F / 180.f; + } + for(int i = 0; i < h_angles.size(); i++) { + h_angles[i] *= M_PI_F / 180.f; + } + + return true; +} + +IESFile::~IESFile() +{ + clear(); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_ies.h b/intern/cycles/util/util_ies.h new file mode 100644 index 00000000000..5933cb3962a --- /dev/null +++ b/intern/cycles/util/util_ies.h @@ -0,0 +1,61 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTIL_IES_H__ +#define __UTIL_IES_H__ + +#include "util/util_param.h" +#include "util/util_vector.h" + +CCL_NAMESPACE_BEGIN + +class IESFile { +public: + IESFile() {} + ~IESFile(); + + int packed_size(); + void pack(float *data); + + bool load(ustring ies); + void clear(); + +protected: + bool parse(ustring ies); + bool process(); + bool process_type_b(); + bool process_type_c(); + + /* The brightness distribution is stored in spherical coordinates. + * The horizontal angles correspond to to theta in the regular notation + * and always span the full range from 0° to 360°. + * The vertical angles correspond to phi and always start at 0°. */ + vector<float> v_angles, h_angles; + /* The actual values are stored here, with every entry storing the values + * of one horizontal segment. */ + vector<vector<float> > intensity; + + /* Types of angle representation in IES files. Currently, only B and C are supported. */ + enum IESType { + TYPE_A = 3, + TYPE_B = 2, + TYPE_C = 1 + } type; +}; + +CCL_NAMESPACE_END + +#endif /* __UTIL_IES_H__ */ diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index d0e91a2a1c9..fd3199f209f 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -310,6 +310,17 @@ ccl_device_inline float4 float3_to_float4(const float3 a) return make_float4(a.x, a.y, a.z, 1.0f); } +ccl_device_inline float inverse_lerp(float a, float b, float x) +{ + return (x - a) / (b - a); +} + +/* Cubic interpolation between b and c, a and d are the previous and next point. */ +ccl_device_inline float cubic_interp(float a, float b, float c, float d, float x) +{ + return 0.5f*(((d + 3.0f*(b-c) - a)*x + (2.0f*a - 5.0f*b + 4.0f*c - d))*x + (c - a))*x + b; +} + CCL_NAMESPACE_END #include "util/util_math_int2.h" diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 61ddcc38f50..5f15487df57 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -186,12 +186,17 @@ ccl_device_forceinline bool ray_triangle_intersect( #undef dot3 } +/* Tests for an intersection between a ray and a quad defined by + * its midpoint, normal and sides. + * If ellipse is true, hits outside the ellipse that's enclosed by the + * quad are rejected. + */ ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt, float3 quad_P, float3 quad_u, float3 quad_v, float3 quad_n, float3 *isect_P, float *isect_t, - float *isect_u, float *isect_v) + float *isect_u, float *isect_v, bool ellipse) { /* Perform intersection test. */ float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n); @@ -200,20 +205,23 @@ ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, } const float3 hit = ray_P + t*ray_D; const float3 inplane = hit - quad_P; - const float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f; - if(u < 0.0f || u > 1.0f) { + const float u = dot(inplane, quad_u) / dot(quad_u, quad_u); + if(u < -0.5f || u > 0.5f) { + return false; + } + const float v = dot(inplane, quad_v) / dot(quad_v, quad_v); + if(v < -0.5f || v > 0.5f) { return false; } - const float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f; - if(v < 0.0f || v > 1.0f) { + if(ellipse && (u*u + v*v > 0.25f)) { return false; } /* Store the result. */ /* TODO(sergey): Check whether we can avoid some checks here. */ if(isect_P != NULL) *isect_P = hit; if(isect_t != NULL) *isect_t = t; - if(isect_u != NULL) *isect_u = u; - if(isect_v != NULL) *isect_v = v; + if(isect_u != NULL) *isect_u = u + 0.5f; + if(isect_v != NULL) *isect_v = v + 0.5f; return true; } diff --git a/intern/cycles/util/util_math_matrix.h b/intern/cycles/util/util_math_matrix.h index 382dad64ea5..9ffcb9659b2 100644 --- a/intern/cycles/util/util_math_matrix.h +++ b/intern/cycles/util/util_math_matrix.h @@ -144,6 +144,18 @@ ccl_device_inline void math_trimatrix_add_gramian_strided(ccl_global float *A, } } +ccl_device_inline void math_trimatrix_add_gramian(ccl_global float *A, + int n, + const float *ccl_restrict v, + float weight) +{ + for(int row = 0; row < n; row++) { + for(int col = 0; col <= row; col++) { + MATHS(A, row, col, 1) += v[row]*v[col]*weight; + } + } +} + /* Transpose matrix A inplace. */ ccl_device_inline void math_matrix_transpose(ccl_global float *A, int n, int stride) { @@ -4,359 +4,66 @@ REM This is for users who like to configure & build Blender with a single comman setlocal EnableDelayedExpansion setlocal ENABLEEXTENSIONS set BLENDER_DIR=%~dp0 -set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =% -for %%X in (svn.exe) do (set HAS_SVN=%%~$PATH:X) -if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" ( - echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting.... - goto EOF -) -set BUILD_DIR=%BLENDER_DIR%..\build_windows -set BUILD_TYPE=Release -rem reset all variables so they do not get accidentally get carried over from previous builds -set BUILD_DIR_OVERRRIDE= -set BUILD_CMAKE_ARGS= -set BUILD_ARCH= -set BUILD_VS_VER= -set BUILD_VS_YEAR= -set BUILD_VS_LIBDIRPOST= -set BUILD_VS_LIBDIR= -set BUILD_VS_SVNDIR= -set BUILD_NGE= -set KEY_NAME= -set MSBUILD_PLATFORM= -set MUST_CLEAN= -set NOBUILD= -set TARGET= -set WINDOWS_ARCH= -set TESTS_CMAKE_ARGS= -:argv_loop -if NOT "%1" == "" ( - REM Help Message - if "%1" == "help" ( - goto HELP - ) +call "%BLENDER_DIR%\build_files\windows\reset_variables.cmd" - REM Build Types - if "%1" == "debug" ( - set BUILD_TYPE=Debug - REM Build Configurations - ) else if "%1" == "noge" ( - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_GAMEENGINE=OFF -DWITH_PLAYER=OFF - set BUILD_NGE=_noge - ) else if "%1" == "builddir" ( - set BUILD_DIR_OVERRRIDE="%BLENDER_DIR%..\%2" - shift /1 - ) else if "%1" == "with_tests" ( - set TESTS_CMAKE_ARGS=-DWITH_GTESTS=On - ) else if "%1" == "full" ( - set TARGET=Full - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ - -C"%BLENDER_DIR%\build_files\cmake\config\blender_full.cmake" - ) else if "%1" == "lite" ( - set TARGET=Lite - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ - -C"%BLENDER_DIR%\build_files\cmake\config\blender_lite.cmake" - ) else if "%1" == "cycles" ( - set TARGET=Cycles - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ - -C"%BLENDER_DIR%\build_files\cmake\config\cycles_standalone.cmake" - ) else if "%1" == "headless" ( - set TARGET=Headless - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ - -C"%BLENDER_DIR%\build_files\cmake\config\blender_headless.cmake" - ) else if "%1" == "bpy" ( - set TARGET=Bpy - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ - -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake" - ) else if "%1" == "release" ( - set TARGET=Release - ) else if "%1" == "x86" ( - set BUILD_ARCH=x86 - ) else if "%1" == "x64" ( - set BUILD_ARCH=x64 - ) else if "%1" == "2017" ( - set BUILD_VS_VER=15 - set BUILD_VS_YEAR=2017 - set BUILD_VS_LIBDIRPOST=vc14 - ) else if "%1" == "2015" ( - set BUILD_VS_VER=14 - set BUILD_VS_YEAR=2015 - set BUILD_VS_LIBDIRPOST=vc14 - ) else if "%1" == "2013" ( - set BUILD_VS_VER=12 - set BUILD_VS_YEAR=2013 - set BUILD_VS_LIBDIRPOST=vc12 - ) else if "%1" == "packagename" ( - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2" - shift /1 - ) else if "%1" == "nobuild" ( - set NOBUILD=1 - ) else if "%1" == "showhash" ( - for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i - cd release/datafiles/locale - for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i - cd %~dp0 - cd release/scripts/addons - for /f "delims=" %%i in ('git rev-parse HEAD') do echo Addons_Hash=%%i - cd %~dp0 - goto EOF - REM Non-Build Commands - ) else if "%1" == "update" ( - svn up ../lib/* - git pull --rebase - git submodule update --remote - goto EOF - ) else if "%1" == "clean" ( - set MUST_CLEAN=1 - ) else ( - echo Command "%1" unknown, aborting! - goto EOF - ) +call "%BLENDER_DIR%\build_files\windows\check_spaces_in_path.cmd" +if errorlevel 1 goto EOF - shift /1 - goto argv_loop -) -if "%BUILD_ARCH%"=="" ( - if "%PROCESSOR_ARCHITECTURE%" == "AMD64" ( - set WINDOWS_ARCH= Win64 - set BUILD_ARCH=x64 - ) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" ( - set WINDOWS_ARCH= Win64 - set BUILD_ARCH=x64 - ) else ( - set WINDOWS_ARCH= - set BUILD_ARCH=x86 - ) -) else if "%BUILD_ARCH%"=="x64" ( - set WINDOWS_ARCH= Win64 -) else if "%BUILD_ARCH%"=="x86" ( - set WINDOWS_ARCH= -) +call "%BLENDER_DIR%\build_files\windows\parse_arguments.cmd" %* +if errorlevel 1 goto EOF -if "%BUILD_VS_VER%"=="" ( - set BUILD_VS_VER=12 - set BUILD_VS_YEAR=2013 - set BUILD_VS_LIBDIRPOST=vc12 -) +call "%BLENDER_DIR%\build_files\windows\find_dependencies.cmd" +if errorlevel 1 goto EOF -if "%BUILD_ARCH%"=="x64" ( - set MSBUILD_PLATFORM=x64 -) else if "%BUILD_ARCH%"=="x86" ( - set MSBUILD_PLATFORM=win32 +if "%SHOW_HELP%" == "1" ( + call "%BLENDER_DIR%\build_files\windows\show_help.cmd" + goto EOF ) - -if "%target%"=="Release" ( - rem for vc12 check for both cuda 7.5 and 8 - if "%CUDA_PATH%"=="" ( - echo Cuda Not found, aborting! - goto EOF - ) - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ - -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake" +if "%BUILD_UPDATE%" == "1" ( + call "%BLENDER_DIR%\build_files\windows\update_sources.cmd" + goto EOF ) -:DetectMSVC -REM Detect MSVC Installation for 2013-2015 -if DEFINED VisualStudioVersion goto msvc_detect_finally -set VALUE_NAME=ProductDir -REM Check 64 bits -set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC" -for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C -if DEFINED MSVC_VC_DIR goto msvc_detect_finally -REM Check 32 bits -set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC" -for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C -if DEFINED MSVC_VC_DIR goto msvc_detect_finally -:msvc_detect_finally -if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat" -if DEFINED MSVC_VC_DIR goto sanity_checks - -rem MSVC Build environment 2017 and up. -for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SXS\VS7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C -if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017 -REM Check 32 bits -for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\sxs\vs7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C -if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017 -:msvc_detect_finally_2017 -if DEFINED MSVC_VS_DIR call "%MSVC_VS_DIR%\Common7\Tools\VsDevCmd.bat" +call "%BLENDER_DIR%\build_files\windows\detect_architecture.cmd" -:sanity_checks -REM Sanity Checks -where /Q msbuild -if %ERRORLEVEL% NEQ 0 ( - if "%BUILD_VS_VER%"=="12" ( - rem vs12 not found, try vs14 - echo Visual Studio 2013 not found, trying Visual Studio 2015. - set BUILD_VS_VER=14 - set BUILD_VS_YEAR=2015 - set BUILD_VS_LIBDIRPOST=vc14 - goto DetectMSVC - ) else ( - echo Error: "MSBuild" command not in the PATH. - echo You must have MSVC installed and run this from the "Developer Command Prompt" - echo ^(available from Visual Studio's Start menu entry^), aborting! +if "%BUILD_VS_YEAR%" == "" ( + call "%BLENDER_DIR%\build_files\windows\autodetect_msvc.cmd" + if errorlevel 1 ( + echo Visual Studio not found ^(try with the 'verbose' switch for more information^) goto EOF ) -) - - -set BUILD_DIR=%BUILD_DIR%_%TARGET%%BUILD_NGE%_%BUILD_ARCH%_vc%BUILD_VS_VER%_%BUILD_TYPE% -if NOT "%BUILD_DIR_OVERRRIDE%"=="" ( - set BUILD_DIR=%BUILD_DIR_OVERRRIDE% -) - -where /Q cmake -if %ERRORLEVEL% NEQ 0 ( - echo Error: "CMake" command not in the PATH. - echo You must have CMake installed and added to your PATH, aborting! - goto EOF -) - -if "%BUILD_ARCH%"=="x64" ( - set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST% -) else if "%BUILD_ARCH%"=="x86" ( - set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST% -) -set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%" - -if NOT EXIST %BUILD_VS_LIBDIR% ( - rem libs not found, but svn is on the system - if not "%HAS_SVN%"=="" ( - echo. - echo The required external libraries in %BUILD_VS_LIBDIR% are missing - echo. - set /p GetLibs= "Would you like to download them? (y/n)" - if /I "!GetLibs!"=="Y" ( - echo. - echo Downloading %BUILD_VS_SVNDIR% libraries, please wait. - echo. - svn checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR% - ) +) else ( + call "%BLENDER_DIR%\build_files\windows\detect_msvc%BUILD_VS_YEAR%.cmd" + if errorlevel 1 ( + echo Visual Studio %BUILD_VS_YEAR% not found ^(try with the 'verbose' switch for more information^) + goto EOF ) ) -if NOT EXIST %BUILD_VS_LIBDIR% ( - echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%" - echo This is needed for building, aborting! - goto EOF -) +call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd" -if "%TARGET%"=="" ( - echo Error: Convenience target not set - echo This is required for building, aborting! - echo . - goto HELP -) +echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR% -set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%WINDOWS_ARCH%" %TESTS_CMAKE_ARGS% -if NOT EXIST %BUILD_DIR%\nul ( - mkdir %BUILD_DIR% -) -if "%MUST_CLEAN%"=="1" ( - echo Cleaning %BUILD_DIR% - msbuild ^ - %BUILD_DIR%\Blender.sln ^ - /target:clean ^ - /property:Configuration=%BUILD_TYPE% ^ - /verbosity:minimal ^ - /p:platform=%MSBUILD_PLATFORM% +call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" +if errorlevel 1 goto EOF - if %ERRORLEVEL% NEQ 0 ( - echo Cleaned "%BUILD_DIR%" - ) - goto EOF -) -REM Only configure on first run or when called with nobuild -if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1 -if "%NOBUILD%"=="1" set MUST_CONFIGURE=1 - -if "%MUST_CONFIGURE%"=="1" ( - cmake ^ - %BUILD_CMAKE_ARGS% ^ - -H%BLENDER_DIR% ^ - -B%BUILD_DIR% ^ - %BUILD_CMAKE_ARGS% - - if %ERRORLEVEL% NEQ 0 ( - echo "Configuration Failed" - goto EOF - ) -) -if DEFINED MSVC_VC_DIR echo call "%MSVC_VC_DIR%\vcvarsall.bat" > %BUILD_DIR%\rebuild.cmd -if DEFINED MSVC_VS_DIR echo call "%MSVC_VS_DIR%\Common7\Tools\VsDevCmd.bat" > %BUILD_DIR%\rebuild.cmd -echo cmake . >> %BUILD_DIR%\rebuild.cmd -echo msbuild ^ - %BUILD_DIR%\Blender.sln ^ - /target:build ^ - /property:Configuration=%BUILD_TYPE% ^ - /maxcpucount:2 ^ - /verbosity:minimal ^ - /p:platform=%MSBUILD_PLATFORM% ^ - /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log >> %BUILD_DIR%\rebuild.cmd -echo msbuild ^ - %BUILD_DIR%\INSTALL.vcxproj ^ - /property:Configuration=%BUILD_TYPE% ^ - /verbosity:minimal ^ - /p:platform=%MSBUILD_PLATFORM% >> %BUILD_DIR%\rebuild.cmd +call "%BLENDER_DIR%\build_files\windows\check_submodules.cmd" +if errorlevel 1 goto EOF -if "%NOBUILD%"=="1" goto EOF +if "%BUILD_WITH_NINJA%" == "" ( + call "%BLENDER_DIR%\build_files\windows\configure_msbuild.cmd" + if errorlevel 1 goto EOF -msbuild ^ - %BUILD_DIR%\Blender.sln ^ - /target:build ^ - /property:Configuration=%BUILD_TYPE% ^ - /maxcpucount:2 ^ - /verbosity:minimal ^ - /p:platform=%MSBUILD_PLATFORM% ^ - /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log + call "%BLENDER_DIR%\build_files\windows\build_msbuild.cmd" + if errorlevel 1 goto EOF +) else ( + call "%BLENDER_DIR%\build_files\windows\configure_ninja.cmd" + if errorlevel 1 goto EOF -if %ERRORLEVEL% NEQ 0 ( - echo "Build Failed" - goto EOF + call "%BLENDER_DIR%\build_files\windows\build_ninja.cmd" + if errorlevel 1 goto EOF ) -msbuild ^ - %BUILD_DIR%\INSTALL.vcxproj ^ - /property:Configuration=%BUILD_TYPE% ^ - /verbosity:minimal ^ - /p:platform=%MSBUILD_PLATFORM% - -echo. -echo At any point you can optionally modify your build configuration by editing: -echo "%BUILD_DIR%\CMakeCache.txt", then run "rebuild.cmd" in the build folder to build with the changes applied. -echo. -echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender.exe" -echo. -goto EOF -:HELP - echo. - echo Convenience targets - echo - release ^(identical to the official blender.org builds^) - echo - full ^(same as release minus the cuda kernels^) - echo - lite - echo - headless - echo - cycles - echo - bpy - echo. - echo Utilities ^(not associated with building^) - echo - clean ^(Target must be set^) - echo - update - echo - nobuild ^(only generate project files^) - echo - showhash ^(Show git hashes of source tree^) - echo. - echo Configuration options - echo - with_tests ^(enable building unit tests^) - echo - noge ^(disable building game enginge and player^) - echo - debug ^(Build an unoptimized debuggable build^) - echo - packagename [newname] ^(override default cpack package name^) - echo - buildir [newdir] ^(override default build folder^) - echo - x86 ^(override host auto-detect and build 32 bit code^) - echo - x64 ^(override host auto-detect and build 64 bit code^) - echo - 2013 ^(build with visual studio 2013^) - echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL] - echo - 2017 ^(build with visual studio 2017^) [EXPERIMENTAL] - echo. - :EOF diff --git a/release/scripts/presets/interface_theme/flatty_dark_blueberry.xml b/release/scripts/presets/interface_theme/flatty_dark_blueberry.xml new file mode 100644 index 00000000000..665259bba00 --- /dev/null +++ b/release/scripts/presets/interface_theme/flatty_dark_blueberry.xml @@ -0,0 +1,1225 @@ +<bpy> + <Theme> + <user_interface> + <ThemeUserInterface menu_shadow_fac="0.3" + menu_shadow_width="4" + icon_file="" + icon_alpha="1" + icon_saturation="0.4" + widget_emboss="#00000005" + editor_outline="#1c1d20" + axis_x="#dc4242" + axis_y="#42dc42" + axis_z="#4242dc" + manipulator_hi="#ffffff" + manipulator_primary="#e3ff33" + manipulator_secondary="#33ffff" + manipulator_a="#177f17" + manipulator_b="#7f1717"> + <wcol_regular> + <ThemeWidgetColors outline="#38393e" + inner="#505158ff" + inner_sel="#407180ff" + item="#38393eff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="-5" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_regular> + <wcol_tool> + <ThemeWidgetColors outline="#2f2f34" + inner="#505158ff" + inner_sel="#599eb3ff" + item="#e6ebffff" + text="#f2f2f2" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="-5" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_tool> + <wcol_toolbar_item> + <ThemeWidgetColors outline="#191919" + inner="#505158ff" + inner_sel="#2d2d33ff" + item="#191919ff" + text="#ffffff" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0" + roundness="0.5"> + </ThemeWidgetColors> + </wcol_toolbar_item> + <wcol_radio> + <ThemeWidgetColors outline="#2d2e33" + inner="#505158ff" + inner_sel="#2d2d33ff" + item="#ffffffff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="5" + shadedown="-5" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_radio> + <wcol_text> + <ThemeWidgetColors outline="#43454d" + inner="#2d2e33ff" + inner_sel="#717280ff" + item="#599eb3ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-3" + shadedown="0" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_text> + <wcol_option> + <ThemeWidgetColors outline="#2d2e33" + inner="#2d2e33ff" + inner_sel="#595966ff" + item="#ffffffff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="-15" + roundness="0.5"> + </ThemeWidgetColors> + </wcol_option> + <wcol_toggle> + <ThemeWidgetColors outline="#43434d" + inner="#595966ff" + inner_sel="#599eb3ff" + item="#191919ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0" + roundness="0.5"> + </ThemeWidgetColors> + </wcol_toggle> + <wcol_num> + <ThemeWidgetColors outline="#46464d" + inner="#505158ff" + inner_sel="#3f7180ff" + item="#46464dff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0" + roundness="0.8"> + </ThemeWidgetColors> + </wcol_num> + <wcol_numslider> + <ThemeWidgetColors outline="#46464d" + inner="#3f3f47ff" + inner_sel="#3f7180ff" + item="#505158ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-4" + shadedown="0" + roundness="0.8"> + </ThemeWidgetColors> + </wcol_numslider> + <wcol_box> + <ThemeWidgetColors outline="#2d2e33" + inner="#43454dff" + inner_sel="#599eb3ff" + item="#191919ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_box> + <wcol_menu> + <ThemeWidgetColors outline="#2d2d2d" + inner="#29282eff" + inner_sel="#505158ff" + item="#e6e6e6ff" + text="#eeeeee" + text_sel="#cccccc" + show_shaded="FALSE" + shadetop="10" + shadedown="-10" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_menu> + <wcol_pulldown> + <ThemeWidgetColors outline="#000000" + inner="#29282eff" + inner_sel="#505158ff" + item="#ffffffff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="25" + shadedown="-20" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_pulldown> + <wcol_menu_back> + <ThemeWidgetColors outline="#1f1f1f" + inner="#1f1f1fef" + inner_sel="#505158ff" + item="#646464ff" + text="#b3b3b3" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="25" + shadedown="-20" + roundness="0.5"> + </ThemeWidgetColors> + </wcol_menu_back> + <wcol_pie_menu> + <ThemeWidgetColors outline="#4d4d4d" + inner="#1a1a1aff" + inner_sel="#599eb3ff" + item="#599eb3ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="10" + shadedown="-10" + roundness="1"> + </ThemeWidgetColors> + </wcol_pie_menu> + <wcol_tooltip> + <ThemeWidgetColors outline="#000000" + inner="#1f1f1fef" + inner_sel="#2d2d2de6" + item="#646464ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="25" + shadedown="-20" + roundness="0.5"> + </ThemeWidgetColors> + </wcol_tooltip> + <wcol_menu_item> + <ThemeWidgetColors outline="#000000" + inner="#00000000" + inner_sel="#505158ff" + item="#acacac80" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="38" + shadedown="0" + roundness="0.5"> + </ThemeWidgetColors> + </wcol_menu_item> + <wcol_scroll> + <ThemeWidgetColors outline="#2f3035" + inner="#585a6700" + inner_sel="#599eb3ff" + item="#585a67ff" + text="#ffffff" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="5" + shadedown="-5" + roundness="1"> + </ThemeWidgetColors> + </wcol_scroll> + <wcol_progress> + <ThemeWidgetColors outline="#b3b3b3" + inner="#ccccccff" + inner_sel="#646464b4" + item="#599eb3ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0" + roundness="0.5"> + </ThemeWidgetColors> + </wcol_progress> + <wcol_list_item> + <ThemeWidgetColors outline="#28292d" + inner="#28292d00" + inner_sel="#5f616fff" + item="#599eb3ff" + text="#eeeeee" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0" + roundness="0.4"> + </ThemeWidgetColors> + </wcol_list_item> + <wcol_state> + <ThemeWidgetStateColors inner_anim="#73be4c" + inner_anim_sel="#5aa633" + inner_key="#f0eb64" + inner_key_sel="#d7d34b" + inner_driven="#b400ff" + inner_driven_sel="#9900e6" + inner_overridden="#000000" + inner_overridden_sel="#000000" + blend="0.5"> + </ThemeWidgetStateColors> + </wcol_state> + <wcol_tab> + <ThemeWidgetColors outline="#28292d" + inner="#38393fff" + inner_sel="#43444bff" + item="#28292dff" + text="#ffffff" + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0" + roundness="0.3"> + </ThemeWidgetColors> + </wcol_tab> + </ThemeUserInterface> + </user_interface> + <view_3d> + <ThemeView3D grid="#1f2023" + clipping_border_3d="#313131ff" + wire="#000000" + wire_edit="#407980" + gp_vertex="#000000" + gp_vertex_select="#ff8500" + gp_vertex_size="3" + text_grease_pencil="#b5e61d" + object_selected="#f15800" + object_active="#ffaa40" + text_keyframe="#ddd700" + camera="#b6b6b6" + empty="#b6b6b6" + lamp="#b6b6b633" + speaker="#b6b6b6" + vertex="#407980" + vertex_select="#ff8500" + vertex_size="3" + vertex_bevel="#00a5ff" + vertex_unreferenced="#000000" + edge_select="#ffa000" + edge_seam="#db2512" + edge_sharp="#00ffff" + edge_crease="#cc0099" + edge_bevel="#00a5ff" + edge_facesel="#4b4b4b" + freestyle_edge_mark="#7fff7f" + face="#00000012" + face_select="#ff85004d" + face_dot="#ff8500" + facedot_size="3" + freestyle_face_mark="#7fff7f33" + nurb_uline="#909000" + nurb_vline="#803060" + nurb_sel_uline="#f0ff40" + nurb_sel_vline="#f090a0" + act_spline="#db2512" + handle_free="#000000" + handle_auto="#909000" + handle_vect="#409030" + handle_sel_vect="#40c030" + handle_align="#803060" + handle_sel_free="#000000" + handle_sel_auto="#f0ff40" + handle_sel_align="#f090a0" + lastsel_point="#ffffff" + extra_edge_len="#150806" + extra_edge_angle="#4d4d00" + extra_face_angle="#0000cc" + extra_face_area="#004d00" + editmesh_active="#ffffff80" + normal="#22dddd" + vertex_normal="#2361dd" + split_normal="#dd23dd" + bone_pose="#50c8ff" + bone_pose_active="#8cffff" + bone_solid="#c8c8c8" + bundle_solid="#c8c8c8" + camera_path="#000000" + skin_root="#b44d4d" + view_overlay="#808080" + transform="#ffffff" + frame_current="#60c040" + paint_curve_handle="#7fff7f7f" + paint_curve_pivot="#ff7f7f7f" + outline_width="1"> + <space> + <ThemeSpaceGradient title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282e00" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303500" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <gradients> + <ThemeGradientColors show_grad="TRUE" + gradient="#2d2d2e" + high_gradient="#474748"> + </ThemeGradientColors> + </gradients> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGradient> + </space> + </ThemeView3D> + </view_3d> + <graph_editor> + <ThemeGraphEditor grid="#17171a" + frame_current="#308837" + window_sliders="#969696" + channels_region="#29282e" + dopesheet_channel="#26537f" + dopesheet_subchannel="#6a90b2" + channel_group="#247f0d" + active_channels_group="#46a431" + vertex="#000000" + vertex_select="#ff8500" + vertex_size="6" + vertex_bevel="#000000" + vertex_unreferenced="#000000" + handle_free="#000000" + handle_auto="#909000" + handle_vect="#409030" + handle_sel_vect="#40c030" + handle_align="#803060" + handle_sel_free="#000000" + handle_sel_auto="#f0ff40" + handle_sel_align="#f090a0" + handle_auto_clamped="#994030" + handle_sel_auto_clamped="#f0af90" + lastsel_point="#ffffff" + handle_vertex="#000000" + handle_vertex_select="#ff8500" + handle_vertex_size="5"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + <space_list> + <ThemeSpaceListGeneric list="#29282e" + list_title="#ffffff" + list_text="#cccccc" + list_text_hi="#ffffff"> + </ThemeSpaceListGeneric> + </space_list> + </ThemeGraphEditor> + </graph_editor> + <file_browser> + <ThemeFileBrowser selected_file="#5b8199"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeFileBrowser> + </file_browser> + <nla_editor> + <ThemeNLAEditor grid="#5e5e5e" + view_sliders="#969696" + active_action="#cc701a66" + active_action_unset="#9987614d" + strips="#0c0a0a" + strips_selected="#ff8c00" + transition_strips="#1c2630" + transition_strips_selected="#2e75db" + meta_strips="#332642" + meta_strips_selected="#692196" + sound_strips="#2b3d3d" + sound_strips_selected="#1f7a7a" + tweak="#4df31a" + tweak_duplicate="#d90000" + keyframe_border="#000000ff" + keyframe_border_selected="#000000ff" + frame_current="#308837"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + <space_list> + <ThemeSpaceListGeneric list="#29282e" + list_title="#ffffff" + list_text="#cccccc" + list_text_hi="#cccccc"> + </ThemeSpaceListGeneric> + </space_list> + </ThemeNLAEditor> + </nla_editor> + <dopesheet_editor> + <ThemeDopeSheet grid="#17171a" + frame_current="#308837" + value_sliders="#000000" + view_sliders="#969696" + dopesheet_channel="#2e6399" + dopesheet_subchannel="#7aa4cc" + channels="#707070" + channels_selected="#60c040" + channel_group="#278c0e" + active_channels_group="#4eb335" + long_key="#1a1515" + long_key_selected="#ff8c00" + keyframe="#e8e8e8" + keyframe_selected="#ffbe33" + keyframe_extreme="#e8b3cc" + keyframe_extreme_selected="#f28080" + keyframe_breakdown="#b3dbe8" + keyframe_breakdown_selected="#54bfed" + keyframe_jitter="#94e575" + keyframe_jitter_selected="#61c042" + keyframe_border="#000000ff" + keyframe_border_selected="#000000ff" + keyframe_scale_factor="1" + summary="#66310066"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + <space_list> + <ThemeSpaceListGeneric list="#29282e" + list_title="#ffffff" + list_text="#cccccc" + list_text_hi="#ffffff"> + </ThemeSpaceListGeneric> + </space_list> + </ThemeDopeSheet> + </dopesheet_editor> + <image_editor> + <ThemeImageEditor gp_vertex="#000000" + gp_vertex_select="#ff8500" + gp_vertex_size="3" + vertex="#000000" + vertex_select="#ff8500" + vertex_size="3" + vertex_bevel="#000000" + vertex_unreferenced="#000000" + face="#ffffff0a" + face_select="#ff85003c" + face_dot="#ff8500" + facedot_size="3" + freestyle_face_mark="#7fff7f33" + editmesh_active="#ffffff80" + wire_edit="#c0c0c0" + edge_select="#ff8500" + scope_back="#727272ff" + preview_stitch_face="#7f7f0033" + preview_stitch_edge="#ff00ff33" + preview_stitch_vert="#0000ff33" + preview_stitch_stitchable="#00ff00ff" + preview_stitch_unstitchable="#ff0000ff" + preview_stitch_active="#e1d2c323" + uv_shadow="#707070ff" + uv_others="#606060ff" + frame_current="#60c040" + metadatabg="#000000" + metadatatext="#ffffff" + handle_free="#000000" + handle_auto="#909000" + handle_align="#803060" + handle_sel_free="#000000" + handle_sel_auto="#f0ff40" + handle_sel_align="#f090a0" + handle_auto_clamped="#000000" + handle_sel_auto_clamped="#000000" + handle_vertex="#000000" + handle_vertex_select="#ffff00" + handle_vertex_size="5" + paint_curve_handle="#7fff7f7f" + paint_curve_pivot="#ff7f7f7f"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeImageEditor> + </image_editor> + <sequence_editor> + <ThemeSequenceEditor gp_vertex="#000000" + gp_vertex_select="#ff8500" + gp_vertex_size="3" + grid="#404040" + window_sliders="#a0a0a0" + movie_strip="#516987" + movieclip_strip="#20208f" + image_strip="#6d5881" + scene_strip="#4e983e" + audio_strip="#2e8f8f" + effect_strip="#a9547c" + transition_strip="#a25f6f" + meta_strip="#6d9183" + text_strip="#a29700" + frame_current="#308837" + keyframe="#ff8500" + draw_action="#50c8ff" + preview_back="#000000" + metadatabg="#000000" + metadatatext="#ffffff"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeSequenceEditor> + </sequence_editor> + <properties> + <ThemeProperties> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeProperties> + </properties> + <text_editor> + <ThemeTextEditor line_numbers_background="#313133" + selected_text="#19191a" + cursor="#ff0000" + syntax_builtin="#ff1961" + syntax_symbols="#ff734d" + syntax_special="#95d600" + syntax_preprocessor="#ad80ff" + syntax_reserved="#c4753b" + syntax_comment="#939393" + syntax_string="#f6e162" + syntax_numbers="#50dbff"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeTextEditor> + </text_editor> + <node_editor> + <ThemeNodeEditor gp_vertex="#000000" + gp_vertex_select="#ff8500" + gp_vertex_size="3" + node_selected="#099be6" + node_active="#ffffff" + wire="#808080" + wire_inner="#808080" + wire_select="#ffffff" + selected_text="#7f7070" + node_backdrop="#5a5c66ff" + converter_node="#66c4ff" + color_node="#ffcb4d" + group_node="#59b36a" + group_socket_node="#dfc300" + frame_node="#9b9b9ba0" + matte_node="#977474" + distor_node="#749797" + noodle_curving="0" + input_node="#ff6675" + output_node="#ff6675" + filter_node="#6c696f" + vector_node="#9999ff" + texture_node="#ffc399" + shader_node="#a7ff99" + script_node="#6c696f" + pattern_node="#6c696f" + layout_node="#6c696f"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + <space_list> + <ThemeSpaceListGeneric list="#29282e" + list_title="#ffffff" + list_text="#cccccc" + list_text_hi="#ffffff"> + </ThemeSpaceListGeneric> + </space_list> + </ThemeNodeEditor> + </node_editor> + <outliner> + <ThemeOutliner match="#337f33" + selected_highlight="#7297d0"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeOutliner> + </outliner> + <info> + <ThemeInfo info_selected="#6080ff" + info_selected_text="#ffffff" + info_error="#990000" + info_error_text="#ffffff" + info_warning="#b36a00" + info_warning_text="#ffffff" + info_info="#668000" + info_info_text="#ffffff" + info_debug="#d3d3d3" + info_debug_text="#000000"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeInfo> + </info> + <user_preferences> + <ThemeUserPreferences> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeUserPreferences> + </user_preferences> + <console> + <ThemeConsole line_output="#6080ff" + line_input="#ffffff" + line_info="#00aa00" + line_error="#dc6060" + cursor="#dc6060" + select="#ffffff30"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeConsole> + </console> + <clip_editor> + <ThemeClipEditor gp_vertex="#000000" + gp_vertex_select="#000000" + gp_vertex_size="1" + marker_outline="#000000" + marker="#7f7f00" + active_marker="#ffffff" + selected_marker="#ffff00" + disabled_marker="#7f0000" + locked_marker="#7f7f7f" + path_before="#ff0000" + path_after="#0000ff" + frame_current="#308837" + strips="#0c0a0a" + strips_selected="#ff8c00" + handle_free="#000000" + handle_auto="#909000" + handle_align="#803060" + handle_sel_free="#000000" + handle_sel_auto="#f0ff40" + handle_sel_align="#f090a0" + handle_auto_clamped="#000000" + handle_sel_auto_clamped="#000000" + handle_vertex="#000000" + handle_vertex_select="#ffff00" + handle_vertex_size="5"> + <space> + <ThemeSpaceGeneric back="#2f3035" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + <space_list> + <ThemeSpaceListGeneric list="#666666" + list_title="#000000" + list_text="#000000" + list_text_hi="#ffffff"> + </ThemeSpaceListGeneric> + </space_list> + </ThemeClipEditor> + </clip_editor> + <topbar> + <ThemeTopBar> + <space> + <ThemeSpaceGeneric back="#43444b" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#29282eff" + header_text="#eeeeee" + header_text_hi="#ffffff" + button="#2f303599" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeTopBar> + </topbar> + <statusbar> + <ThemeStatusBar> + <space> + <ThemeSpaceGeneric back="#09090a" + title="#8f8f8f" + text="#8f8f8f" + text_hi="#ffffff" + header="#252528ff" + header_text="#cbcbcb" + header_text_hi="#ffffff" + button="#72727280" + button_title="#000000" + button_text="#000000" + button_text_hi="#ffffff" + tab_active="#727272" + tab_inactive="#535353" + tab_back="#404040ff" + tab_outline="#3c3c3c"> + <panelcolors> + <ThemePanelColors header="#5f5f5fff" + back="#46464699" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeStatusBar> + </statusbar> + <bone_color_sets> + <ThemeBoneColorSet normal="#9a0000" + select="#bd1111" + active="#f70a0a" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#f74018" + select="#f66913" + active="#fa9900" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#1e9109" + select="#59b70b" + active="#83ef1d" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#0a3694" + select="#3667df" + active="#5ec1ef" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#a9294e" + select="#c1416a" + active="#f05d91" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#430c78" + select="#543aa3" + active="#8764d5" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#24785a" + select="#3c9579" + active="#6fb6ab" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#4b707c" + select="#6a8691" + active="#9bc2cd" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#f4c90c" + select="#eec236" + active="#f3ff00" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#1e2024" + select="#484c56" + active="#ffffff" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#6f2f6a" + select="#9845be" + active="#d330d6" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#6c8e22" + select="#7fb022" + active="#bbef5b" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#8d8d8d" + select="#b0b0b0" + active="#dedede" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#834326" + select="#8b5811" + active="#bd6a11" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#08310e" + select="#1c430b" + active="#34622b" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#000000" + select="#000000" + active="#000000" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#000000" + select="#000000" + active="#000000" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#000000" + select="#000000" + active="#000000" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#000000" + select="#000000" + active="#000000" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + <ThemeBoneColorSet normal="#000000" + select="#000000" + active="#000000" + show_colored_constraints="FALSE"> + </ThemeBoneColorSet> + </bone_color_sets> + </Theme> + <ThemeStyle> + <panel_title> + <ThemeFontStyle points="11" + font_kerning_style="FITTED" + shadow="1" + shadow_offset_x="0" + shadow_offset_y="-1" + shadow_alpha="0.15" + shadow_value="1"> + </ThemeFontStyle> + </panel_title> + <widget_label> + <ThemeFontStyle points="11" + font_kerning_style="FITTED" + shadow="3" + shadow_offset_x="0" + shadow_offset_y="-1" + shadow_alpha="0.15" + shadow_value="1"> + </ThemeFontStyle> + </widget_label> + <widget> + <ThemeFontStyle points="11" + font_kerning_style="FITTED" + shadow="5" + shadow_offset_x="0" + shadow_offset_y="-1" + shadow_alpha="0.5" + shadow_value="0"> + </ThemeFontStyle> + </widget> + </ThemeStyle> +</bpy> diff --git a/release/scripts/presets/interface_theme/flatty_light.xml b/release/scripts/presets/interface_theme/flatty_light.xml index c1d4dce5f2c..c12a41dc8cc 100644 --- a/release/scripts/presets/interface_theme/flatty_light.xml +++ b/release/scripts/presets/interface_theme/flatty_light.xml @@ -2,20 +2,20 @@ <Theme> <user_interface> <ThemeUserInterface menu_shadow_fac="0.3" - menu_shadow_width="2" + menu_shadow_width="4" icon_file="" icon_alpha="1" icon_saturation="0.3" widget_emboss="#00000005" editor_outline="#313338" - axis_x="#dc2c2c" - axis_y="#2cdc2c" - axis_z="#2c2cdc" + axis_x="#ff3352" + axis_y="#8bdc00" + axis_z="#046bdc" manipulator_hi="#ffffff" - manipulator_primary="#deff0d" - manipulator_secondary="#00ffff" - manipulator_a="#177f17" - manipulator_b="#7f1717"> + manipulator_primary="#ffd842" + manipulator_secondary="#43c2ff" + manipulator_a="#2b9757" + manipulator_b="#c43164"> <wcol_regular> <ThemeWidgetColors outline="#9d9d9d" inner="#b3b3b3ff" @@ -270,8 +270,8 @@ inner_key_sel="#d7d34b" inner_driven="#b400ff" inner_driven_sel="#9900e6" - inner_overridden="#000000" - inner_overridden_sel="#000000" + inner_overridden="#6bf3cc" + inner_overridden_sel="#5fd9b6" blend="0.5"> </ThemeWidgetStateColors> </wcol_state> @@ -302,10 +302,10 @@ object_selected="#f15800" object_active="#ffaa40" text_keyframe="#ddd700" - camera="#000000" - empty="#000000" - lamp="#00000028" - speaker="#000000" + camera="#b3b3b3" + empty="#b3b3b3" + lamp="#cccccc33" + speaker="#b3b3b3" vertex="#000000" vertex_select="#ff8500" vertex_size="3" @@ -1058,6 +1058,35 @@ </space> </ThemeTopBar> </topbar> + <statusbar> + <ThemeStatusBar> + <space> + <ThemeSpaceGeneric back="#393939" + title="#ffffff" + text="#ffffff" + text_hi="#ffffff" + header="#adadadff" + header_text="#1a1a1a" + header_text_hi="#ffffff" + button="#2f303500" + button_title="#ffffff" + button_text="#ffffff" + button_text_hi="#ffffff" + tab_active="#446499" + tab_inactive="#28292d" + tab_back="#28292dff" + tab_outline="#28292d"> + <panelcolors> + <ThemePanelColors header="#29282eff" + back="#3e3f46ff" + show_header="TRUE" + show_back="TRUE"> + </ThemePanelColors> + </panelcolors> + </ThemeSpaceGeneric> + </space> + </ThemeStatusBar> + </statusbar> <bone_color_sets> <ThemeBoneColorSet normal="#9a0000" select="#bd1111" diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py index 1d7e5807b34..2e3dae25197 100644 --- a/release/scripts/startup/bl_ui/properties_data_lamp.py +++ b/release/scripts/startup/bl_ui/properties_data_lamp.py @@ -136,9 +136,9 @@ class DATA_PT_EEVEE_lamp(DataButtonsPanel, Panel): elif lamp.type == 'AREA': sub = sub.column(align=True) sub.prop(lamp, "shape", text="") - if lamp.shape == 'SQUARE': + if lamp.shape in {'SQUARE', 'DISK'}: sub.prop(lamp, "size") - elif lamp.shape == 'RECTANGLE': + elif lamp.shape in {'RECTANGLE', 'ELLIPSE'}: sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") @@ -228,9 +228,9 @@ class DATA_PT_area(DataButtonsPanel, Panel): col.row().prop(lamp, "shape", expand=True) sub = col.row(align=True) - if lamp.shape == 'SQUARE': + if lamp.shape in {'SQUARE', 'DISK'}: sub.prop(lamp, "size") - elif lamp.shape == 'RECTANGLE': + elif lamp.shape in {'RECTANGLE', 'ELLIPSE'}: sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") diff --git a/release/scripts/startup/bl_ui/properties_data_lightprobe.py b/release/scripts/startup/bl_ui/properties_data_lightprobe.py index 89bf040dabf..c56d40df906 100644 --- a/release/scripts/startup/bl_ui/properties_data_lightprobe.py +++ b/release/scripts/startup/bl_ui/properties_data_lightprobe.py @@ -111,10 +111,10 @@ class DATA_PT_lightprobe(DataButtonsPanel, Panel): col.separator() - col.label("Visibility Group:") + col.label("Visibility Collection:") row = col.row(align=True) - row.prop(probe, "visibility_group", text="") - row.prop(probe, "invert_visibility_group", text="", icon='ARROW_LEFTRIGHT') + row.prop(probe, "visibility_collection", text="") + row.prop(probe, "invert_visibility_collection", text="", icon='ARROW_LEFTRIGHT') class DATA_PT_lightprobe_parallax(DataButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index fb1d62a92db..abdf1ed2db1 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -328,7 +328,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): row.prop(md, "delimit") layout_info = layout - layout_info.label(text=iface_("Faces: %d") % md.face_count, translate=False) + layout_info.label(text=iface_("Face Count: {:,}".format(md.face_count)), + translate=False) def DISPLACE(self, layout, ob, md): has_texture = (md.texture is not None) diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 13c783ad024..9b70c8f22d4 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -204,7 +204,7 @@ class EEVEE_MATERIAL_PT_options(MaterialButtonsPanel, Panel): row.prop(mat, "alpha_threshold") if mat.blend_method not in {"OPAQUE", "CLIP", "HASHED"}: - layout.prop(mat, "transparent_hide_backside") + layout.prop(mat, "show_transparent_backside") layout.prop(mat, "use_screen_refraction") layout.prop(mat, "refraction_depth") diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 93de404245f..bccde2da2f4 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -75,28 +75,6 @@ class RENDER_PT_context(Panel): layout.prop(rd, "engine", text="") -class RENDER_PT_render(RenderButtonsPanel, Panel): - bl_label = "Render" - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} - - def draw(self, context): - layout = self.layout - - rd = context.scene.render - - row = layout.row(align=True) - row.operator("render.render", text="Render", icon='RENDER_STILL') - row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True - row.operator("sound.mixdown", text="Audio", icon='PLAY_AUDIO') - - split = layout.split(percentage=0.33) - - split.label(text="Display:") - row = split.row(align=True) - row.prop(rd, "display_mode", text="") - row.prop(rd, "use_lock_interface", icon_only=True) - - class RENDER_PT_dimensions(RenderButtonsPanel, Panel): bl_label = "Dimensions" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} @@ -465,17 +443,17 @@ class RENDER_PT_eevee_ambient_occlusion(RenderButtonsPanel, Panel): def draw_header(self, context): scene = context.scene props = scene.eevee - self.layout.prop(props, "gtao_enable", text="") + self.layout.prop(props, "use_gtao", text="") def draw(self, context): layout = self.layout scene = context.scene props = scene.eevee - layout.active = props.gtao_enable + layout.active = props.use_gtao col = layout.column() - col.prop(props, "gtao_use_bent_normals") - col.prop(props, "gtao_bounce") + col.prop(props, "use_gtao_bent_normals") + col.prop(props, "use_gtao_bounce") col.prop(props, "gtao_distance") col.prop(props, "gtao_factor") col.prop(props, "gtao_quality") @@ -493,14 +471,14 @@ class RENDER_PT_eevee_motion_blur(RenderButtonsPanel, Panel): def draw_header(self, context): scene = context.scene props = scene.eevee - self.layout.prop(props, "motion_blur_enable", text="") + self.layout.prop(props, "use_motion_blur", text="") def draw(self, context): layout = self.layout scene = context.scene props = scene.eevee - layout.active = props.motion_blur_enable + layout.active = props.use_motion_blur col = layout.column() col.prop(props, "motion_blur_samples") col.prop(props, "motion_blur_shutter") @@ -518,14 +496,14 @@ class RENDER_PT_eevee_depth_of_field(RenderButtonsPanel, Panel): def draw_header(self, context): scene = context.scene props = scene.eevee - self.layout.prop(props, "dof_enable", text="") + self.layout.prop(props, "use_dof", text="") def draw(self, context): layout = self.layout scene = context.scene props = scene.eevee - layout.active = props.dof_enable + layout.active = props.use_dof col = layout.column() col.prop(props, "bokeh_max_size") col.prop(props, "bokeh_threshold") @@ -543,14 +521,14 @@ class RENDER_PT_eevee_bloom(RenderButtonsPanel, Panel): def draw_header(self, context): scene = context.scene props = scene.eevee - self.layout.prop(props, "bloom_enable", text="") + self.layout.prop(props, "use_bloom", text="") def draw(self, context): layout = self.layout scene = context.scene props = scene.eevee - layout.active = props.bloom_enable + layout.active = props.use_bloom col = layout.column() col.prop(props, "bloom_threshold") col.prop(props, "bloom_knee") @@ -572,25 +550,25 @@ class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel): def draw_header(self, context): scene = context.scene props = scene.eevee - self.layout.prop(props, "volumetric_enable", text="") + self.layout.prop(props, "use_volumetric", text="") def draw(self, context): layout = self.layout scene = context.scene props = scene.eevee - layout.active = props.volumetric_enable + layout.active = props.use_volumetric col = layout.column() col.prop(props, "volumetric_start") col.prop(props, "volumetric_end") col.prop(props, "volumetric_tile_size") col.prop(props, "volumetric_samples") col.prop(props, "volumetric_sample_distribution") - col.prop(props, "volumetric_lights") + col.prop(props, "use_volumetric_lights") col.prop(props, "volumetric_light_clamp") - col.prop(props, "volumetric_shadows") + col.prop(props, "use_volumetric_shadows") col.prop(props, "volumetric_shadow_samples") - col.prop(props, "volumetric_colored_transmittance") + col.prop(props, "use_volumetric_colored_transmittance") class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel): @@ -605,7 +583,7 @@ class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel): def draw_header(self, context): scene = context.scene props = scene.eevee - self.layout.prop(props, "sss_enable", text="") + self.layout.prop(props, "use_sss", text="") def draw(self, context): layout = self.layout @@ -615,7 +593,7 @@ class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel): col = layout.column() col.prop(props, "sss_samples") col.prop(props, "sss_jitter_threshold") - col.prop(props, "sss_separate_albedo") + col.prop(props, "use_sss_separate_albedo") class RENDER_PT_eevee_screen_space_reflections(RenderButtonsPanel, Panel): @@ -630,7 +608,7 @@ class RENDER_PT_eevee_screen_space_reflections(RenderButtonsPanel, Panel): def draw_header(self, context): scene = context.scene props = scene.eevee - self.layout.prop(props, "ssr_enable", text="") + self.layout.prop(props, "use_ssr", text="") def draw(self, context): layout = self.layout @@ -638,9 +616,9 @@ class RENDER_PT_eevee_screen_space_reflections(RenderButtonsPanel, Panel): props = scene.eevee col = layout.column() - col.active = props.ssr_enable - col.prop(props, "ssr_refraction") - col.prop(props, "ssr_halfres") + col.active = props.use_ssr + col.prop(props, "use_ssr_refraction") + col.prop(props, "use_ssr_halfres") col.prop(props, "ssr_quality") col.prop(props, "ssr_max_roughness") col.prop(props, "ssr_thickness") @@ -666,7 +644,7 @@ class RENDER_PT_eevee_shadows(RenderButtonsPanel, Panel): col.prop(props, "shadow_method") col.prop(props, "shadow_cube_size") col.prop(props, "shadow_cascade_size") - col.prop(props, "shadow_high_bitdepth") + col.prop(props, "use_shadow_high_bitdepth") class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel): @@ -686,7 +664,7 @@ class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel): col = layout.column() col.prop(props, "taa_samples") col.prop(props, "taa_render_samples") - col.prop(props, "taa_reprojection") + col.prop(props, "use_taa_reprojection") class RENDER_PT_eevee_indirect_lighting(RenderButtonsPanel, Panel): @@ -737,7 +715,6 @@ classes = ( RENDER_MT_ffmpeg_presets, RENDER_MT_framerate_presets, RENDER_PT_context, - RENDER_PT_render, RENDER_PT_dimensions, RENDER_PT_post_processing, RENDER_PT_stamp, diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 10b18328cea..a3dc401b484 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -1232,9 +1232,8 @@ class CLIP_MT_view(Menu): layout.prop(sc, "show_locked_time") layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + + layout.menu("INFO_MT_area") class CLIP_MT_clip(Menu): diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py index e6f96d989c7..dd5ab03fcba 100644 --- a/release/scripts/startup/bl_ui/space_console.py +++ b/release/scripts/startup/bl_ui/space_console.py @@ -69,9 +69,7 @@ class CONSOLE_MT_console(Menu): layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class CONSOLE_MT_language(Menu): diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index c4b867ab647..f3841de3ba4 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -255,9 +255,7 @@ class DOPESHEET_MT_view(Menu): layout.operator("action.view_frame") layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class DOPESHEET_MT_select(Menu): diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 219043d0467..7e927bb6385 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -129,9 +129,7 @@ class GRAPH_MT_view(Menu): layout.operator("graph.view_frame") layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class GRAPH_MT_select(Menu): diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 4f837acabc3..b1ff1618d09 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -126,9 +126,7 @@ class IMAGE_MT_view(Menu): layout.operator("image.cycle_render_slot", text="Render Slot Cycle Previous").reverse = True layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class IMAGE_MT_select(Menu): @@ -645,11 +643,11 @@ class IMAGE_PT_view_properties(Panel): col.label(text="Coordinates:") col.prop(sima, "show_repeat", text="Repeat") if show_uvedit: - col.prop(uvedit, "show_normalized_coords", text="Normalized") + col.prop(uvedit, "show_pixel_coords", text="Pixel") elif show_uvedit: col.label(text="Coordinates:") - col.prop(uvedit, "show_normalized_coords", text="Normalized") + col.prop(uvedit, "show_pixel_coords", text="Pixel") if show_uvedit or show_maskedit: col = layout.column() diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 5460a8d44b2..e5ef5f9a0da 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -31,8 +31,24 @@ class INFO_HT_header(Header): # Empty for now until info editor gets turned into log editor pass + +# Not really info, just add to re-usable location. +class INFO_MT_area(Menu): + bl_label = "Area" + + def draw(self, context): + layout = self.layout + + layout.operator("screen.area_dupli") + if context.space_data.type == 'VIEW_3D': + layout.operator("screen.region_quadview") + layout.operator("screen.screen_full_area") + layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + + classes = ( INFO_HT_header, + INFO_MT_area, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index 8a933570c5e..2f1c1d8325e 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -90,9 +90,7 @@ class NLA_MT_view(Menu): layout.operator("nla.view_frame") layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class NLA_MT_select(Menu): diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 61a3eb84fa0..375e101a6a5 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -193,9 +193,7 @@ class NODE_MT_view(Menu): layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class NODE_MT_select(Menu): diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index 2a59c2c5f79..8b8526cf9f2 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -118,9 +118,7 @@ class OUTLINER_MT_view(Menu): layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class OUTLINER_MT_edit_datablocks(Menu): diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index cb7ed8b931f..ce1d1da038c 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -237,9 +237,7 @@ class SEQUENCER_MT_view(Menu): layout.prop(st, "use_marker_sync") layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class SEQUENCER_MT_select(Menu): @@ -431,10 +429,6 @@ class SEQUENCER_MT_strip(Menu): layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("ed.undo") - layout.operator("ed.redo") - layout.operator("ed.undo_history") - layout.separator() layout.menu("SEQUENCER_MT_strip_transform") layout.operator("sequencer.snap") diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index 98a7da855ca..b1af82c95fe 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -180,9 +180,7 @@ class TEXT_MT_view(Menu): layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class TEXT_MT_text(Menu): diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index 3a6fa40aebd..48ac85f0d0e 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -112,7 +112,10 @@ class TIME_MT_editor_menus(Menu): region_type='HEADER', panel_type="TIME_PT_playback", text="Playback") - + layout.popover(space_type='DOPESHEET_EDITOR', + region_type='HEADER', + panel_type="TIME_PT_keyframing_settings", + text="Keying") class TIME_MT_marker(Menu): bl_label = "Marker" @@ -152,9 +155,7 @@ class TIME_MT_view(Menu): layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class TIME_MT_cache(Menu): @@ -267,6 +268,7 @@ class TIME_PT_playback(TimelinePanelButtons, Panel): class TIME_PT_keyframing_settings(TimelinePanelButtons, Panel): bl_label = "Keyframing Settings" bl_options = {'HIDE_HEADER'} + bl_region_type = 'HEADER' @classmethod def poll(cls, context): diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 8bcd56ce561..42fac9e03a4 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -87,6 +87,20 @@ class _defs_view3d_generic: text="Cursor", icon="ops.generic.cursor", keymap=( + ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='PRESS')), + ("transform.translate", + dict(release_confirm=True, cursor_transform=True), + dict(type='EVT_TWEAK_A', value='ANY'), + ), + ), + ) + + @ToolDef.from_fn + def cursor_click(): + return dict( + text="Cursor Click", + icon="ops.generic.cursor", + keymap=( ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='CLICK')), ), ) @@ -1018,6 +1032,11 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_edit_curve.draw, _defs_edit_curve.extrude_cursor, ], + 'PARTICLE': [ + # TODO(campbell): use cursor click tool to allow paint tools to run, + # we need to integrate particle system tools properly. + _defs_view3d_generic.cursor_click, + ], 'SCULPT': [ _defs_sculpt.generate_from_brushes, ], diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 4eabf2bf327..53acc29dfad 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -400,6 +400,7 @@ class INFO_MT_editor_menus(Menu): @staticmethod def draw_menus(layout, context): layout.menu("INFO_MT_file") + layout.menu("INFO_MT_edit") layout.menu("INFO_MT_render") @@ -433,8 +434,6 @@ class INFO_MT_file(Menu): layout.separator() - layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES') - layout.operator_context = 'INVOKE_AREA' layout.operator("wm.save_homefile", icon='SAVE_PREFS') layout.operator("wm.read_factory_settings", icon='LOAD_FACTORY') @@ -554,16 +553,27 @@ class INFO_MT_render(Menu): def draw(self, context): layout = self.layout + rd = context.scene.render + layout.operator("render.render", text="Render Image", icon='RENDER_STILL').use_viewport = True props = layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION') props.animation = True props.use_viewport = True + layout.operator("sound.mixdown", text="Render Audio", icon='PLAY_AUDIO') layout.separator() - layout.operator("render.opengl", text="OpenGL Render Image") - layout.operator("render.opengl", text="OpenGL Render Animation").animation = True - layout.menu("INFO_MT_opengl_render") + layout.prop_menu_enum(rd, "display_mode", text="Display Mode", icon='IMAGE_COL') + layout.prop(rd, "use_lock_interface", text="Lock Interface") + + layout.separator() + + props = layout.operator("render.opengl", text="OpenGL Render Image", icon='RENDER_STILL') + props.view_context = False + props = layout.operator("render.opengl", text="OpenGL Render Animation", icon='RENDER_ANIMATION') + props.view_context = False + props.animation = True + layout.menu("INFO_MT_opengl_render", icon='SETTINGS') layout.separator() @@ -585,6 +595,24 @@ class INFO_MT_opengl_render(Menu): layout.prop_menu_enum(rd, "alpha_mode") +class INFO_MT_edit(Menu): + bl_label = "Edit" + + def draw(self, context): + layout = self.layout + + layout.operator("ed.undo") + layout.operator("ed.redo") + + layout.separator() + + layout.operator("ed.undo_history") + + layout.separator() + + layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES') + + class INFO_MT_window(Menu): bl_label = "Window" @@ -664,6 +692,7 @@ classes = ( INFO_MT_file_export, INFO_MT_file_external_data, INFO_MT_file_previews, + INFO_MT_edit, INFO_MT_game, INFO_MT_render, INFO_MT_opengl_render, diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 4f5791101a9..213d231c37a 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -201,8 +201,6 @@ class VIEW3D_MT_transform_base(Menu): def draw(self, context): layout = self.layout - layout.separator() - layout.operator("transform.tosphere", text="To Sphere") layout.operator("transform.shear", text="Shear") layout.operator("transform.bend", text="Bend") @@ -384,6 +382,11 @@ class VIEW3D_MT_uv_map(Menu): layout.operator("uv.reset") + layout.separator() + + layout.operator("mesh.uvs_rotate") + layout.operator("mesh.uvs_reverse") + class VIEW3D_MT_edit_proportional(Menu): bl_label = "Proportional Editing" @@ -409,17 +412,17 @@ class VIEW3D_MT_view(Menu): layout = self.layout view = context.space_data - layout.operator("view3d.properties", icon='MENU_PANEL') - layout.operator("view3d.toolshelf", icon='MENU_PANEL') + layout.operator("view3d.toolshelf", icon='MENU_PANEL', text="Show Toolbar") + layout.operator("view3d.properties", icon='MENU_PANEL', text="Show Sidebar") layout.separator() - layout.operator("view3d.view_selected").use_all_regions = False + layout.operator("view3d.view_selected", text="Frame Selected").use_all_regions = False if view.region_quadviews: - layout.operator("view3d.view_selected", text="View Selected (Quad View)").use_all_regions = True + layout.operator("view3d.view_selected", text="Frame Selected (Quad View)").use_all_regions = True - layout.operator("view3d.view_all").center = False - layout.operator("view3d.view_persportho") + layout.operator("view3d.view_all", text="Frame All").center = False + layout.operator("view3d.view_persportho", text="Perspective/Orthographic") layout.separator() @@ -437,23 +440,16 @@ class VIEW3D_MT_view(Menu): layout.separator() - layout.operator("view3d.layers", text="Show All Layers").nr = 0 - - layout.separator() - - layout.operator("screen.animation_play", text="Playback Animation") + layout.operator("screen.animation_play", text="Play Animation") layout.separator() layout.operator("render.opengl", icon='RENDER_STILL') - layout.operator("render.opengl", text="OpenGL Render (Animation)", icon='RENDER_ANIMATION').animation = True + layout.operator("render.opengl", text="OpenGL Render Animation", icon='RENDER_ANIMATION').animation = True layout.separator() - layout.operator("screen.area_dupli") - layout.operator("screen.region_quadview") - layout.operator("screen.screen_full_area") - layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True + layout.menu("INFO_MT_area") class VIEW3D_MT_view_cameras(Menu): @@ -634,12 +630,12 @@ class VIEW3D_MT_select_object(Menu): layout.separator() - layout.operator("object.select_all").action = 'TOGGLE' - layout.operator("object.select_all", text="Inverse").action = 'INVERT' - layout.operator("object.select_random", text="Random") - layout.operator("object.select_mirror", text="Mirror") + layout.operator("object.select_all", text="Select/Deselect All").action = 'TOGGLE' layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...") - layout.operator("object.select_camera", text="Select Camera") + layout.operator("object.select_camera", text="Select Active Camera") + layout.operator("object.select_all", text="Inverse Selection").action = 'INVERT' + layout.operator("object.select_mirror", text="Mirror Selection") + layout.operator("object.select_random", text="Select Random") layout.separator() @@ -647,8 +643,8 @@ class VIEW3D_MT_select_object(Menu): layout.separator() - layout.operator_menu_enum("object.select_grouped", "type", text="Grouped") - layout.operator_menu_enum("object.select_linked", "type", text="Linked") + layout.operator_menu_enum("object.select_grouped", "type", text="Select Grouped") + layout.operator_menu_enum("object.select_linked", "type", text="Select Linked") layout.operator("object.select_pattern", text="Select Pattern...") @@ -821,19 +817,19 @@ class VIEW3D_MT_select_edit_mesh(Menu): layout.separator() # primitive - layout.operator("mesh.select_all").action = 'TOGGLE' - layout.operator("mesh.select_all", text="Inverse").action = 'INVERT' + layout.operator("mesh.select_all", text="Select/Deselect All").action = 'TOGGLE' + layout.operator("mesh.select_all", text="Inverse Selection").action = 'INVERT' layout.separator() # numeric - layout.operator("mesh.select_random", text="Random") + layout.operator("mesh.select_random", text="Select Random") layout.operator("mesh.select_nth") layout.separator() # geometric - layout.operator("mesh.edges_select_sharp", text="Sharp Edges") + layout.operator("mesh.edges_select_sharp", text="Select Sharp Edges") layout.separator() @@ -859,7 +855,7 @@ class VIEW3D_MT_select_edit_mesh(Menu): layout.separator() layout.operator("mesh.select_axis", text="Side of Active") - layout.operator("mesh.select_mirror", text="Mirror") + layout.operator("mesh.select_mirror", text="Mirror Selection") class VIEW3D_MT_select_edit_curve(Menu): @@ -935,10 +931,6 @@ class VIEW3D_MT_select_edit_text(Menu): def draw(self, context): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - layout.operator("font.text_paste", text="Paste") layout.operator("font.text_cut", text="Cut") layout.operator("font.text_copy", text="Copy") @@ -1205,7 +1197,8 @@ class INFO_MT_surface_add(Menu): layout.operator("surface.primitive_nurbs_surface_curve_add", text="Nurbs Curve", icon='SURFACE_NCURVE') layout.operator("surface.primitive_nurbs_surface_circle_add", text="Nurbs Circle", icon='SURFACE_NCIRCLE') layout.operator("surface.primitive_nurbs_surface_surface_add", text="Nurbs Surface", icon='SURFACE_NSURFACE') - layout.operator("surface.primitive_nurbs_surface_cylinder_add", text="Nurbs Cylinder", icon='SURFACE_NCYLINDER') + layout.operator("surface.primitive_nurbs_surface_cylinder_add", + text="Nurbs Cylinder", icon='SURFACE_NCYLINDER') layout.operator("surface.primitive_nurbs_surface_sphere_add", text="Nurbs Sphere", icon='SURFACE_NSPHERE') layout.operator("surface.primitive_nurbs_surface_torus_add", text="Nurbs Torus", icon='SURFACE_NTORUS') @@ -1337,7 +1330,11 @@ class INFO_MT_add(Menu): if len(bpy.data.collections) > 10: layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("object.collection_instance_add", text="Collection Instance...", icon='OUTLINER_OB_GROUP_INSTANCE') + layout.operator( + "object.collection_instance_add", + text="Collection Instance...", + icon='OUTLINER_OB_GROUP_INSTANCE', + ) else: layout.operator_menu_enum( "object.collection_instance_add", @@ -1347,21 +1344,6 @@ class INFO_MT_add(Menu): ) -class VIEW3D_MT_undo_redo(Menu): - bl_label = "Undo/Redo" - _operator_name = "" - - def draw(self, context): - layout = self.layout - - layout.operator("ed.undo") - layout.operator("ed.redo") - - layout.separator() - - layout.operator("ed.undo_history") - - class VIEW3D_MT_object_relations(Menu): bl_label = "Relations" @@ -1390,24 +1372,10 @@ class VIEW3D_MT_object(Menu): def draw(self, context): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - - layout.operator("object.delete", text="Delete...").use_global = False - - layout.separator() - layout.menu("VIEW3D_MT_transform_object") layout.menu("VIEW3D_MT_mirror") layout.menu("VIEW3D_MT_object_clear") layout.menu("VIEW3D_MT_object_apply") - layout.menu("VIEW3D_MT_object_shading") - - layout.separator() - - layout.menu("VIEW3D_MT_object_parent") - layout.menu("VIEW3D_MT_object_collection") layout.menu("VIEW3D_MT_snap") layout.separator() @@ -1415,11 +1383,25 @@ class VIEW3D_MT_object(Menu): layout.operator("object.duplicate_move") layout.operator("object.duplicate_move_linked") layout.operator("object.join") + layout.separator() - layout.menu("VIEW3D_MT_make_links", text="Make Links...") + + layout.operator("view3d.copybuffer", text="Copy Objects") + layout.operator("view3d.pastebuffer", text="Paste Objects") + + layout.separator() + + layout.menu("VIEW3D_MT_object_parent") + layout.menu("VIEW3D_MT_object_collection") layout.menu("VIEW3D_MT_object_relations") layout.menu("VIEW3D_MT_object_constraints") layout.menu("VIEW3D_MT_object_track") + layout.menu("VIEW3D_MT_make_links", text="Make Links...") + + layout.separator() + + layout.operator("object.shade_smooth", text="Smooth Shading") + layout.operator("object.shade_flat", text="Flat Shading") layout.separator() @@ -1434,6 +1416,10 @@ class VIEW3D_MT_object(Menu): layout.operator_menu_enum("object.convert", "target") + layout.separator() + + layout.operator("object.delete", text="Delete...").use_global = False + class VIEW3D_MT_object_animation(Menu): bl_label = "Animation" @@ -1493,7 +1479,7 @@ class VIEW3D_MT_object_clear(Menu): class VIEW3D_MT_object_specials(Menu): - bl_label = "Specials" + bl_label = "Context Menu" @classmethod def poll(cls, context): @@ -1506,6 +1492,42 @@ class VIEW3D_MT_object_specials(Menu): scene = context.scene obj = context.object + layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN') + layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN') + + layout.separator() + + layout.operator("object.duplicate_move") + layout.operator("object.duplicate_move_linked") + + layout.separator() + + layout.menu("VIEW3D_MT_snap") + layout.menu("VIEW3D_MT_object_parent") + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("object.move_to_collection") + + layout.separator() + + layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...") + + layout.separator() + + layout.operator("object.delete", text="Delete...").use_global = False + + if obj.type == 'MESH': + + layout.separator() + + layout.operator("object.shade_smooth", text="Smooth Shading") + layout.operator("object.shade_flat", text="Flat Shading") + + layout.separator() + + layout.operator("object.origin_set") + layout.operator("object.join") + layout.operator_menu_enum("object.convert", "target") + if obj.type == 'CAMERA': layout.operator_context = 'INVOKE_REGION_WIN' @@ -1589,7 +1611,7 @@ class VIEW3D_MT_object_specials(Menu): props.data_path_item = "data.size" props.header_text = "Lamp Size X: %.3f" - if lamp.shape == 'RECTANGLE': + if lamp.shape in {'RECTANGLE', 'ELLIPSE'}: props = layout.operator("wm.context_modal_mouse", text="Size Y") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.size_y" @@ -1615,11 +1637,6 @@ class VIEW3D_MT_object_specials(Menu): props.input_scale = -0.01 props.header_text = "Spot Blend: %.2f" - layout.separator() - - props = layout.operator("object.isolate_type_render") - props = layout.operator("object.hide_render_clear_all") - class VIEW3D_MT_object_shading(Menu): # XXX, this menu is a place to store shading operator in object mode @@ -1883,10 +1900,6 @@ class VIEW3D_MT_paint_vertex(Menu): def draw(self, context): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - layout.operator("paint.vertex_color_set") layout.operator("paint.vertex_color_smooth") layout.operator("paint.vertex_color_dirt") @@ -1959,9 +1972,6 @@ class VIEW3D_MT_paint_weight(Menu): def draw_generic(layout, is_editmode=False): if not is_editmode: - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() layout.operator("paint.weight_from_bones", text="Assign Automatic From Bones").type = 'AUTOMATIC' layout.operator("paint.weight_from_bones", text="Assign From Bone Envelopes").type = 'ENVELOPES' @@ -1991,14 +2001,13 @@ class VIEW3D_MT_paint_weight(Menu): layout.operator("object.vertex_group_limit_total", text="Limit Total") layout.operator("object.vertex_group_fix", text="Fix Deforms") - if not is_editmode: layout.separator() layout.operator("paint.weight_set") def draw(self, context): - self.draw_generic(self.layout, is_editmode=False); + self.draw_generic(self.layout, is_editmode=False) class VIEW3D_MT_sculpt(Menu): @@ -2010,10 +2019,6 @@ class VIEW3D_MT_sculpt(Menu): toolsettings = context.tool_settings sculpt = toolsettings.sculpt - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - layout.prop(sculpt, "use_symmetry_x") layout.prop(sculpt, "use_symmetry_y") layout.prop(sculpt, "use_symmetry_z") @@ -2081,14 +2086,6 @@ class VIEW3D_MT_particle(Menu): particle_edit = context.tool_settings.particle_edit - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - - layout.operator("particle.delete") - - layout.separator() - layout.operator("particle.mirror") layout.operator("particle.remove_doubles") @@ -2106,9 +2103,13 @@ class VIEW3D_MT_particle(Menu): layout.menu("VIEW3D_MT_particle_showhide") + layout.separator() + + layout.operator("particle.delete") + class VIEW3D_MT_particle_specials(Menu): - bl_label = "Specials" + bl_label = "Context Menu" def draw(self, context): layout = self.layout @@ -2166,10 +2167,6 @@ class VIEW3D_MT_pose(Menu): def draw(self, context): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - layout.menu("VIEW3D_MT_transform_armature") layout.menu("VIEW3D_MT_pose_transform") @@ -2362,30 +2359,41 @@ class VIEW3D_MT_pose_apply(Menu): class VIEW3D_MT_pose_specials(Menu): - bl_label = "Specials" + bl_label = "Context Menu" def draw(self, context): layout = self.layout - layout.operator("paint.weight_from_bones", text="Assign Automatic from Bones").type = 'AUTOMATIC' - layout.operator("paint.weight_from_bones", text="Assign from Bone Envelopes").type = 'ENVELOPES' + layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...") + + layout.separator() + + layout.operator("pose.copy") + layout.operator("pose.paste").flipped = False + layout.operator("pose.paste", text="Paste X-Flipped Pose").flipped = True layout.separator() layout.operator("pose.select_constraint_target") - layout.operator("pose.flip_names") + + layout.separator() + + layout.operator("pose.paths_calculate", text="Calculate") + layout.operator("pose.paths_clear", text="Clear") layout.separator() layout.operator("pose.paths_calculate") layout.operator("pose.paths_clear") - layout.operator("pose.user_transforms_clear") - layout.operator("pose.user_transforms_clear", text="Clear User Transforms (All)").only_selected = False - layout.operator("pose.relax") layout.separator() - layout.operator_menu_enum("pose.autoside_names", "axis") + layout.operator("pose.hide").unselected = False + layout.operator("pose.reveal") + + layout.separator() + + layout.operator("pose.user_transforms_clear") class BoneOptions: @@ -2442,16 +2450,9 @@ class VIEW3D_MT_edit_mesh(Menu): def draw(self, context): layout = self.layout + with_bullet = bpy.app.build_options.bullet toolsettings = context.tool_settings - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - - layout.menu("VIEW3D_MT_edit_mesh_delete") - - layout.separator() - layout.menu("VIEW3D_MT_transform") layout.menu("VIEW3D_MT_mirror") layout.menu("VIEW3D_MT_snap") @@ -2462,80 +2463,124 @@ class VIEW3D_MT_edit_mesh(Menu): layout.separator() - layout.operator("mesh.duplicate_move") + layout.operator("mesh.duplicate_move", text="Duplicate") layout.menu("VIEW3D_MT_edit_mesh_extrude") - layout.separator() + layout.operator("mesh.split") + layout.operator("mesh.bisect") - layout.menu("VIEW3D_MT_edit_mesh_normals") - layout.menu("VIEW3D_MT_edit_mesh_shading") - layout.menu("VIEW3D_MT_edit_mesh_weights") - layout.menu("VIEW3D_MT_edit_mesh_clean") + if with_bullet: + layout.operator("mesh.convex_hull") layout.separator() layout.operator("mesh.symmetrize") layout.operator("mesh.symmetry_snap") - layout.operator("mesh.bisect") - layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...") layout.separator() - layout.prop(toolsettings, "use_mesh_automerge") - layout.menu("VIEW3D_MT_edit_proportional") + layout.menu("VIEW3D_MT_edit_mesh_normals") + layout.menu("VIEW3D_MT_edit_mesh_shading") + layout.menu("VIEW3D_MT_edit_mesh_weights") + layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...") layout.separator() layout.menu("VIEW3D_MT_edit_mesh_showhide") + layout.operator_menu_enum("mesh.separate", "type") + layout.menu("VIEW3D_MT_edit_mesh_clean") + layout.menu("VIEW3D_MT_edit_mesh_delete") class VIEW3D_MT_edit_mesh_specials(Menu): - bl_label = "Specials" + bl_label = "Context Menu" def draw(self, context): layout = self.layout + select_mode = context.tool_settings.mesh_select_mode + layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("mesh.subdivide", text="Subdivide").smoothness = 0.0 - layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0 + layout.operator("mesh.subdivide", text="Subdivide") layout.separator() - layout.operator("mesh.merge", text="Merge...") - layout.operator("mesh.remove_doubles") + layout.operator("mesh.duplicate_move", text="Duplicate") - layout.separator() + # Vertex Select Commands + if select_mode[0]: + layout.separator() - layout.operator("mesh.hide", text="Hide").unselected = False - layout.operator("mesh.reveal", text="Reveal") - layout.operator("mesh.select_all", text="Select Inverse").action = 'INVERT' + layout.operator("mesh.edge_face_add", text="New Edge/Face from Vertices") + layout.operator("mesh.vert_connect_path", text="Connect Vertex Path") + layout.operator("mesh.vert_connect", text="Connect Vertex Pairs") - layout.separator() + layout.separator() - layout.operator("mesh.flip_normals") - layout.operator("mesh.vertices_smooth", text="Smooth") - layout.operator("mesh.vertices_smooth_laplacian", text="Laplacian Smooth") + layout.operator("mesh.vertices_smooth", text="Smooth") + layout.operator("mesh.vertices_smooth_laplacian", text="Smooth Laplacian") - layout.separator() + layout.separator() + layout.operator("mesh.merge", text="Merge Vertices...") + layout.operator("mesh.remove_doubles", text="Remove Double Vertices") + layout.operator("mesh.dissolve_verts") + layout.operator("mesh.delete", text="Delete Vertices").type = "VERT" - layout.operator("mesh.inset") - layout.operator("mesh.bevel", text="Bevel") - layout.operator("mesh.bridge_edge_loops") + # Edge Select Commands + if select_mode[1]: + layout.separator() - layout.separator() + layout.operator("mesh.bridge_edge_loops", text="Bridge Edge Loops") - layout.operator("mesh.faces_shade_smooth") - layout.operator("mesh.faces_shade_flat") + layout.separator() + + layout.operator("mesh.dissolve_edges") + layout.operator("mesh.delete", text="Delete Edges").type = "EDGE" + + # Face Select Commands + if select_mode[2]: + layout.separator() + + layout.operator("mesh.faces_shade_smooth") + layout.operator("mesh.faces_shade_flat") + + layout.separator() + + layout.operator("mesh.bridge_edge_loops", text="Bridge Faces") + + layout.separator() + + layout.operator("mesh.poke") + + layout.separator() + + props = layout.operator("mesh.quads_convert_to_tris") + props.quad_method = props.ngon_method = 'BEAUTY' + layout.operator("mesh.tris_convert_to_quads") + + layout.separator() + + layout.menu("VIEW3D_MT_uv_map", text="UV Unwrap Faces...") + + layout.separator() + + layout.operator("mesh.dissolve_faces") + layout.operator("mesh.delete", text="Delete Faces").type = "FACE" + + # General Mesh Commands layout.separator() - layout.operator("mesh.blend_from_shape") - layout.operator("mesh.shape_propagate_to_all") - layout.operator("mesh.shortest_path_select") - layout.operator("mesh.sort_elements") + layout.menu("VIEW3D_MT_snap", text="Snap...") + layout.operator("transform.mirror", text="Mirror") layout.operator("mesh.symmetrize") layout.operator("mesh.symmetry_snap") + layout.separator() + + layout.operator("mesh.hide", text="Hide").unselected = False + layout.operator("mesh.reveal", text="Reveal") + class VIEW3D_MT_edit_mesh_select_mode(Menu): bl_label = "Mesh Select Mode" @@ -2554,15 +2599,15 @@ class VIEW3D_MT_edit_mesh_extrude(Menu): _extrude_funcs = { 'VERT': lambda layout: - layout.operator("mesh.extrude_vertices_move", text="Vertices Only"), + layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices"), 'EDGE': lambda layout: - layout.operator("mesh.extrude_edges_move", text="Edges Only"), - 'FACE': lambda layout: - layout.operator("mesh.extrude_faces_move", text="Individual Faces"), + layout.operator("mesh.extrude_edges_move", text="Extrude Edges"), 'REGION': lambda layout: - layout.operator("view3d.edit_mesh_extrude_move_normal", text="Region"), + layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces"), 'REGION_VERT_NORMAL': lambda layout: - layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Region (Vertex Normals)"), + layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"), + 'FACE': lambda layout: + layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"), } @staticmethod @@ -2596,39 +2641,37 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - with_bullet = bpy.app.build_options.bullet + layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices"), + layout.operator("mesh.bevel", text="Bevel Vertices").vertex_only = True - layout.operator("mesh.merge") - layout.operator("mesh.remove_doubles") - props = layout.operator("mesh.rip_move") - props.MESH_OT_rip.use_fill = False - props = layout.operator("mesh.rip_move", text="Rip Fill") - props.MESH_OT_rip.use_fill = True - layout.operator("mesh.rip_edge_move") - layout.operator("mesh.split") - layout.operator_menu_enum("mesh.separate", "type") + layout.separator() + + layout.operator("mesh.edge_face_add", text="New Edge/Face from Vertices") layout.operator("mesh.vert_connect_path", text="Connect Vertex Path") - layout.operator("mesh.vert_connect", text="Connect Vertices") - layout.operator("transform.vert_slide", text="Slide") + layout.operator("mesh.vert_connect", text="Connect Vertex Pairs") layout.separator() - layout.operator("mesh.mark_sharp", text="Mark Sharp Edges").use_verts = True - props = layout.operator("mesh.mark_sharp", text="Clear Sharp Edges") - props.use_verts = True - props.clear = True + props = layout.operator("mesh.rip_move", text="Rip Vertices") + props.MESH_OT_rip.use_fill = False + props = layout.operator("mesh.rip_move", text="Rip Vertices and Fill") + props.MESH_OT_rip.use_fill = True + layout.operator("mesh.rip_edge_move", text="Rip Vertices and Extend") layout.separator() - layout.operator("mesh.bevel").vertex_only = True - if with_bullet: - layout.operator("mesh.convex_hull") - layout.operator("mesh.vertices_smooth") + layout.operator("transform.vert_slide", text="Slide Vertices") + layout.operator("mesh.vertices_smooth", text="Smooth Vertices") + + layout.separator() layout.operator("mesh.blend_from_shape") + layout.operator("mesh.shape_propagate_to_all", text="Propagate to Shapes") + + layout.separator() - layout.operator("object.vertex_group_smooth") - layout.operator("mesh.shape_propagate_to_all") + layout.operator("mesh.merge", text="Merge Vertices") + layout.operator("mesh.remove_doubles", text="Remove Double Vertices") layout.separator() @@ -2663,6 +2706,13 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu): layout.operator("mesh.mark_sharp") layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True + layout.operator("mesh.mark_sharp", text="Mark Sharp from Vertices").use_verts = True + props = layout.operator("mesh.mark_sharp", text="Clear Sharp from Vertices") + props.use_verts = True + props.clear = True + + layout.separator() + layout.separator() if with_freestyle: @@ -2679,14 +2729,15 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("mesh.edge_face_add") - layout.operator("mesh.subdivide") - layout.operator("mesh.subdivide_edgering") - layout.operator("mesh.unsubdivide") + layout.operator("mesh.extrude_edges_move", text="Extrude Edges"), + layout.operator("mesh.bevel", text="Bevel Edges").vertex_only = False + layout.operator("mesh.bridge_edge_loops") layout.separator() - layout.menu("VIEW3D_MT_edit_mesh_edges_data") + layout.operator("mesh.subdivide") + layout.operator("mesh.subdivide_edgering") + layout.operator("mesh.unsubdivide") layout.separator() @@ -2695,22 +2746,16 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.separator() - layout.operator("mesh.bevel").vertex_only = False + layout.operator("transform.edge_slide") layout.operator("mesh.edge_split") - layout.operator("mesh.bridge_edge_loops") layout.separator() - layout.operator("transform.edge_slide") - layout.operator("mesh.loop_multi_select", text="Edge Loops").ring = False - layout.operator("mesh.loop_multi_select", text="Edge Rings").ring = True - layout.operator("mesh.loop_to_region") - layout.operator("mesh.region_to_loop") + layout.menu("VIEW3D_MT_edit_mesh_edges_data") -class VIEW3D_MT_edit_mesh_faces(Menu): - bl_label = "Face" - bl_idname = "VIEW3D_MT_edit_mesh_faces" +class VIEW3D_MT_edit_mesh_faces_data(Menu): + bl_label = "Face Data" def draw(self, context): layout = self.layout @@ -2719,48 +2764,69 @@ class VIEW3D_MT_edit_mesh_faces(Menu): layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("mesh.flip_normals") - layout.operator("mesh.edge_face_add") - layout.operator("mesh.fill") - layout.operator("mesh.fill_grid") - layout.operator("mesh.beautify_fill") - layout.operator("mesh.inset") - layout.operator("mesh.bevel").vertex_only = False - layout.operator("mesh.solidify") - layout.operator("mesh.intersect") - layout.operator("mesh.intersect_boolean") - layout.operator("mesh.wireframe") + layout.operator("mesh.colors_rotate") + layout.operator("mesh.colors_reverse") + + layout.separator() + + layout.operator("mesh.uvs_rotate") + layout.operator("mesh.uvs_reverse") layout.separator() if with_freestyle: layout.operator("mesh.mark_freestyle_face").clear = False layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True - layout.separator() + +class VIEW3D_MT_edit_mesh_faces(Menu): + bl_label = "Face" + bl_idname = "VIEW3D_MT_edit_mesh_faces" + + def draw(self, context): + layout = self.layout + + with_freestyle = bpy.app.build_options.freestyle + + layout.operator_context = 'INVOKE_REGION_WIN' + + layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces"), + layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"), + layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"), + + layout.separator() + + layout.operator("mesh.inset") layout.operator("mesh.poke") props = layout.operator("mesh.quads_convert_to_tris") props.quad_method = props.ngon_method = 'BEAUTY' layout.operator("mesh.tris_convert_to_quads") - layout.operator("mesh.face_split_by_edges") + layout.operator("mesh.solidify", text="Solidify Faces") + layout.operator("mesh.wireframe") layout.separator() - layout.operator("mesh.faces_shade_smooth") - layout.operator("mesh.faces_shade_flat") + layout.operator("mesh.fill") + layout.operator("mesh.fill_grid") + layout.operator("mesh.beautify_fill") - layout.operator("mesh.normals_make_consistent", text="Recalculate Normals").inside = False + layout.separator() + + layout.operator("mesh.intersect") + layout.operator("mesh.intersect_boolean") layout.separator() - layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False + layout.operator("mesh.face_split_by_edges") layout.separator() - layout.operator("mesh.uvs_rotate") - layout.operator("mesh.uvs_reverse") - layout.operator("mesh.colors_rotate") - layout.operator("mesh.colors_reverse") + layout.operator("mesh.faces_shade_smooth") + layout.operator("mesh.faces_shade_flat") + + layout.separator() + + layout.menu("VIEW3D_MT_edit_mesh_faces_data") class VIEW3D_MT_edit_mesh_normals(Menu): @@ -2903,14 +2969,6 @@ class VIEW3D_MT_edit_gpencil_delete(Menu): def draw_curve(self, context): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - - layout.menu("VIEW3D_MT_edit_curve_delete") - - layout.separator() - layout.menu("VIEW3D_MT_transform") layout.menu("VIEW3D_MT_mirror") layout.menu("VIEW3D_MT_snap") @@ -2935,15 +2993,9 @@ def draw_curve(self, context): layout.separator() - layout.menu("VIEW3D_MT_edit_curve_clean") - - layout.separator() - - layout.menu("VIEW3D_MT_edit_proportional") - - layout.separator() - layout.menu("VIEW3D_MT_edit_curve_showhide") + layout.menu("VIEW3D_MT_edit_curve_clean") + layout.menu("VIEW3D_MT_edit_curve_delete") class VIEW3D_MT_edit_curve(Menu): @@ -2987,6 +3039,7 @@ class VIEW3D_MT_edit_curve_segments(Menu): layout.operator("curve.subdivide") layout.operator("curve.switch_direction") + class VIEW3D_MT_edit_curve_clean(Menu): bl_label = "Clean Up" @@ -2997,7 +3050,7 @@ class VIEW3D_MT_edit_curve_clean(Menu): class VIEW3D_MT_edit_curve_specials(Menu): - bl_label = "Specials" + bl_label = "Context Menu" def draw(self, context): layout = self.layout @@ -3044,9 +3097,6 @@ class VIEW3D_MT_edit_font(Menu): def draw(self, context): layout = self.layout - # Break convention of having undo menu here, - # instead place in "Edit" menu, matching the text menu. - layout.menu("VIEW3D_MT_edit_text_chars") layout.separator() @@ -3106,14 +3156,6 @@ class VIEW3D_MT_edit_meta(Menu): def draw(self, context): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - - layout.operator("mball.delete_metaelems", text="Delete...") - - layout.separator() - layout.menu("VIEW3D_MT_transform") layout.menu("VIEW3D_MT_mirror") layout.menu("VIEW3D_MT_snap") @@ -3124,11 +3166,8 @@ class VIEW3D_MT_edit_meta(Menu): layout.separator() - layout.menu("VIEW3D_MT_edit_proportional") - - layout.separator() - layout.menu("VIEW3D_MT_edit_meta_showhide") + layout.operator("mball.delete_metaelems", text="Delete...") class VIEW3D_MT_edit_meta_showhide(Menu): @@ -3148,8 +3187,6 @@ class VIEW3D_MT_edit_lattice(Menu): def draw(self, context): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - layout.separator() layout.menu("VIEW3D_MT_transform") @@ -3165,10 +3202,6 @@ class VIEW3D_MT_edit_lattice(Menu): layout.operator("object.vertex_parent_set") - layout.separator() - - layout.menu("VIEW3D_MT_edit_proportional") - class VIEW3D_MT_edit_armature(Menu): bl_label = "Armature" @@ -3179,14 +3212,6 @@ class VIEW3D_MT_edit_armature(Menu): edit_object = context.edit_object arm = edit_object.data - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - - layout.operator("armature.delete") - - layout.separator() - layout.menu("VIEW3D_MT_transform_armature") layout.menu("VIEW3D_MT_mirror") layout.menu("VIEW3D_MT_snap") @@ -3233,9 +3258,13 @@ class VIEW3D_MT_edit_armature(Menu): layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings") + layout.separator() + + layout.operator("armature.delete") + class VIEW3D_MT_armature_specials(Menu): - bl_label = "Specials" + bl_label = "Context Menu" def draw(self, context): layout = self.layout @@ -3303,14 +3332,6 @@ class VIEW3D_MT_edit_gpencil(Menu): layout = self.layout - layout.menu("VIEW3D_MT_undo_redo") - - layout.separator() - - layout.menu("VIEW3D_MT_edit_gpencil_delete") - - layout.separator() - layout.menu("VIEW3D_MT_edit_gpencil_transform") layout.operator("transform.mirror", text="Mirror") layout.menu("GPENCIL_MT_snap") @@ -3342,10 +3363,6 @@ class VIEW3D_MT_edit_gpencil(Menu): layout.separator() - layout.menu("VIEW3D_MT_edit_proportional") - - layout.separator() - layout.operator("gpencil.reveal") layout.operator("gpencil.hide", text="Show Active Layer Only").unselected = True layout.operator("gpencil.hide", text="Hide Active Layer").unselected = False @@ -3360,6 +3377,10 @@ class VIEW3D_MT_edit_gpencil(Menu): layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...") + layout.separator() + + layout.menu("VIEW3D_MT_edit_gpencil_delete") + class VIEW3D_MT_edit_gpencil_transform(Menu): bl_label = "Transform" @@ -3533,22 +3554,26 @@ class VIEW3D_PT_shading(Panel): col.separator() row = col.row() - row.prop(shading, "show_see_through") + row.prop(shading, "show_xray") row = col.row() - row.active = not shading.show_see_through + row.active = not shading.show_xray row.prop(shading, "show_shadows") sub = row.row() - sub.active = shading.show_shadows and not shading.show_see_through + sub.active = shading.show_shadows and not shading.show_xray sub.prop(shading, "shadow_intensity", text="") - row = col.row() row.prop(shading, "show_object_outline") sub = row.row() sub.active = shading.show_object_outline sub.prop(shading, "object_outline_color", text="") + elif shading.type in ('MATERIAL'): + col.row().template_icon_view(shading, "studio_light") + if shading.studio_light_orientation == 'WORLD': + col.row().prop(shading, "studiolight_rot_z") + class VIEW3D_PT_overlay(Panel): bl_space_type = 'VIEW_3D' @@ -3605,8 +3630,6 @@ class VIEW3D_PT_overlay(Panel): subsub.active = scene.unit_settings.system == 'NONE' subsub.prop(overlay, "grid_subdivisions", text="Subdivisions") - - if context.mode == 'EDIT_MESH': col.separator() col.label(text="Edit Mode:") @@ -3634,7 +3657,7 @@ class VIEW3D_PT_overlay(Panel): col = layout.column() col.active = display_all - col.prop(overlay, "transparent_bones") + col.prop(overlay, "show_transparent_bones") col.prop(overlay, "show_bone_selection") elif context.mode == 'EDIT_ARMATURE': @@ -3643,7 +3666,7 @@ class VIEW3D_PT_overlay(Panel): col = layout.column() col.active = display_all - col.prop(overlay, "transparent_bones") + col.prop(overlay, "show_transparent_bones") elif context.mode in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}: col.separator() @@ -3988,8 +4011,6 @@ classes = ( INFO_MT_lightprobe_add, INFO_MT_camera_add, INFO_MT_add, - VIEW3D_MT_undo_redo, - VIEW3D_MT_object_relations, VIEW3D_MT_object, VIEW3D_MT_object_animation, VIEW3D_MT_object_rigid_body, @@ -3997,6 +4018,7 @@ classes = ( VIEW3D_MT_object_specials, VIEW3D_MT_object_shading, VIEW3D_MT_object_apply, + VIEW3D_MT_object_relations, VIEW3D_MT_object_parent, VIEW3D_MT_object_track, VIEW3D_MT_object_collection, @@ -4039,6 +4061,7 @@ classes = ( VIEW3D_MT_edit_mesh_edges, VIEW3D_MT_edit_mesh_edges_data, VIEW3D_MT_edit_mesh_faces, + VIEW3D_MT_edit_mesh_faces_data, VIEW3D_MT_edit_mesh_normals, VIEW3D_MT_edit_mesh_shading, VIEW3D_MT_edit_mesh_weights, diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 9a1bff86ed3..1b1e0f73dd1 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -182,6 +182,7 @@ class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel): arm = context.active_object.data self.layout.prop(arm, "use_auto_ik") + self.layout.prop(arm, "use_mirror_x") # ********** default tools for paint modes **************** @@ -569,7 +570,7 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): else: slot = None - if slot and slot.valid: + if slot and slot.is_valid: col.label("UV Map:") col.prop_search(slot, "uv_layer", ob.data, "uv_layers", text="") diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 591180f08b4..d60710db4aa 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -229,6 +229,7 @@ shader_node_categories = [ NodeItem("ShaderNodeTexChecker"), NodeItem("ShaderNodeTexBrick"), NodeItem("ShaderNodeTexPointDensity"), + NodeItem("ShaderNodeTexIES"), ]), ShaderNodeCategory("SH_NEW_OP_COLOR", "Color", items=[ NodeItem("ShaderNodeMixRGB"), diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index c647dd3cc0f..eb05e66cf06 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -129,9 +129,9 @@ bool BKE_camera_view_frame_fit_to_scene( struct Scene *scene, struct ViewLayer *view_layer, struct Object *camera_ob, float r_co[3], float *r_scale); bool BKE_camera_view_frame_fit_to_coords( - const struct Scene *scene, + const struct Depsgraph *depsgraph, const float (*cos)[3], int num_cos, - const struct Object *camera_ob, + struct Object *camera_ob, float r_co[3], float *r_scale); void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings); @@ -139,11 +139,11 @@ void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_set /* Camera multi-view API */ struct Object *BKE_camera_multiview_render(struct Scene *scene, struct Object *camera, const char *viewname); -void BKE_camera_multiview_view_matrix(struct RenderData *rd, struct Object *camera, const bool is_left, float r_viewmat[4][4]); -void BKE_camera_multiview_model_matrix(struct RenderData *rd, struct Object *camera, const char *viewname, float r_modelmat[4][4]); -float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object *camera, const char *viewname); -void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname); -bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, struct Object *camera); +void BKE_camera_multiview_view_matrix(struct RenderData *rd, const struct Object *camera, const bool is_left, float r_viewmat[4][4]); +void BKE_camera_multiview_model_matrix(struct RenderData *rd, const struct Object *camera, const char *viewname, float r_modelmat[4][4]); +float BKE_camera_multiview_shift_x(struct RenderData *rd, const struct Object *camera, const char *viewname); +void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, const struct Object *camera, const char *viewname); +bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, const struct Object *camera); /* Camera background image API */ struct CameraBGImage *BKE_camera_background_image_new(struct Camera *cam); diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 18f6301953c..98ba0f6f2a4 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -49,6 +49,7 @@ extern "C" { /* special struct for use in constraint evaluation */ typedef struct bConstraintOb { + struct Depsgraph *depsgraph;/* to get evaluated armature. */ struct Scene *scene; /* for system time, part of deglobalization, code nicer later with local time (ton) */ struct Object *ob; /* if pchan, then armature that it comes from, otherwise constraint owner */ struct bPoseChannel *pchan; /* pose channel that owns the constraints being evaluated */ @@ -144,7 +145,7 @@ void BKE_constraints_proxylocal_extract(struct ListBase *dst, struct ListBase *s bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *pchan); /* Constraint Evaluation function prototypes */ -struct bConstraintOb *BKE_constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype); +struct bConstraintOb *BKE_constraints_make_evalob(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, void *subdata, short datatype); void BKE_constraints_clear_evalob(struct bConstraintOb *cob); void BKE_constraint_mat_convertspace( diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index e54531bdb0e..22897d2ea80 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -160,7 +160,7 @@ struct ImBuf *BKE_icon_geom_rasterize( const struct Icon_Geom *geom, const unsigned int size_x, const unsigned int size_y); -int BKE_icon_ensure_studio_light(struct StudioLight *sl); +int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type); #define ICON_RENDER_DEFAULT_HEIGHT 32 diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 626a1cd09e3..60204d177f2 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -80,7 +80,7 @@ void BKE_view_layer_copy_data( struct ViewLayer *view_layer_dst, const struct ViewLayer *view_layer_src, const int flag); -void BKE_view_layer_rename(struct Scene *scene, struct ViewLayer *view_layer, const char *name); +void BKE_view_layer_rename(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, const char *name); struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer); bool BKE_layer_collection_activate(struct ViewLayer *view_layer, struct LayerCollection *lc); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index ab00b8174b5..c8d50793e76 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -557,7 +557,9 @@ struct DerivedMesh *modifier_applyModifierEM_DM_deprecated( struct ModifierData *md, const struct ModifierEvalContext *ctx, struct BMEditMesh *editData, struct DerivedMesh *dm); -struct Mesh *BKE_modifier_get_evaluated_mesh_from_object(struct Object *ob, const ModifierApplyFlag flag); +struct Mesh *BKE_modifier_get_evaluated_mesh_from_object( + const struct ModifierEvalContext *ctx, + struct Object *ob); #endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index f3cbcd7b99f..c654dd51e2a 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -796,6 +796,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, c #define SH_NODE_UVALONGSTROKE 191 #define SH_NODE_TEX_POINTDENSITY 192 #define SH_NODE_BSDF_PRINCIPLED 193 +#define SH_NODE_TEX_IES 194 #define SH_NODE_EEVEE_SPECULAR 195 #define SH_NODE_BEVEL 197 #define SH_NODE_DISPLACEMENT 198 diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 7dbdac1b835..db6c7aa9c4f 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -45,6 +45,7 @@ struct View3D; struct SoftBody; struct MovieClip; struct Main; +struct Mesh; struct RigidBodyWorld; struct HookModifierData; struct ModifierData; @@ -269,6 +270,8 @@ void BKE_object_sculpt_modifiers_changed(struct Object *ob); int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot); +struct Mesh *BKE_object_get_evaluated_mesh(const struct Depsgraph *depsgraph, struct Object *ob); + int BKE_object_insert_ptcache(struct Object *ob); void BKE_object_delete_ptcache(struct Object *ob, int index); struct KeyBlock *BKE_object_shapekey_insert(struct Object *ob, const char *name, const bool from_mix); diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h index b82bc692402..8a14f8fb041 100644 --- a/source/blender/blenkernel/BKE_outliner_treehash.h +++ b/source/blender/blenkernel/BKE_outliner_treehash.h @@ -36,6 +36,9 @@ void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore) /* full rebuild for already allocated hashtable */ void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore); +/* clear element usage flags */ +void BKE_outliner_treehash_clear_used(void *treehash); + /* Add/remove hashtable elements */ void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem); void BKE_outliner_treehash_remove_element(void *treehash, struct TreeStoreElem *elem); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index b6a87ae333e..4820f0173bf 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -439,8 +439,8 @@ void psys_particle_on_dm(struct Mesh *mesh_final, int from, int index, int index /* particle_system.c */ void distribute_particles(struct ParticleSimulationData *sim, int from); void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa); -void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_deformed, struct ParticleSystem *psys); -int psys_particle_dm_face_lookup(struct Mesh *mesh_final, struct Mesh *mesh_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes); +void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_original, struct ParticleSystem *psys); +int psys_particle_dm_face_lookup(struct Mesh *mesh_final, struct Mesh *mesh_original, int findex, const float fw[4], struct LinkNode **poly_nodes); void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index 2fcf6ab2f19..213de712abd 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -51,6 +51,10 @@ #define STUDIOLIGHT_Y_NEG 3 #define STUDIOLIGHT_Z_POS 4 #define STUDIOLIGHT_Z_NEG 5 +#define STUDIOLIGHT_ICON_ID_TYPE_RADIANCE 0 +#define STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE 1 + +struct GPUTexture; enum StudioLightFlag { STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED = (1 << 0), @@ -58,7 +62,9 @@ enum StudioLightFlag { STUDIOLIGHT_EXTERNAL_FILE = (1 << 2), STUDIOLIGHT_ORIENTATION_CAMERA = (1 << 3), STUDIOLIGHT_ORIENTATION_WORLD = (1 << 4), - STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 5), + STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED = (1 << 5), + STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE = (1 << 6), + STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 7), } StudioLightFlag; typedef struct StudioLight { @@ -66,18 +72,21 @@ typedef struct StudioLight { int flag; char name[FILE_MAXFILE]; char path[FILE_MAX]; - int icon_id; + int irradiance_icon_id; + int radiance_icon_id; int index; float diffuse_light[6][3]; float light_direction[3]; + ImBuf *equirectangular_buffer; ImBuf *radiance_buffers[6]; + struct GPUTexture *equirectangular_gputexture; } StudioLight; void BKE_studiolight_init(void); void BKE_studiolight_free(void); -struct StudioLight *BKE_studiolight_find(const char *name); +struct StudioLight *BKE_studiolight_find(const char *name, int flag); struct StudioLight *BKE_studiolight_findindex(int index); -unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size); +unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size, int icon_id_type); const struct ListBase *BKE_studiolight_listbase(void); void BKE_studiolight_ensure_flag(StudioLight *sl, int flag); diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h index 5ee15a08f9b..5442fd43ce5 100644 --- a/source/blender/blenkernel/BKE_workspace.h +++ b/source/blender/blenkernel/BKE_workspace.h @@ -53,12 +53,20 @@ void BKE_workspace_layout_remove( void BKE_workspace_relations_free( ListBase *relation_list); +void BKE_workspace_scene_relations_free_invalid( + struct WorkSpace *workspace); /* -------------------------------------------------------------------- */ /* General Utils */ -void BKE_workspace_view_layer_remove_references( +void BKE_workspace_view_layer_rename( + const struct Main *bmain, + const struct Scene *scene, + const char *old_name, + const char *new_name) ATTR_NONNULL(); + +void BKE_workspace_view_layer_remove( const struct Main *bmain, const struct ViewLayer *view_layer) ATTR_NONNULL(); @@ -92,6 +100,9 @@ struct Base *BKE_workspace_active_base_get(const struct WorkSpace *workspace, co struct ViewLayer *BKE_workspace_view_layer_get( const struct WorkSpace *workspace, const struct Scene *scene) GETTER_ATTRS; +struct ViewLayer *BKE_workspace_view_layer_exists( + const struct WorkSpace *workspace, + const struct Scene *scene) GETTER_ATTRS; void BKE_workspace_view_layer_set( struct WorkSpace *workspace, struct ViewLayer *layer, diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f80096b39eb..8dbfc35c774 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2239,7 +2239,7 @@ void BKE_pose_where_is_bone( /* prepare PoseChannel for Constraint solving * - makes a copy of matrix, and creates temporary struct to use */ - cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); + cob = BKE_constraints_make_evalob(depsgraph, scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); /* Solve PoseChannel's Constraints */ BKE_constraints_solve(depsgraph, &pchan->constraints, cob, ctime); /* ctime doesnt alter objects */ diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 259c5189896..dbaf3f2ee9e 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -560,6 +560,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int NodeShaderScript *nss = (NodeShaderScript *)node->storage; rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); } + else if (node->type == SH_NODE_TEX_IES) { + NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage; + rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data); + } } } break; @@ -576,6 +580,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int NodeShaderScript *nss = (NodeShaderScript *)node->storage; rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); } + else if (node->type == SH_NODE_TEX_IES) { + NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage; + rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data); + } } } break; diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index a18fd9ead87..b1b4f18a6d5 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -268,7 +268,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, Depsgraph *depsgraph, c if (rv3d->persp == RV3D_CAMOB) { /* camera view */ - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + const Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); BKE_camera_params_from_object(params, ob_camera_eval); params->zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); @@ -666,16 +666,18 @@ bool BKE_camera_view_frame_fit_to_scene( } bool BKE_camera_view_frame_fit_to_coords( - const Scene *scene, const float (*cos)[3], int num_cos, const Object *camera_ob, + const Depsgraph *depsgraph, const float (*cos)[3], int num_cos, Object *camera_ob, float r_co[3], float *r_scale) { + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); CameraParams params; CameraViewFrameData data_cb; /* just in case */ *r_scale = 1.0f; - camera_frame_fit_data_init(scene, camera_ob, ¶ms, &data_cb); + camera_frame_fit_data_init(scene_eval, camera_ob_eval, ¶ms, &data_cb); /* run callback on all given coordinates */ while (num_cos--) { @@ -687,12 +689,12 @@ bool BKE_camera_view_frame_fit_to_coords( /******************* multiview matrix functions ***********************/ -static void camera_model_matrix(Object *camera, float r_modelmat[4][4]) +static void camera_model_matrix(const Object *camera, float r_modelmat[4][4]) { copy_m4_m4(r_modelmat, camera->obmat); } -static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4]) +static void camera_stereo3d_model_matrix(const Object *camera, const bool is_left, float r_modelmat[4][4]) { Camera *data = (Camera *)camera->data; float interocular_distance, convergence_distance; @@ -790,7 +792,7 @@ static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, flo } /* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */ -void BKE_camera_multiview_view_matrix(RenderData *rd, Object *camera, const bool is_left, float r_viewmat[4][4]) +void BKE_camera_multiview_view_matrix(RenderData *rd, const Object *camera, const bool is_left, float r_viewmat[4][4]) { BKE_camera_multiview_model_matrix(rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat); invert_m4(r_viewmat); @@ -805,7 +807,7 @@ static bool camera_is_left(const char *viewname) return true; } -void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4]) +void BKE_camera_multiview_model_matrix(RenderData *rd, const Object *camera, const char *viewname, float r_modelmat[4][4]) { const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; @@ -822,7 +824,7 @@ void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const cha normalize_m4(r_modelmat); } -bool BKE_camera_multiview_spherical_stereo(RenderData *rd, Object *camera) +bool BKE_camera_multiview_spherical_stereo(RenderData *rd, const Object *camera) { Camera *cam; const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; @@ -895,7 +897,7 @@ Object *BKE_camera_multiview_render(Scene *scene, Object *camera, const char *vi } } -static float camera_stereo3d_shift_x(Object *camera, const char *viewname) +static float camera_stereo3d_shift_x(const Object *camera, const char *viewname) { Camera *data = camera->data; float shift = data->shiftx; @@ -933,7 +935,7 @@ static float camera_stereo3d_shift_x(Object *camera, const char *viewname) return shift; } -float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *viewname) +float BKE_camera_multiview_shift_x(RenderData *rd, const Object *camera, const char *viewname) { const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; Camera *data = camera->data; @@ -951,7 +953,7 @@ float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *v } } -void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, Object *camera, const char *viewname) +void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, const Object *camera, const char *viewname) { if (camera->type == OB_CAMERA) { params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname); @@ -977,6 +979,7 @@ CameraBGImage *BKE_camera_background_image_new(Camera *cam) bgpic->alpha = 0.5f; bgpic->iuser.fie_ima = 2; bgpic->iuser.ok = 1; + bgpic->iuser.flag |= IMA_ANIM_ALWAYS; bgpic->flag |= CAM_BGIMG_FLAG_EXPANDED; BLI_addtail(&cam->bg_images, bgpic); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 30ed796d73f..c4709a32f78 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -614,7 +614,7 @@ bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *o return false; } - if (collection_object_remove(bmain, collection, ob, free_us)) { + if (!collection_object_remove(bmain, collection, ob, free_us)) { return false; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 6a477c9c06e..28c6fe852c2 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -84,6 +84,9 @@ #include "BIK_api.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #ifdef WITH_PYTHON # include "BPY_extern.h" #endif @@ -116,7 +119,7 @@ void BKE_constraint_unique_name(bConstraint *con, ListBase *list) /* package an object/bone for use in constraint evaluation */ /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */ -bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype) +bConstraintOb *BKE_constraints_make_evalob(Depsgraph *depsgraph, Scene *scene, Object *ob, void *subdata, short datatype) { bConstraintOb *cob; @@ -125,6 +128,7 @@ bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subda /* for system time, part of deglobalization, code nicer later with local time (ton) */ cob->scene = scene; + cob->depsgraph = depsgraph; /* based on type of available data */ switch (datatype) { @@ -3903,20 +3907,25 @@ static void followtrack_id_looper(bConstraint *con, ConstraintIDFunc func, void static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { + Depsgraph *depsgraph = cob->depsgraph; Scene *scene = cob->scene; bFollowTrackConstraint *data = con->data; MovieClip *clip = data->clip; MovieTracking *tracking; MovieTrackingTrack *track; MovieTrackingObject *tracking_object; - Object *camob = data->camera ? data->camera : scene->camera; - float ctime = BKE_scene_frame_get(scene); + + Object *camob_eval = DEG_get_evaluated_object( + depsgraph, + data->camera ? data->camera : scene->camera); + + float ctime = DEG_get_ctime(depsgraph);; float framenr; if (data->flag & FOLLOWTRACK_ACTIVECLIP) clip = scene->clip; - if (!clip || !data->track[0] || !camob) + if (!clip || !data->track[0] || !camob_eval) return; tracking = &clip->tracking; @@ -3945,7 +3954,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { float imat[4][4]; - copy_m4_m4(mat, camob->obmat); + copy_m4_m4(mat, camob_eval->obmat); BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, imat); invert_m4(imat); @@ -3954,7 +3963,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); } else { - BKE_tracking_get_camera_object_matrix(cob->scene, camob, mat); + BKE_tracking_get_camera_object_matrix(cob->scene, camob_eval, mat); mul_m4_m4m4(cob->matrix, obmat, mat); translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); @@ -3966,7 +3975,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); float len, d; - BKE_object_where_is_calc_mat4(scene, camob, mat); + BKE_object_where_is_calc_mat4(scene, camob_eval, mat); /* camera axis */ vec[0] = 0.0f; @@ -4034,7 +4043,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase } BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, camob); + BKE_camera_params_from_object(¶ms, camob_eval); if (params.is_ortho) { vec[0] = params.ortho_scale * (pos[0] - 0.5f + params.shiftx); @@ -4046,9 +4055,9 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase else vec[0] *= aspect; - mul_v3_m4v3(disp, camob->obmat, vec); + mul_v3_m4v3(disp, camob_eval->obmat, vec); - copy_m4_m4(rmat, camob->obmat); + copy_m4_m4(rmat, camob_eval->obmat); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -4066,10 +4075,10 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase else vec[0] *= aspect; - mul_v3_m4v3(disp, camob->obmat, vec); + mul_v3_m4v3(disp, camob_eval->obmat, vec); /* apply camera rotation so Z-axis would be co-linear */ - copy_m4_m4(rmat, camob->obmat); + copy_m4_m4(rmat, camob_eval->obmat); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -4088,7 +4097,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase invert_m4_m4(imat, depth_ob->obmat); - mul_v3_m4v3(ray_start, imat, camob->obmat[3]); + mul_v3_m4v3(ray_start, imat, camob_eval->obmat[3]); mul_v3_m4v3(ray_end, imat, cob->matrix[3]); sub_v3_v3v3(ray_nor, ray_end, ray_start); @@ -4147,6 +4156,7 @@ static void camerasolver_id_looper(bConstraint *con, ConstraintIDFunc func, void static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { + Depsgraph *depsgraph = cob->depsgraph; Scene *scene = cob->scene; bCameraSolverConstraint *data = con->data; MovieClip *clip = data->clip; @@ -4158,7 +4168,7 @@ static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float mat[4][4], obmat[4][4]; MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object = BKE_tracking_object_get_camera(tracking); - float ctime = BKE_scene_frame_get(scene); + float ctime = DEG_get_ctime(depsgraph); float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat); @@ -4205,6 +4215,7 @@ static void objectsolver_id_looper(bConstraint *con, ConstraintIDFunc func, void static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { + Depsgraph *depsgraph = cob->depsgraph; Scene *scene = cob->scene; bObjectSolverConstraint *data = con->data; MovieClip *clip = data->clip; @@ -4224,7 +4235,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (object) { float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4]; - float ctime = BKE_scene_frame_get(scene); + float ctime = DEG_get_ctime(depsgraph); float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); BKE_object_where_is_calc_mat4(scene, camob, cammat); @@ -4279,7 +4290,7 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa return; } - const float frame = BKE_scene_frame_get(scene); + const float frame = DEG_get_ctime(cob->depsgraph); const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); BKE_cachefile_ensure_handle(G.main, cache_file); @@ -4811,6 +4822,7 @@ void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph, Scene *scene, cob = MEM_callocN(sizeof(bConstraintOb), "tempConstraintOb"); cob->type = ownertype; cob->scene = scene; + cob->depsgraph = depsgraph; switch (ownertype) { case CONSTRAINT_OBTYPE_OBJECT: /* it is usually this case */ { diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index bfd4e07606f..e409f8c91f0 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -806,10 +806,11 @@ struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) /** \name Studio Light Icon * \{ */ -int BKE_icon_ensure_studio_light(struct StudioLight *sl) +int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type) { int icon_id = get_next_free_id(); - icon_create(icon_id, ICON_DATA_STUDIOLIGHT, sl); + Icon *icon = icon_create(icon_id, ICON_DATA_STUDIOLIGHT, sl); + icon->id_type = id_type; return icon_id; } /** \} */ diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index fd231971121..3a6d599ccd3 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -397,7 +397,7 @@ void BKE_view_layer_copy_data( // TODO: not always safe to free BKE_layer_collection_sync(scene_dst, view_layer_dst); } -void BKE_view_layer_rename(Scene *scene, ViewLayer *view_layer, const char *newname) +void BKE_view_layer_rename(Main *bmain, Scene *scene, ViewLayer *view_layer, const char *newname) { char oldname[sizeof(view_layer->name)]; @@ -418,8 +418,9 @@ void BKE_view_layer_rename(Scene *scene, ViewLayer *view_layer, const char *newn } } - /* fix all the animation data which may link to this */ + /* fix all the animation data and workspace which may link to this */ BKE_animdata_fix_paths_rename_all(NULL, "view_layers", oldname, view_layer->name); + BKE_workspace_view_layer_rename(bmain, scene, oldname, view_layer->name); /* Dependency graph uses view layer name based lookups. */ DEG_id_tag_update(&scene->id, 0); diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index dbfe619153d..37b5b62b06e 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -932,6 +932,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call BKE_workspace_layout_screen_set(layout, screen); } + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; relation; relation = relation->next) { + CALLBACK_INVOKE(relation->scene, IDWALK_CB_NOP); + } break; } case ID_GD: @@ -1080,6 +1083,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) case ID_LP: return ELEM(id_type_used, ID_IM); case ID_WS: + return ELEM(id_type_used, ID_SCR, ID_SCE); case ID_IM: case ID_VF: case ID_TXT: diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index c43a2e3b8ec..111968ba018 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -66,6 +66,7 @@ #include "BKE_library_query.h" #include "BKE_mesh.h" #include "BKE_multires.h" +#include "BKE_object.h" #include "BKE_DerivedMesh.h" /* may move these, only for modifier_path_relbase */ @@ -74,6 +75,7 @@ /* end */ #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "MOD_modifiertypes.h" @@ -1213,13 +1215,10 @@ struct DerivedMesh *modifier_applyModifierEM_DM_deprecated(struct ModifierData * /** Get evaluated mesh for other object, which is used as an operand for the modifier, * i.e. second operand for boolean modifier. */ -Mesh *BKE_modifier_get_evaluated_mesh_from_object(Object *ob, const ModifierApplyFlag flag) +Mesh *BKE_modifier_get_evaluated_mesh_from_object(const ModifierEvalContext *ctx, Object *ob) { - if (flag & MOD_APPLY_RENDER) { - /* TODO(sergey): Use proper derived render in the future. */ - return ob->mesh_evaluated; - } - else { - return ob->mesh_evaluated; - } + /* Note: we do not care about RENDER setting here, since we get data from despgraph + * (and render depsgraph shall be different from realtime one) + */ + return BKE_object_get_evaluated_mesh(ctx->depsgraph, ob); } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index d86b73ab1a9..a25b21a995a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3545,6 +3545,7 @@ static void registerShaderNodes(void) register_node_type_sh_tex_checker(); register_node_type_sh_tex_brick(); register_node_type_sh_tex_pointdensity(); + register_node_type_sh_tex_ies(); } static void registerTextureNodes(void) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9a1799ffb09..ab3300c4ff7 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -118,6 +118,7 @@ #include "BKE_image.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "DRW_engine.h" @@ -378,9 +379,9 @@ void BKE_object_free_caches(Object *object) if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } psmd->flag |= eParticleSystemFlag_file_loaded; update_flag |= OB_RECALC_DATA; @@ -890,8 +891,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f BLI_listbase_clear(&psysn->pathcachebufs); BLI_listbase_clear(&psysn->childcachebufs); - /* XXX Never copy caches here? */ - psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES); + psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag); /* XXX - from reading existing code this seems correct but intended usage of * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ @@ -2131,7 +2131,7 @@ void BKE_object_where_is_calc_time_ex( /* solve constraints */ if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; - cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + cob = BKE_constraints_make_evalob(depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); BKE_constraints_solve(depsgraph, &ob->constraints, cob, ctime); BKE_constraints_clear_evalob(cob); } @@ -2457,6 +2457,7 @@ void BKE_object_empty_draw_type_set(Object *ob, const int value) if (!ob->iuser) { ob->iuser = MEM_callocN(sizeof(ImageUser), "image user"); ob->iuser->ok = 1; + ob->iuser->flag |= IMA_ANIM_ALWAYS; ob->iuser->frames = 100; ob->iuser->sfra = 1; ob->iuser->fie_ima = 2; @@ -2801,6 +2802,15 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, return 1; } +/** Get evaluated mesh for given (main, original) object and depsgraph. */ +Mesh *BKE_object_get_evaluated_mesh(const Depsgraph *depsgraph, Object *ob) +{ + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + + return ob_eval->mesh_evaluated; +} + + static int pc_cmp(const void *a, const void *b) { const LinkData *ad = a, *bd = b; diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 91571e8bf62..d21a1326392 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -128,7 +128,7 @@ void BKE_object_eval_constraints(Depsgraph *depsgraph, * Not sure why, this is from Joshua - sergey * */ - cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + cob = BKE_constraints_make_evalob(depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); BKE_constraints_solve(depsgraph, &ob->constraints, cob, ctime); BKE_constraints_clear_evalob(cob); } @@ -276,11 +276,12 @@ void BKE_object_handle_data_update( /* quick cache removed */ } -bool BKE_object_eval_proxy_copy(Depsgraph *UNUSED(depsgraph), +bool BKE_object_eval_proxy_copy(Depsgraph *depsgraph, Object *object) { /* Handle proxy copy for target, */ if (ID_IS_LINKED(object) && object->proxy_from) { + DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); if (object->proxy_from->proxy_group) { /* Transform proxy into group space. */ Object *obg = object->proxy_from->proxy_group; diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c index 9bbde607b80..fb62645ef43 100644 --- a/source/blender/blenkernel/intern/outliner_treehash.c +++ b/source/blender/blenkernel/intern/outliner_treehash.c @@ -41,6 +41,7 @@ typedef struct TseGroup { TreeStoreElem **elems; + int lastused; int size; int allocated; } TseGroup; @@ -54,6 +55,7 @@ static TseGroup *tse_group_create(void) tse_group->elems = MEM_mallocN(sizeof(TreeStoreElem *), "TseGroupElems"); tse_group->size = 0; tse_group->allocated = 1; + tse_group->lastused = 0; return tse_group; } @@ -143,6 +145,16 @@ static void free_treehash_group(void *key) tse_group_free(key); } +void BKE_outliner_treehash_clear_used(void *treehash) +{ + GHashIterator gh_iter; + + GHASH_ITER(gh_iter, treehash) { + TseGroup *group = BLI_ghashIterator_getValue(&gh_iter); + group->lastused = 0; + } +} + void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore) { BLI_assert(treehash); @@ -161,6 +173,7 @@ void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem) *val_p = tse_group_create(); } group = *val_p; + group->lastused = 0; tse_group_add_element(group, elem); } @@ -198,10 +211,19 @@ TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, s group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); if (group) { - int i; - for (i = 0; i < group->size; i++) { - if (!group->elems[i]->used) { - return group->elems[i]; + /* Find unused element, with optimization to start from previously + * found element assuming we do repeated lookups. */ + int size = group->size; + int offset = group->lastused; + + for (int i = 0; i < size; i++, offset++) { + if (offset >= size) { + offset = 0; + } + + if (!group->elems[offset]->used) { + group->lastused = offset; + return group->elems[offset]; } } } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 4056a15fe47..f961510984a 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -338,8 +338,8 @@ void BKE_paint_palette_set(Paint *p, Palette *palette) { if (p) { id_us_min((ID *)p->palette); - id_us_plus((ID *)palette); p->palette = palette; + id_us_plus((ID *)p->palette); } } @@ -347,8 +347,8 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc) { if (br) { id_us_min((ID *)br->paint_curve); - id_us_plus((ID *)pc); br->paint_curve = pc; + id_us_plus((ID *)br->paint_curve); } } @@ -381,9 +381,7 @@ void BKE_palette_clear(Palette *palette) Palette *BKE_palette_add(Main *bmain, const char *name) { - Palette *palette; - - palette = BKE_libblock_alloc(bmain, ID_PAL, name, 0); + Palette *palette = BKE_id_new(bmain, ID_PAL, name); /* enable fake user by default */ id_fake_user_set(&palette->id); @@ -424,7 +422,7 @@ void BKE_palette_free(Palette *palette) PaletteColor *BKE_palette_color_add(Palette *palette) { - PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color"); + PaletteColor *color = MEM_callocN(sizeof(*color), "Palette Color"); BLI_addtail(&palette->colors, color); return color; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 26c822f5fef..a42826a1f89 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1295,7 +1295,7 @@ static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4 * \return the DM tessface index. */ int psys_particle_dm_face_lookup( - Mesh *mesh_final, Mesh *mesh_deformed, + Mesh *mesh_final, Mesh *mesh_original, int findex_orig, const float fw[4], struct LinkNode **poly_nodes) { MFace *mtessface_final; @@ -1308,7 +1308,7 @@ int psys_particle_dm_face_lookup( const int *index_mp_to_orig = NULL; const int totface_final = mesh_final->totface; - const int totface_deformed = mesh_deformed ? mesh_deformed->totface : totface_final; + const int totface_deformed = mesh_original ? mesh_original->totface : totface_final; if (ELEM(0, totface_final, totface_deformed)) { return DMCACHE_NOTFOUND; @@ -1318,8 +1318,8 @@ int psys_particle_dm_face_lookup( index_mp_to_orig = CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX); BLI_assert(index_mf_to_mpoly); - if (mesh_deformed) { - index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_deformed->fdata, CD_ORIGINDEX); + if (mesh_original) { + index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_original->fdata, CD_ORIGINDEX); } else { BLI_assert(mesh_final->runtime.deformed_only); @@ -1329,8 +1329,8 @@ int psys_particle_dm_face_lookup( pindex_orig = index_mf_to_mpoly_deformed[findex_orig]; - if (mesh_deformed == NULL) { - mesh_deformed = mesh_final; + if (mesh_original == NULL) { + mesh_original = mesh_final; } index_mf_to_mpoly_deformed = NULL; @@ -1349,7 +1349,7 @@ int psys_particle_dm_face_lookup( return DMCACHE_NOTFOUND; } } - else if (findex_orig >= mesh_deformed->totface) { + else if (findex_orig >= mesh_original->totface) { return DMCACHE_NOTFOUND; /* index not in the original mesh */ } diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index e85a3f15022..846afd48064 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -847,7 +847,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti /* Simple children */ if (part->childtype != PART_CHILD_FACES) { BLI_srandom(31415926 + psys->seed + psys->child_seed); - distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_deformed, psys, use_render_params); + distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params); return 0; } } @@ -1233,7 +1233,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) BLI_task_pool_free(task_pool); - psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_deformed, sim->psys); + psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_original, sim->psys); if (ctx.mesh != final_mesh) BKE_id_free(NULL, ctx.mesh); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 6c454cfa0b1..cba0721ab3f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -311,7 +311,7 @@ int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render /* Distribution */ /************************************************/ -void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, ParticleSystem *psys) +void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, ParticleSystem *psys) { /* use for building derived mesh mapping info: * @@ -350,7 +350,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, Partic origindex_poly= NULL; } else { - totelem = mesh_deformed->totface; + totelem = mesh_original->totface; origindex = CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX); /* for face lookups we need the poly origindex too */ @@ -414,7 +414,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, Partic pa->num_dmcache = DMCACHE_NOTFOUND; } else { /* FROM_FACE/FROM_VOLUME */ - pa->num_dmcache = psys_particle_dm_face_lookup(mesh_final, mesh_deformed, pa->num, pa->fuv, nodearray); + pa->num_dmcache = psys_particle_dm_face_lookup(mesh_final, mesh_original, pa->num, pa->fuv, nodearray); } } } @@ -3242,7 +3242,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re if (psys->recalc & PSYS_RECALC_RESET) { /* need this for changing subsurf levels */ - psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_deformed, psys); + psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_original, psys); if (psys->clmd) cloth_free_modifier(psys->clmd); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 7fd7b791a3f..a99057ac0ad 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -50,6 +50,7 @@ #include "BLI_blenlib.h" #include "BLI_threads.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -4071,9 +4072,11 @@ void BKE_ptcache_update_info(PTCacheID *pid) } else { PTCacheMem *pm = cache->mem_cache.first; - float bytes = 0.0f; - int i, mb; - + char formatted_tot[16]; + char formatted_mem[15]; + long long int bytes = 0.0f; + int i; + for (; pm; pm=pm->next) { for (i=0; i<BPHYS_TOT_DATA; i++) bytes += MEM_allocN_len(pm->data[i]); @@ -4088,12 +4091,10 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - mb = (bytes > 1024.0f * 1024.0f); + BLI_str_format_int_grouped(formatted_tot, totframes); + BLI_str_format_byte_unit(formatted_mem, bytes, true); - BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"), - totframes, - bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), - mb ? IFACE_("Mb") : IFACE_("kb")); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%s frames in memory (%s)"), formatted_tot, formatted_mem); } if (cache->flag & PTCACHE_OUTDATED) { diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 28d5cad3da8..75018bbe5bd 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1660,7 +1660,7 @@ void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, floa #else /* WITH_BULLET */ /* stubs */ -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-parameter" #endif @@ -1686,7 +1686,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic pop #endif diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d4ffc90c797..1a9a2d5b36d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -571,6 +571,8 @@ void BKE_scene_init(Scene *sce) */ sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; + sce->r.dither_intensity = 1.0f; + sce->r.bake_mode = 0; sce->r.bake_filter = 16; sce->r.bake_flag = R_BAKE_CLEAR; @@ -633,6 +635,7 @@ void BKE_scene_init(Scene *sce) sce->toolsettings->doublimit = 0.001; sce->toolsettings->vgroup_weight = 1.0f; sce->toolsettings->uvcalc_margin = 0.001f; + sce->toolsettings->uvcalc_flag = UVCALC_TRANSFORM_CORRECT; sce->toolsettings->unwrapper = 1; sce->toolsettings->select_thresh = 0.01f; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 8e8bf395f38..3d3130486cb 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -414,7 +414,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, const Mo } if (calc->smd->auxTarget) { - auxMesh = BKE_modifier_get_evaluated_mesh_from_object(calc->smd->auxTarget, ctx->flag); + auxMesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, calc->smd->auxTarget); if (!auxMesh) return; BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); @@ -625,7 +625,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, Mesh *me if (smd->target) { - calc.target = BKE_modifier_get_evaluated_mesh_from_object(smd->target, ctx->flag); + calc.target = BKE_modifier_get_evaluated_mesh_from_object(ctx, smd->target); /* TODO there might be several "bugs" on non-uniform scales matrixs * because it will no longer be nearest surface, not sphere projection diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index 8086156d3af..f139ea5fbe6 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -48,6 +48,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "GPU_texture.h" + #include "MEM_guardedalloc.h" @@ -67,6 +69,16 @@ static void studiolight_free(struct StudioLight *sl) IMB_freeImBuf(sl->radiance_buffers[index]); sl->radiance_buffers[index] = NULL; } + + if (sl->equirectangular_gputexture) { + GPU_texture_free(sl->equirectangular_gputexture); + sl->equirectangular_gputexture = NULL; + } + + if (sl->equirectangular_buffer) { + IMB_freeImBuf(sl->equirectangular_buffer); + sl->equirectangular_buffer = NULL; + } } MEM_freeN(sl); } @@ -78,7 +90,8 @@ static struct StudioLight *studiolight_create(void) sl->name[0] = 0x00; sl->flag = 0; sl->index = BLI_listbase_count(&studiolights); - sl->icon_id = BKE_icon_ensure_studio_light(sl); + sl->radiance_icon_id = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_RADIANCE); + sl->irradiance_icon_id = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE); for (int index = 0 ; index < 6 ; index ++) { sl->radiance_buffers[index] = NULL; @@ -109,7 +122,11 @@ static void studiolight_calculate_radiance(ImBuf *ibuf, float color[4], const fl nearest_interpolation_color_wrap(ibuf, NULL, color, uv[0] * ibuf->x, uv[1] * ibuf->y); } -static void studiolight_calculate_radiance_buffer(ImBuf *ibuf, float *colbuf, const float start_x, const float add_x, const float start_y, const float add_y, const float z, const int index_x, const int index_y, const int index_z) +static void studiolight_calculate_radiance_buffer( + ImBuf *ibuf, float *colbuf, + const float start_x, const float add_x, + const float start_y, const float add_y, const float z, + const int index_x, const int index_y, const int index_z) { float direction[3]; float yf = start_y; @@ -129,40 +146,71 @@ static void studiolight_calculate_radiance_buffer(ImBuf *ibuf, float *colbuf, co } } -static void studiolight_calculate_radiance_buffers(StudioLight *sl) +static void studiolight_load_equierectangular_image(StudioLight *sl) { if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { - ImBuf* ibuf = NULL; + ImBuf *ibuf = NULL; ibuf = IMB_loadiffname(sl->path, 0, NULL); if (ibuf) { IMB_float_from_rect(ibuf); - float *colbuf = MEM_mallocN(4*STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE*STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE*sizeof(float), __func__); + sl->equirectangular_buffer = ibuf; + } + } + sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED; +} + +static void studiolight_create_equierectangular_gputexture(StudioLight *sl) +{ + if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + char error[256]; + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED); + ImBuf *ibuf = sl->equirectangular_buffer; + sl->equirectangular_gputexture = GPU_texture_create_2D(ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error); + } + sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE; +} + + + +static void studiolight_calculate_radiance_buffers(StudioLight *sl) +{ + if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED); + ImBuf* ibuf = sl->equirectangular_buffer; + if (ibuf) { + float *colbuf = MEM_mallocN(SQUARE(STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * sizeof(float[4]), __func__); const float add = 1.0f / (STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE + 1); const float start = ((1.0f / STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * 0.5f) - 0.5f; /* front */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, 0.5f, 0, 2, 1); - sl->radiance_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* back */ studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, -0.5f, 0, 2, 1); - sl->radiance_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* left */ studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, 0.5f, 1, 2, 0); - sl->radiance_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* right */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 1, 2, 0); - sl->radiance_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* top */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 0, 1, 2); - sl->radiance_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* bottom */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, -start, -add, 0.5f, 0, 1, 2); - sl->radiance_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); #if 0 IMB_saveiff(sl->radiance_buffers[STUDIOLIGHT_X_POS], "/tmp/studiolight_radiance_left.png", IB_rectfloat); @@ -173,7 +221,6 @@ static void studiolight_calculate_radiance_buffers(StudioLight *sl) IMB_saveiff(sl->radiance_buffers[STUDIOLIGHT_Z_NEG], "/tmp/studiolight_radiance_top.png", IB_rectfloat); #endif MEM_freeN(colbuf); - IMB_freeImBuf(ibuf); } } sl->flag |= STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED; @@ -441,6 +488,114 @@ static int studiolight_cmp(const void *a, const void *b) return BLI_strcasecmp(sl1->name, sl2->name); } } + +/* icons */ +static unsigned int* studiolight_radiance_preview(StudioLight *sl, int icon_size) +{ + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED); + + uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); + int icon_center = icon_size / 2; + float sphere_radius = icon_center * 0.9; + + int offset = 0; + for (int y = 0; y < icon_size; y++) { + float dy = y - icon_center; + for (int x = 0; x < icon_size; x++) { + float dx = x - icon_center; + /* calculate aliasing */ + float alias = 0; + const float alias_step = 0.333; + for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { + for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { + if (sqrt(ay * ay + ax * ax) < sphere_radius) { + alias += alias_step * alias_step; + } + } + } + uint pixelresult = 0x0; + uint alias_i = clamp_i(alias * 256, 0, 255); + if (alias_i != 0) { + /* calculate normal */ + uint alias_mask = alias_i << 24; + float incoming[3]; + copy_v3_fl3(incoming, 0.0, 1.0, 0.0); + + float normal[3]; + normal[0] = dx / sphere_radius; + normal[2] = dy / sphere_radius; + normal[1] = -sqrt(-(normal[0] * normal[0]) - (normal[2] * normal[2]) + 1); + normalize_v3(normal); + + float direction[3]; + reflect_v3_v3v3(direction, incoming, normal); + + float color[4]; + studiolight_calculate_radiance(sl->equirectangular_buffer, color, direction); + + pixelresult = rgb_to_cpack( + linearrgb_to_srgb(color[0]), + linearrgb_to_srgb(color[1]), + linearrgb_to_srgb(color[2])) | alias_mask; + } + rect[offset++] = pixelresult; + } + } + return rect; +} + +static unsigned int* studiolight_irradiance_preview(StudioLight *sl, int icon_size) +{ + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); + + uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); + int icon_center = icon_size / 2; + float sphere_radius = icon_center * 0.9; + + int offset = 0; + for (int y = 0; y < icon_size; y++) { + float dy = y - icon_center; + for (int x = 0; x < icon_size; x++) { + float dx = x - icon_center; + /* calculate aliasing */ + float alias = 0; + const float alias_step = 0.333; + for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { + for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { + if (sqrt(ay * ay + ax * ax) < sphere_radius) { + alias += alias_step * alias_step; + } + } + } + uint pixelresult = 0x0; + uint alias_i = clamp_i(alias * 256, 0, 255); + if (alias_i != 0) { + /* calculate normal */ + uint alias_mask = alias_i << 24; + float normal[3]; + normal[0] = dx / sphere_radius; + normal[1] = dy / sphere_radius; + normal[2] = sqrt(-(normal[0] * normal[0]) - (normal[1] * normal[1]) + 1); + normalize_v3(normal); + + float color[3]; + mul_v3_v3fl(color, sl->diffuse_light[STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_POS], clamp_f(normal[1], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_NEG], clamp_f(-normal[1], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_POS], clamp_f(normal[2], 0.0, 1.0)); + + pixelresult = rgb_to_cpack( + linearrgb_to_srgb(color[0]), + linearrgb_to_srgb(color[1]), + linearrgb_to_srgb(color[2])) | alias_mask; + } + rect[offset++] = pixelresult; + } + } + return rect; +} + /* API */ void BKE_studiolight_init(void) { @@ -477,11 +632,16 @@ void BKE_studiolight_free(void) } } -struct StudioLight *BKE_studiolight_find(const char *name) +struct StudioLight *BKE_studiolight_find(const char *name, int flag) { LISTBASE_FOREACH(StudioLight *, sl, &studiolights) { if (STREQLEN(sl->name, name, FILE_MAXFILE)) { - return sl; + if ((sl->flag & flag) == flag) { + return sl; + } else { + /* flags do not match, so use default */ + return studiolights.first; + } } } /* When not found, use the default studio light */ @@ -504,56 +664,13 @@ const struct ListBase *BKE_studiolight_listbase(void) return &studiolights; } -unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size) +unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size, int icon_id_type) { - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); - - uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); - int icon_center = icon_size / 2; - float sphere_radius = icon_center * 0.9; - - int offset = 0; - for (int y = 0; y < icon_size; y++) { - float dy = y - icon_center; - for (int x = 0; x < icon_size; x++) { - float dx = x - icon_center; - /* calculate aliasing */ - float alias = 0; - const float alias_step = 0.333; - for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { - for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { - if (sqrt(ay * ay + ax * ax) < sphere_radius) { - alias += alias_step * alias_step; - } - } - } - uint pixelresult = 0x0; - uint alias_i = clamp_i(alias * 256, 0, 255); - if (alias_i != 0) { - /* calculate normal */ - uint alias_mask = alias_i << 24; - float normal[3]; - normal[0] = dx / sphere_radius; - normal[1] = dy / sphere_radius; - normal[2] = sqrt(-(normal[0] * normal[0]) - (normal[1] * normal[1]) + 1); - normalize_v3(normal); - - float color[3]; - mul_v3_v3fl(color, sl->diffuse_light[STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_POS], clamp_f(normal[1], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_NEG], clamp_f(-normal[1], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_POS], clamp_f(normal[2], 0.0, 1.0)); - - pixelresult = rgb_to_cpack( - linearrgb_to_srgb(color[0]), - linearrgb_to_srgb(color[1]), - linearrgb_to_srgb(color[2])) | alias_mask; - } - rect[offset++] = pixelresult; - } + if (icon_id_type == STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE) { + return studiolight_irradiance_preview(sl, icon_size); + } else { + return studiolight_radiance_preview(sl, icon_size); } - return rect; } void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) @@ -562,12 +679,18 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) return; } + if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED)) { + studiolight_load_equierectangular_image(sl); + } if ((flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED)) { studiolight_calculate_radiance_buffers(sl); } if ((flag & STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED)) { studiolight_calculate_diffuse_light(sl); } + if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE)) { + studiolight_create_equierectangular_gputexture(sl); + } if ((flag & STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED)) { studiolight_calculate_light_direction(sl); } diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index 7fc0d814089..fb768333bb6 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -26,6 +26,7 @@ #define DNA_PRIVATE_WORKSPACE_ALLOW #include <stdlib.h> +#include <string.h> #include "BLI_utildefines.h" #include "BLI_string.h" @@ -117,18 +118,6 @@ static void *workspace_relation_get_data_matching_parent( } } -static void workspace_relation_remove_from_value( - ListBase *relation_list, const void *value) -{ - for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) { - relation_next = relation->next; - - if (relation->value == value) { - workspace_relation_remove(relation_list, relation); - } - } -} - /** * Checks if \a screen is already used within any workspace. A screen should never be assigned to multiple * WorkSpaceLayouts, but that should be ensured outside of the BKE_workspace module and without such checks. @@ -168,7 +157,7 @@ WorkSpace *BKE_workspace_add(Main *bmain, const char *name) void BKE_workspace_free(WorkSpace *workspace) { BKE_workspace_relations_free(&workspace->hook_layout_relations); - BKE_workspace_relations_free(&workspace->scene_viewlayer_relations); + BLI_freelistN(&workspace->scene_layer_relations); BLI_freelistN(&workspace->owner_ids); BLI_freelistN(&workspace->layouts); @@ -269,16 +258,45 @@ void BKE_workspace_relations_free( } } +void BKE_workspace_scene_relations_free_invalid( + WorkSpace *workspace) +{ + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first, *relation_next; relation; relation = relation_next) { + relation_next = relation->next; + + if (relation->scene == NULL) { + BLI_freelinkN(&workspace->scene_layer_relations, relation); + } + else if (!BLI_findstring(&relation->scene->view_layers, relation->view_layer, offsetof(ViewLayer, name))) { + BLI_freelinkN(&workspace->scene_layer_relations, relation); + } + } +} /* -------------------------------------------------------------------- */ /* General Utils */ -void BKE_workspace_view_layer_remove_references( +void BKE_workspace_view_layer_rename( const Main *bmain, - const ViewLayer *view_layer) + const Scene *scene, + const char *old_name, + const char *new_name) { for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { - workspace_relation_remove_from_value(&workspace->scene_viewlayer_relations, view_layer); + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; relation; relation = relation->next) { + if (relation->scene == scene && STREQ(relation->view_layer, old_name)) { + STRNCPY(relation->view_layer, new_name); + } + } + } +} + +void BKE_workspace_view_layer_remove( + const Main *bmain, + const ViewLayer *UNUSED(view_layer)) +{ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + BKE_workspace_scene_relations_free_invalid(workspace); } } @@ -408,13 +426,38 @@ Base *BKE_workspace_active_base_get(const WorkSpace *workspace, const Scene *sce return view_layer->basact; } +ViewLayer *BKE_workspace_view_layer_exists(const WorkSpace *workspace, const Scene *scene) +{ + WorkSpaceSceneRelation *relation = BLI_findptr(&workspace->scene_layer_relations, scene, offsetof(WorkSpaceSceneRelation, scene)); + return (relation) ? BLI_findstring(&scene->view_layers, relation->view_layer, offsetof(ViewLayer, name)) : NULL; +} + ViewLayer *BKE_workspace_view_layer_get(const WorkSpace *workspace, const Scene *scene) { - return workspace_relation_get_data_matching_parent(&workspace->scene_viewlayer_relations, scene); + ViewLayer *layer = BKE_workspace_view_layer_exists(workspace, scene); + + if (layer == NULL) { + BKE_workspace_view_layer_set((WorkSpace *)workspace, scene->view_layers.first, (Scene *)scene); + layer = scene->view_layers.first; + } + + return layer; } + void BKE_workspace_view_layer_set(WorkSpace *workspace, ViewLayer *layer, Scene *scene) { - workspace_relation_ensure_updated(&workspace->scene_viewlayer_relations, scene, layer); + WorkSpaceSceneRelation *relation = BLI_findptr(&workspace->scene_layer_relations, scene, offsetof(WorkSpaceSceneRelation, scene)); + if (relation == NULL) { + relation = MEM_callocN(sizeof(*relation), __func__); + } + else { + BLI_remlink(&workspace->scene_layer_relations, relation); + } + + /* (Re)insert at the head of the list, for faster lookups. */ + relation->scene = scene; + STRNCPY(relation->view_layer, layer->name); + BLI_addhead(&workspace->scene_layer_relations, relation); } ListBase *BKE_workspace_layouts_get(WorkSpace *workspace) @@ -422,7 +465,6 @@ ListBase *BKE_workspace_layouts_get(WorkSpace *workspace) return &workspace->layouts; } - const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout) { return layout->name; diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 48be9d1842f..faa8dc03615 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -71,6 +71,7 @@ char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT A size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); +void BLI_str_format_byte_unit(char dst[15], long long int size, const bool base_10) ATTR_NONNULL(); int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index c0b76aa9cbf..75ddb5e739c 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -552,13 +552,13 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size); /* UNUSED macro, for function argument */ -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else # define UNUSED(x) UNUSED_ ## x #endif -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x #else # define UNUSED_FUNCTION(x) UNUSED_ ## x diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 1a6fd082e95..49630347032 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -799,6 +799,7 @@ int BLI_str_rstrip_float_zero(char *str, const char pad) while (end_p != p && *end_p == '0') { *end_p = pad; end_p--; + totstrip++; } } } @@ -995,6 +996,41 @@ size_t BLI_str_format_int_grouped(char dst[16], int num) } /** + * Format a size in bytes using binary units. + * 1000 -> 1 KB + * Number of decimal places grows with the used unit (e.g. 1.5 MB, 1.55 GB, 1.545 TB). + * + * \param dst The resulting string. Dimension of 14 to support largest possible value for \a bytes (LLONG_MAX). + * \param bytes Number to format + * \param base_10 Calculate using base 10 (GB, MB, ...) or 2 (GiB, MiB, ...) + */ +void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10) +{ + double bytes_converted = bytes; + int order = 0; + int decimals; + const int base = base_10 ? 1000 : 1024; + const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"}; + const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; + const int tot_units = ARRAY_SIZE(units_base_2); + + BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch"); + + while ((ABS(bytes_converted) >= base) && ((order + 1) < tot_units)) { + bytes_converted /= base; + order++; + } + decimals = MAX2(order - 1, 0); + + /* Format value first, stripping away floating zeroes. */ + const size_t dst_len = 15; + size_t len = BLI_snprintf_rlen(dst, dst_len, "%.*f", decimals, bytes_converted); + len -= (size_t)BLI_str_rstrip_float_zero(dst, '\0'); + dst[len++] = ' '; + BLI_strncpy(dst + len, base_10 ? units_base_10[order] : units_base_2[order], dst_len - len); +} + +/** * Find the ranges needed to split \a str into its individual words. * * \param str: The string to search for words. diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 761f3982e28..e6f5d9839ea 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -488,7 +488,8 @@ void BLI_spin_lock(SpinLock *spin) #elif defined(_MSC_VER) while (InterlockedExchangeAcquire(spin, 1)) { while (*spin) { - /* pass */ + /* Spinlock hint for processors with hyperthreading. */ + YieldProcessor(); } } #else diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 70c898a374e..bc4b8daf0d3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2865,6 +2865,19 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file) /* ************ READ WORKSPACES *************** */ +static void lib_link_workspace_scene_data(FileData *fd, WorkSpace *workspace) +{ + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; + relation != NULL; + relation = relation->next) + { + relation->scene = newlibadr(fd, workspace->id.lib, relation->scene); + } + + /* Free any relations that got lost due to missing datablocks. */ + BKE_workspace_scene_relations_free_invalid(workspace); +} + static void lib_link_workspaces(FileData *fd, Main *bmain) { for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { @@ -2877,31 +2890,7 @@ static void lib_link_workspaces(FileData *fd, Main *bmain) IDP_LibLinkProperty(id->properties, fd); id_us_ensure_real(id); - for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first, - *relation_next = NULL; - relation != NULL; - relation = relation_next) - { - relation_next = relation->next; - - relation->parent = newlibadr(fd, id->lib, relation->parent); - /* relation->value is set in direct_link_workspace_link_scene_data, - * except when loading linked data. */ - Scene *scene = relation->parent; - - if (scene) { - if (scene->id.lib != NULL) { - relation->value = BLI_findstring(&scene->view_layers, relation->value_name, offsetof(ViewLayer, name)); - } - if (relation->value == NULL) { - relation->value = scene->view_layers.first; - } - } - else { - /* Remove empty relation if scene got lost. */ - BLI_freelinkN(&workspace->scene_viewlayer_relations, relation); - } - } + lib_link_workspace_scene_data(fd, workspace); for (WorkSpaceLayout *layout = layouts->first, *layout_next; layout; layout = layout_next) { bScreen *screen = newlibadr(fd, id->lib, BKE_workspace_layout_screen_get(layout)); @@ -2928,7 +2917,7 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main { link_list(fd, BKE_workspace_layouts_get(workspace)); link_list(fd, &workspace->hook_layout_relations); - link_list(fd, &workspace->scene_viewlayer_relations); + link_list(fd, &workspace->scene_layer_relations); link_list(fd, &workspace->owner_ids); link_list(fd, &workspace->tools); @@ -2940,12 +2929,6 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main relation->value = newdataadr(fd, relation->value); } - if (ID_IS_LINKED(&workspace->id)) { - /* Appending workspace so render layer is likely from a different scene. Unset - * now, when activating workspace later we set a valid one from current scene. */ - BKE_workspace_relations_free(&workspace->scene_viewlayer_relations); - } - /* Same issue/fix as in direct_link_workspace_link_scene_data: Can't read workspace data * when reading windows, so have to update windows after/when reading workspaces. */ for (wmWindowManager *wm = main->wm.first; wm; wm = wm->id.next) { @@ -5247,7 +5230,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; psmd->mesh_final = NULL; - psmd->mesh_deformed = NULL; + psmd->mesh_original = NULL; psmd->psys= newdataadr(fd, psmd->psys); psmd->flag &= ~eParticleSystemFlag_psys_updated; psmd->flag |= eParticleSystemFlag_file_loaded; @@ -5717,7 +5700,6 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col cob->ob = newlibadr_us(fd, lib, cob->ob); if (cob->ob == NULL) { - BLI_assert(!"Collection linked object got lost"); // TODO: remove, only for testing now BLI_freelinkN(&collection->gobject, cob); } } @@ -5729,7 +5711,6 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) { - BLI_assert(!"Collection child got lost"); // TODO: remove, only for testing now BLI_freelinkN(&collection->children, child); } else { @@ -6073,31 +6054,7 @@ static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb) } } -/** - * Workspaces store a render layer pointer which can only be read after scene is read. - */ -static void direct_link_workspace_link_scene_data( - FileData *fd, Scene *scene, const ListBase *workspaces) -{ - for (WorkSpace *workspace = workspaces->first; workspace; workspace = workspace->id.next) { - for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first; - relation != NULL; - relation = relation->next) - { - ViewLayer *view_layer = newdataadr(fd, relation->value); - if (view_layer != NULL) { - BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1); - /* relation->parent is set in lib_link_workspaces */ - } - if (UNLIKELY(view_layer == NULL)) { - view_layer = scene->view_layers.first; - } - relation->value = view_layer; - } - } -} - -static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain) +static void direct_link_scene(FileData *fd, Scene *sce) { Editing *ed; Sequence *seq; @@ -6363,8 +6320,6 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain) sce->layer_properties = newdataadr(fd, sce->layer_properties); IDP_DirectLinkGroup_OrFree(&sce->layer_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - - direct_link_workspace_link_scene_data(fd, sce, &bmain->workspaces); } /* ****************** READ GREASE PENCIL ***************** */ @@ -7176,7 +7131,20 @@ static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map) BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map); } -static void lib_link_workspace_scene_data_restore(wmWindow *win, Scene *scene) +static void lib_link_workspace_scene_data_restore(struct IDNameLib_Map *id_map, WorkSpace *workspace) +{ + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; + relation != NULL; + relation = relation->next) + { + relation->scene = restore_pointer_by_name(id_map, &relation->scene->id, USER_IGNORE); + } + + /* Free any relations that got lost due to missing datablocks or view layers. */ + BKE_workspace_scene_relations_free_invalid(workspace); +} + +static void lib_link_window_scene_data_restore(wmWindow *win, Scene *scene) { bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); @@ -7437,12 +7405,14 @@ void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain); for (WorkSpace *workspace = newmain->workspaces.first; workspace; workspace = workspace->id.next) { + lib_link_workspace_scene_data_restore(id_map, workspace); + BKE_workspace_view_layer_set(workspace, cur_view_layer, curscene); + ListBase *layouts = BKE_workspace_layouts_get(workspace); for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) { lib_link_workspace_layout_restore(id_map, newmain, layout); } - BKE_workspace_view_layer_set(workspace, cur_view_layer, curscene); } for (wmWindow *win = curwm->windows.first; win; win = win->next) { @@ -7461,7 +7431,7 @@ void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene /* keep cursor location through undo */ copy_v3_v3(win->scene->cursor.location, oldscene->cursor.location); copy_qt_qt(win->scene->cursor.rotation, oldscene->cursor.rotation); - lib_link_workspace_scene_data_restore(win, win->scene); + lib_link_window_scene_data_restore(win, win->scene); BLI_assert(win->screen == NULL); } @@ -8373,7 +8343,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short wrong_id = direct_link_screen(fd, (bScreen *)id); break; case ID_SCE: - direct_link_scene(fd, (Scene *)id, main); + direct_link_scene(fd, (Scene *)id); break; case ID_OB: direct_link_object(fd, (Object *)id); @@ -9096,6 +9066,14 @@ static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *ch } } +static void expand_id(FileData *fd, Main *mainvar, ID *id) +{ + if (id->override_static) { + expand_doit(fd, mainvar, id->override_static->reference); + expand_doit(fd, mainvar, id->override_static->storage); + } +} + static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop) { if (!prop) @@ -9870,6 +9848,7 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) id = lbarray[a]->first; while (id) { if (id->tag & LIB_TAG_NEED_EXPAND) { + expand_id(fd, mainvar, id); expand_idprops(fd, mainvar, id->properties); switch (GS(id->name)) { diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 7bb20c38308..a25c744afc4 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -262,6 +262,7 @@ static void do_version_layer_collection_post( static void do_version_scene_collection_convert( Main *bmain, + ID *id, SceneCollection *sc, Collection *collection, GHash *collection_map) @@ -273,7 +274,8 @@ static void do_version_scene_collection_convert( for (SceneCollection *nsc = sc->scene_collections.first; nsc;) { SceneCollection *nsc_next = nsc->next; Collection *ncollection = BKE_collection_add(bmain, collection, nsc->name); - do_version_scene_collection_convert(bmain, nsc, ncollection, collection_map); + ncollection->id.lib = id->lib; + do_version_scene_collection_convert(bmain, id, nsc, ncollection, collection_map); nsc = nsc_next; } @@ -293,7 +295,7 @@ static void do_version_group_collection_to_collection(Main *bmain, Collection *g { /* Convert old 2.8 group collections to new unified collections. */ if (group->collection) { - do_version_scene_collection_convert(bmain, group->collection, group, NULL); + do_version_scene_collection_convert(bmain, &group->id, group->collection, group, NULL); } group->collection = NULL; @@ -317,7 +319,7 @@ static void do_version_scene_collection_to_collection(Main *bmain, Scene *scene) /* Convert scene collections. */ GHash *collection_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); if (scene->collection) { - do_version_scene_collection_convert(bmain, scene->collection, scene->master_collection, collection_map); + do_version_scene_collection_convert(bmain, &scene->id, scene->collection, scene->master_collection, collection_map); scene->collection = NULL; } @@ -434,6 +436,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) collections[DO_VERSION_COLLECTION_VISIBLE].suffix); Collection *collection = BKE_collection_add(bmain, collection_master, name); + collection->id.lib = scene->id.lib; collection->flag |= collections[DO_VERSION_COLLECTION_VISIBLE].flag; collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] = collection; collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer); @@ -453,6 +456,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) collections[collection_index].suffix); Collection *collection = BKE_collection_add(bmain, collection_parent, name); + collection->id.lib = scene->id.lib; collection->flag |= collections[collection_index].flag; collections[collection_index].collections[layer] = collection; collections[collection_index].created |= (1 << layer); @@ -676,12 +680,14 @@ void do_versions_after_linking_280(Main *main) /* Convert group layer visibility flags to hidden nested collection. */ for (Collection *collection = main->collection.first; collection; collection = collection->id.next) { - Collection *collection_hidden = NULL; + /* Add fake user for all existing groups. */ + id_fake_user_set(&collection->id); if (collection->flag & (COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER)) { continue; } + Collection *collection_hidden = NULL; for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) { cob_next = cob->next; Object *ob = cob->ob; @@ -689,6 +695,7 @@ void do_versions_after_linking_280(Main *main) if (!(ob->lay & collection->layer)) { if (collection_hidden == NULL) { collection_hidden = BKE_collection_add(main, collection, "Hidden"); + collection_hidden->id.lib = collection->id.lib; collection_hidden->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER; } @@ -696,9 +703,6 @@ void do_versions_after_linking_280(Main *main) BKE_collection_object_remove(main, collection, ob, true); } } - - /* Add fake user for all existing groups. */ - id_fake_user_set(&collection->id); } /* Convert layers to collections. */ diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f7a69931f9f..764eaecd1e9 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -141,6 +141,8 @@ void BLO_update_defaults_startup_blend(Main *bmain) if (scene->toolsettings) { ToolSettings *ts = scene->toolsettings; + ts->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; + if (ts->sculpt) { Sculpt *sculpt = ts->sculpt; sculpt->paint.symmetry_flags |= PAINT_SYMM_X; @@ -354,6 +356,7 @@ void BLO_update_defaults_startup_blend(Main *bmain) for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { scene->r.displaymode = R_OUTPUT_WINDOW; scene->r.size = 100; + scene->r.dither_intensity = 1.0f; scene->unit.system = USER_UNIT_METRIC; STRNCPY(scene->view_settings.view_transform, "Filmic"); } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index f3042dc84db..de1699e24b7 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -3599,18 +3599,10 @@ static void write_workspace(WriteData *wd, WorkSpace *workspace) { ListBase *layouts = BKE_workspace_layouts_get(workspace); - /* Update the names for file (only need to set on write). */ - for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first; - relation; - relation = relation->next) - { - STRNCPY(relation->value_name, ((ViewLayer *)relation->value)->name); - } - writestruct(wd, ID_WS, WorkSpace, 1, workspace); writelist(wd, DATA, WorkSpaceLayout, layouts); writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations); - writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations); + writelist(wd, DATA, WorkSpaceSceneRelation, &workspace->scene_layer_relations); writelist(wd, DATA, wmOwnerID, &workspace->owner_ids); writelist(wd, DATA, bToolRef, &workspace->tools); for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) { diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index 5245d24a075..320bebc9958 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -169,7 +169,7 @@ set(SRC bmesh_tools.h ) -if(MSVC) +if(MSVC AND NOT MSVC_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101") endif() diff --git a/source/blender/compositor/nodes/COM_MathNode.cpp b/source/blender/compositor/nodes/COM_MathNode.cpp index eb6bb2caf56..0fb6933afe7 100644 --- a/source/blender/compositor/nodes/COM_MathNode.cpp +++ b/source/blender/compositor/nodes/COM_MathNode.cpp @@ -86,6 +86,9 @@ void MathNode::convertToOperations(NodeConverter &converter, const CompositorCon case NODE_MATH_ABS: operation = new MathAbsoluteOperation(); break; + case NODE_MATH_ATAN2: + operation = new MathArcTan2Operation(); + break; } if (operation) { diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp index 32a1e77b9a7..dbc91980acd 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp @@ -343,3 +343,16 @@ void MathAbsoluteOperation::executePixelSampled(float output[4], float x, float clampIfNeeded(output); } + +void MathArcTan2Operation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +{ + float inputValue1[4]; + float inputValue2[4]; + + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + + output[0] = atan2(inputValue1[0], inputValue2[0]); + + clampIfNeeded(output); +}
\ No newline at end of file diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h index 32cd19f1fb9..04019372711 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.h +++ b/source/blender/compositor/operations/COM_MathBaseOperation.h @@ -169,4 +169,10 @@ public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; +class MathArcTan2Operation : public MathBaseOperation { +public: + MathArcTan2Operation() : MathBaseOperation() {} + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); +}; + #endif diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 9a1bd87f93d..64bdbe49dac 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -549,7 +549,11 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) */ ComponentKey ob_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE); ComponentKey proxy_pose_key(&object->proxy->id, DEG_NODE_TYPE_EVAL_POSE); - add_relation(ob_pose_key, proxy_pose_key, "Proxy"); + add_relation(ob_pose_key, proxy_pose_key, "Proxy Pose"); + + ComponentKey ob_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey proxy_transform_key(&object->proxy->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform"); } /* Object dupligroup. */ if (object->dup_group != NULL) { 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 c8b9702621e..0e8d4669108 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 @@ -49,6 +49,7 @@ #include "BLI_threads.h" #include "BLI_string.h" +#include "BKE_curve.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_layer.h" @@ -76,6 +77,7 @@ extern "C" { # include "DNA_lattice_types.h" # include "DNA_linestyle_types.h" # include "DNA_material_types.h" +# include "DNA_meta_types.h" # include "DNA_node_types.h" # include "DNA_texture_types.h" # include "DNA_world_types.h" @@ -276,10 +278,11 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) bool result = BKE_id_copy_ex(NULL, (ID *)id_for_copy, &newid, - LIB_ID_CREATE_NO_MAIN | - LIB_ID_CREATE_NO_USER_REFCOUNT | - LIB_ID_CREATE_NO_ALLOCATE | - LIB_ID_CREATE_NO_DEG_TAG, + (LIB_ID_CREATE_NO_MAIN | + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_ALLOCATE | + LIB_ID_CREATE_NO_DEG_TAG | + LIB_ID_COPY_CACHES), false); #ifdef NESTED_ID_NASTY_WORKAROUND @@ -410,7 +413,7 @@ int foreach_libblock_remap_callback(void *user_data_v, return IDWALK_RET_NOP; } -void updata_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/, +void update_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/, const ID *id_orig, ID *id_cow) { const bArmature *armature_orig = (const bArmature *)id_orig; @@ -418,7 +421,32 @@ void updata_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/, armature_cow->edbo = armature_orig->edbo; } -void updata_mesh_edit_mode_pointers(const Depsgraph *depsgraph, +void update_curve_edit_mode_pointers(const Depsgraph * /*depsgraph*/, + const ID *id_orig, ID *id_cow) +{ + const Curve *curve_orig = (const Curve *)id_orig; + Curve *curve_cow = (Curve *)id_cow; + curve_cow->editnurb = curve_orig->editnurb; + curve_cow->editfont = curve_orig->editfont; +} + +void update_mball_edit_mode_pointers(const Depsgraph * /*depsgraph*/, + const ID *id_orig, ID *id_cow) +{ + const MetaBall *mball_orig = (const MetaBall *)id_orig; + MetaBall *mball_cow = (MetaBall *)id_cow; + mball_cow->editelems = mball_orig->editelems; +} + +void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/, + const ID *id_orig, ID *id_cow) +{ + const Lattice *lt_orig = (const Lattice *)id_orig; + Lattice *lt_cow = (Lattice *)id_cow; + lt_cow->editlatt = lt_orig->editlatt; +} + +void update_mesh_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow) { /* For meshes we need to update edit_btmesh to make it to point @@ -443,16 +471,25 @@ void updata_mesh_edit_mode_pointers(const Depsgraph *depsgraph, /* Edit data is stored and owned by original datablocks, copied ones * are simply referencing to them. */ -void updata_edit_mode_pointers(const Depsgraph *depsgraph, +void update_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow) { const ID_Type type = GS(id_orig->name); switch (type) { case ID_AR: - updata_armature_edit_mode_pointers(depsgraph, id_orig, id_cow); + update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow); break; case ID_ME: - updata_mesh_edit_mode_pointers(depsgraph, id_orig, id_cow); + update_mesh_edit_mode_pointers(depsgraph, id_orig, id_cow); + break; + case ID_CU: + update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow); + break; + case ID_MB: + update_mball_edit_mode_pointers(depsgraph, id_orig, id_cow); + break; + case ID_LT: + update_lattice_edit_mode_pointers(depsgraph, id_orig, id_cow); break; default: break; @@ -504,7 +541,7 @@ void update_special_pointers(const Depsgraph *depsgraph, default: break; } - updata_edit_mode_pointers(depsgraph, id_orig, id_cow); + update_edit_mode_pointers(depsgraph, id_orig, id_cow); } /* This callback is used to validate that all nested ID datablocks are @@ -680,6 +717,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, ListBase gpumaterial_backup; ListBase *gpumaterial_ptr = NULL; Mesh *mesh_evaluated = NULL; + CurveCache *curve_cache = NULL; short base_flag = 0; if (check_datablock_expanded(id_cow)) { switch (id_type) { @@ -729,6 +767,10 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, object->data = mesh_evaluated->id.orig_id; } } + /* Store curve cache and make sure we don't free it. */ + curve_cache = object->curve_cache; + object->curve_cache = NULL; + /* Make a backup of base flags. */ base_flag = object->base_flag; break; @@ -764,6 +806,9 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, ((Mesh *)mesh_evaluated->id.orig_id)->edit_btmesh; } } + if (curve_cache != NULL) { + object->curve_cache = curve_cache; + } object->base_flag = base_flag; } return id_cow; @@ -786,6 +831,25 @@ void discard_armature_edit_mode_pointers(ID *id_cow) armature_cow->edbo = NULL; } +void discard_curve_edit_mode_pointers(ID *id_cow) +{ + Curve *curve_cow = (Curve *)id_cow; + curve_cow->editnurb = NULL; + curve_cow->editfont = NULL; +} + +void discard_mball_edit_mode_pointers(ID *id_cow) +{ + MetaBall *mball_cow = (MetaBall *)id_cow; + mball_cow->editelems = NULL; +} + +void discard_lattice_edit_mode_pointers(ID *id_cow) +{ + Lattice *lt_cow = (Lattice *)id_cow; + lt_cow->editlatt = NULL; +} + void discard_mesh_edit_mode_pointers(ID *id_cow) { Mesh *mesh_cow = (Mesh *)id_cow; @@ -810,6 +874,15 @@ void discard_edit_mode_pointers(ID *id_cow) case ID_ME: discard_mesh_edit_mode_pointers(id_cow); break; + case ID_CU: + discard_curve_edit_mode_pointers(id_cow); + break; + case ID_MB: + discard_mball_edit_mode_pointers(id_cow); + break; + case ID_LT: + discard_lattice_edit_mode_pointers(id_cow); + break; default: break; } diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 96dcac5b2d2..965faa7ba53 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC intern/draw_cache_impl_metaball.c intern/draw_cache_impl_particles.c intern/draw_common.c + intern/draw_debug.c intern/draw_instance_data.c intern/draw_manager.c intern/draw_manager_data.c @@ -96,6 +97,7 @@ set(SRC engines/eevee/eevee_engine.c engines/eevee/eevee_lightprobes.c engines/eevee/eevee_lights.c + engines/eevee/eevee_lookdev.c engines/eevee/eevee_materials.c engines/eevee/eevee_mist.c engines/eevee/eevee_motion_blur.c @@ -120,6 +122,7 @@ set(SRC intern/draw_cache.h intern/draw_cache_impl.h intern/draw_common.h + intern/draw_debug.h intern/draw_instance_data.h intern/draw_manager.h intern/draw_manager_text.h @@ -220,6 +223,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.gls data_to_c_simple(engines/workbench/shaders/workbench_forward_composite_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_depth_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_object_outline_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC) diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 204990de5b0..c86574f7557 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -119,7 +119,8 @@ static void basic_cache_init(void *vedata) #ifdef USE_DEPTH /* Depth Pass */ { - psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + psl->depth_pass = DRW_pass_create( + "Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); psl->depth_pass_cull = DRW_pass_create( diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c index bcbc37ac7af..d08fee6039f 100644 --- a/source/blender/draw/engines/clay/clay_engine.c +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -224,7 +224,8 @@ static void clay_view_layer_data_free(void *storage) static CLAY_ViewLayerData *CLAY_view_layer_data_get(void) { - CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure(&draw_engine_clay_type, &clay_view_layer_data_free); + CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure( + &draw_engine_clay_type, &clay_view_layer_data_free); if (*sldata == NULL) { *sldata = MEM_callocN(sizeof(**sldata), "CLAY_ViewLayerData"); @@ -751,7 +752,8 @@ static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, boo return shgrps[id]; } -static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl) +static DRWShadingGroup *CLAY_hair_shgrp_get( + CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl) { DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps; @@ -803,8 +805,8 @@ static void clay_cache_init(void *vedata) /* Hair Pass */ { psl->hair_pass = DRW_pass_create( - "Hair Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + "Hair Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); } { diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index f644b59c0b7..8be9c637fbc 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -92,7 +92,7 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_BLOOM_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) { const float *viewport_size = DRW_viewport_size_get(); /* Shaders */ diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index c275a5005ff..60c6175f4fa 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -84,7 +84,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_DOF_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_DOF_ENABLED) { RegionView3D *rv3d = draw_ctx->rv3d; if (!e_data.dof_downsample_sh) { diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 646c7a03afd..211a8abd42c 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -305,7 +305,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); { - psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR); + psl->color_downsample_ps = DRW_pass_create( + "Downsample", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps); DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src); DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); @@ -315,7 +316,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { static int zero = 0; static uint six = 6; - psl->color_downsample_cube_ps = DRW_pass_create("Downsample Cube", DRW_STATE_WRITE_COLOR); + psl->color_downsample_cube_ps = DRW_pass_create( + "Downsample Cube", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps); DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src); DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1); @@ -327,25 +329,29 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Perform min/max downsample */ DRWShadingGroup *grp; - psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downlevel_ps = DRW_pass_create( + "HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &txl->maxzbuffer); DRW_shgroup_call_add(grp, quad, NULL); /* Copy depth buffer to halfres top level of HiZ */ - psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downdepth_ps = DRW_pass_create( + "HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); - psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downdepth_layer_ps = DRW_pass_create( + "HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1); DRW_shgroup_call_add(grp, quad, NULL); - psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_copydepth_ps = DRW_pass_create( + "HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); @@ -353,7 +359,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { /* This pass compute camera motions to the non moving objects. */ - psl->velocity_resolve = DRW_pass_create("Velocity Resolve", DRW_STATE_WRITE_COLOR); + psl->velocity_resolve = DRW_pass_create( + "Velocity Resolve", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.velocity_resolve_sh, psl->velocity_resolve); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); @@ -504,6 +511,13 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) /* Save the final texture and framebuffer for final transformation or read. */ effects->final_tx = effects->source_buffer; effects->final_fb = (effects->target_buffer != fbl->main_color_fb) ? fbl->main_fb : fbl->effect_fb; + if ((effects->enabled_effects & EFFECT_TAA) && (effects->enabled_effects & (EFFECT_BLOOM | EFFECT_DOF | EFFECT_MOTION_BLUR)) == 0) { + if (!effects->swap_double_buffer) { + effects->final_fb = fbl->double_buffer_fb; + } else { + effects->final_fb = fbl->main_fb; + } + } /* If no post processes is enabled, buffers are still not swapped, do it now. */ SWAP_DOUBLE_BUFFERS(); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 8448393aa97..f6776d43665 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -187,7 +187,6 @@ static void eevee_draw_background(void *vedata) /* Default framebuffer and texture */ DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - /* Sort transparents before the loop. */ DRW_pass_sort_shgroup_z(psl->transparent_pass); @@ -310,6 +309,11 @@ static void eevee_draw_background(void *vedata) } } + /* LookDev */ + EEVEE_lookdev_draw_background(vedata); + /* END */ + + /* Tonemapping and transfer result to default framebuffer. */ GPU_framebuffer_bind(dfbl->default_fb); DRW_transform_to_display(stl->effects->final_tx); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index d2faeb6ed39..c7a2951a670 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -71,6 +71,7 @@ static struct { struct GPUShader *probe_default_sh; + struct GPUShader *probe_default_studiolight_sh; struct GPUShader *probe_filter_glossy_sh; struct GPUShader *probe_filter_diffuse_sh; struct GPUShader *probe_filter_visibility_sh; @@ -214,6 +215,9 @@ static void lightprobe_shaders_init(void) e_data.probe_default_sh = DRW_shader_create( datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL); + e_data.probe_default_studiolight_sh = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, "#define LOOKDEV\n"); + MEM_freeN(shader_str); shader_str = BLI_string_joinN( @@ -411,7 +415,11 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat World *wo = scene->world; float *col = ts.colorBackground; - if (wo) { + + /* LookDev */ + EEVEE_lookdev_cache_init(vedata, &grp, e_data.probe_default_studiolight_sh, psl->probe_background, pinfo); + /* END */ + if (!grp && wo) { col = &wo->horr; bool wo_sh_compiled = true; @@ -445,6 +453,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat if (wo->update_flag != 0 || pinfo->prev_world != wo || pinfo->prev_wo_sh_compiled != wo_sh_compiled) { pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = 0; pinfo->prev_wo_sh_compiled = wo_sh_compiled; pinfo->prev_world = wo; } @@ -452,6 +461,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat } else if (pinfo->prev_world) { pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = 0; pinfo->prev_wo_sh_compiled = false; pinfo->prev_world = NULL; } @@ -1830,6 +1840,7 @@ void EEVEE_lightprobes_free(void) MEM_SAFE_FREE(e_data.format_probe_display_cube); MEM_SAFE_FREE(e_data.format_probe_display_planar); DRW_SHADER_FREE_SAFE(e_data.probe_default_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_default_studiolight_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_visibility_sh); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 123dabbe226..dd69e19e7c1 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -82,7 +82,8 @@ static bool lightbits_get(const EEVEE_LightBits *r, uint idx) return r->fields[idx / 8] & (1 << (idx % 8)); } -static void lightbits_convert(EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, uint table_length) +static void lightbits_convert( + EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, uint table_length) { for (int i = 0; i < table_length; ++i) { if (lightbits_get(bitf, i) != 0) { @@ -591,7 +592,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) } else if (la->type == LA_AREA) { evli->sizex = max_ff(0.0001f, la->area_size * scale[0] * 0.5f); - if (la->area_shape == LA_AREA_RECT) { + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { evli->sizey = max_ff(0.0001f, la->area_sizey * scale[1] * 0.5f); } else { @@ -602,10 +603,18 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) evli->radius = max_ff(0.001f, la->area_size); } + /* Lamp Type */ + evli->lamptype = (float)la->type; + /* Make illumination power constant */ if (la->type == LA_AREA) { power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */ 80.0f; /* XXX : Empirical, Fit cycles power */ + if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { + evli->lamptype = LAMPTYPE_AREA_ELLIPSE; + /* Scale power to account for the lower area of the ellipse compared to the surrouding rectangle. */ + power *= 4.0f / M_PI; + } } else if (la->type == LA_SPOT || la->type == LA_LOCAL) { power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */ @@ -620,9 +629,6 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) } mul_v3_fl(evli->color, power * la->energy); - /* Lamp Type */ - evli->lamptype = (float)la->type; - /* No shadow by default */ evli->shadowid = -1.0f; } diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c new file mode 100644 index 00000000000..4ae13669a01 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -0,0 +1,130 @@ +/* + * Copyright 2016, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_lookdev.c + * \ingroup draw_engine + */ +#include "DRW_render.h" + +#include "BKE_camera.h" +#include "BKE_studiolight.h" + +#include "DNA_screen_types.h" + +#include "eevee_private.h" + +void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, DRWShadingGroup **grp, GPUShader *shader, DRWPass *pass, EEVEE_LightProbesInfo *pinfo) +{ + EEVEE_StorageList *stl = vedata->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + if (v3d && v3d->drawtype == OB_MATERIAL) + { + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_ORIENTATION_WORLD); + if ((sl->flag & STUDIOLIGHT_ORIENTATION_WORLD)) { + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE); + *grp = DRW_shgroup_create(shader, pass); + GPUTexture *tex = sl->equirectangular_gputexture; + DRW_shgroup_uniform_texture(*grp, "image", tex); + + axis_angle_to_mat3_single(stl->g_data->studiolight_matrix, 'Z', v3d->shading.studiolight_rot_z); + DRW_shgroup_uniform_mat3(*grp, "StudioLightMatrix", stl->g_data->studiolight_matrix); + + DRW_shgroup_uniform_float(*grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(*grp, geom, NULL); + + /* Do we need to recalc the lightprobes? */ + if (pinfo && (pinfo->studiolight_index != sl->index || pinfo->studiolight_rot_z != v3d->shading.studiolight_rot_z)) { + pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = sl->index; + pinfo->studiolight_rot_z = v3d->shading.studiolight_rot_z; + pinfo->prev_wo_sh_compiled = false; + pinfo->prev_world = NULL; + } + } + } +} + +void EEVEE_lookdev_draw_background(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (psl->lookdev_pass && draw_ctx->v3d) { + DRW_stats_group_start("Look Dev"); + CameraParams params; + BKE_camera_params_init(¶ms); + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + ARegion *ar = draw_ctx->ar; + + BKE_camera_params_from_view3d(¶ms, draw_ctx->depsgraph, v3d, rv3d); + params.is_ortho = true; + params.ortho_scale = 4.0; + params.zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; + BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); + BKE_camera_params_compute_matrix(¶ms); + + const float *viewport_size = DRW_viewport_size_get(); + int viewport_inset_x = viewport_size[0]/4; + int viewport_inset_y = viewport_size[1]/4; + + EEVEE_CommonUniformBuffer *common = &sldata->common_data; + common->la_num_light = 0; + common->prb_num_planar = 0; + common->prb_num_render_cube = 1; + common->prb_num_render_grid = 1; + common->ao_dist = 0.0f; + common->ao_factor = 0.0f; + common->ao_settings = 0.0f; + DRW_uniformbuffer_update(sldata->common_ubo, common); + + /* override matrices */ + float winmat[4][4]; + float winmat_inv[4][4]; + copy_m4_m4(winmat, params.winmat); + invert_m4_m4(winmat_inv, winmat); + DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(winmat_inv, DRW_MAT_WININV); + float viewmat[4][4]; + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + float persmat[4][4]; + float persmat_inv[4][4]; + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persmat_inv, persmat); + DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(persmat_inv, DRW_MAT_PERSINV); + + GPUFrameBuffer *fb = effects->final_fb; + GPU_framebuffer_bind(fb); + GPU_framebuffer_viewport_set(fb, viewport_size[0]-viewport_inset_x, 0, viewport_inset_x, viewport_inset_y); + DRW_draw_pass(psl->lookdev_pass); + + DRW_viewport_matrix_override_unset_all(); + DRW_stats_group_end(); + } +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index b585b1a4f85..1134c82954c 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -34,6 +34,7 @@ #include "BKE_particle.h" #include "BKE_paint.h" #include "BKE_pbvh.h" +#include "BKE_studiolight.h" #include "DNA_world_types.h" #include "DNA_modifier_types.h" @@ -54,6 +55,7 @@ static struct { struct GPUShader *default_prepass_clip_sh; struct GPUShader *default_lit[VAR_MAT_MAX]; struct GPUShader *default_background; + struct GPUShader *default_studiolight_background; struct GPUShader *update_noise_sh; /* 64*64 array texture containing all LUTs and other utilitarian arrays. @@ -320,6 +322,9 @@ static char *eevee_get_defines(int options) if (((options & VAR_MAT_VOLUME) != 0) && ((options & VAR_MAT_BLEND) != 0)) { BLI_dynstr_appendf(ds, "#define USE_ALPHA_BLEND_VOLUMETRICS\n"); } + if ((options & VAR_MAT_LOOKDEV) != 0) { + BLI_dynstr_appendf(ds, "#define LOOKDEV\n"); + } str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); @@ -578,6 +583,10 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL); + e_data.default_studiolight_background = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, + "#define LOOKDEV\n"); + e_data.default_prepass_sh = DRW_shader_create( datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, NULL); @@ -861,6 +870,35 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get( return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); } +/** + * Create a default shading group inside the lookdev pass without standard uniforms. + **/ +static struct DRWShadingGroup *EEVEE_lookdev_shading_group_get( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + bool use_ssr, int shadow_method) +{ + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV; + + options |= eevee_material_shadow_option(shadow_method); + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + if (vedata->psl->lookdev_pass == NULL) { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_CULL_BACK; + vedata->psl->lookdev_pass = DRW_pass_create("LookDev Pass", state); + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass); + /* XXX / WATCH: This creates non persistent binds for the ubos and textures. + * But it's currently OK because the following shgroups does not add any bind. */ + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false); + } + + return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass); +} void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; @@ -884,7 +922,11 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) float *col = ts.colorBackground; - if (wo) { + /* LookDev */ + EEVEE_lookdev_cache_init(vedata, &grp, e_data.default_studiolight_background, psl->background_pass, NULL); + /* END */ + + if (!grp && wo) { col = &wo->horr; if (wo->use_nodes && wo->nodetree) { @@ -936,7 +978,8 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; psl->depth_pass_clip_cull = DRW_pass_create("Depth Pass Cull Clip", state); - stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull); + stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull); DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); } @@ -952,26 +995,33 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; psl->refract_depth_pass_cull = DRW_pass_create("Refract Depth Pass Cull", state); - stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh, psl->refract_depth_pass_cull); + stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create( + e_data.default_prepass_sh, psl->refract_depth_pass_cull); state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; psl->refract_depth_pass_clip = DRW_pass_create("Refract Depth Pass Clip", state); - stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip); + stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip); DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip, "clip_block", sldata->clip_ubo); state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; psl->refract_depth_pass_clip_cull = DRW_pass_create("Refract Depth Pass Cull Clip", state); - stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull); + stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull); DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); } { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | + DRW_STATE_WIRE); psl->refract_pass = DRW_pass_create("Opaque Refraction Pass", state); } { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | + DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL); psl->sss_pass = DRW_pass_create("Subsurface Pass", state); e_data.sss_count = 0; } @@ -1062,16 +1112,16 @@ static void material_opaque( static float half = 0.5f; /* Shading */ - *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, false, use_refract, - use_sss, use_translucency, linfo->shadow_method); + *gpumat = EEVEE_material_mesh_get( + scene, ma, vedata, false, false, use_refract, + use_sss, use_translucency, linfo->shadow_method); GPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat); /* Alpha CLipped : Discard pixel from depth pass, then * fail the depth test for shading. */ if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) { - *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma, - (ma->blend_method == MA_BM_HASHED), false); + *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma, (ma->blend_method == MA_BM_HASHED), false); GPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth); if (status_mat_depth != GPU_MAT_SUCCESS) { @@ -1080,12 +1130,16 @@ static void material_opaque( status_mat_surface = status_mat_depth; } else if (use_refract) { - *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); + *shgrp_depth = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); + *shgrp_depth_clip = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); } else { - *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); + *shgrp_depth = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); + *shgrp_depth_clip = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); } if (*shgrp_depth != NULL) { @@ -1110,16 +1164,18 @@ static void material_opaque( static int first_ssr = 1; int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr; - *shgrp = DRW_shgroup_material_create(*gpumat, - (use_refract) ? psl->refract_pass : - (use_sss) ? psl->sss_pass : psl->material_pass); + *shgrp = DRW_shgroup_material_create( + *gpumat, + (use_refract) ? psl->refract_pass : + (use_sss) ? psl->sss_pass : psl->material_pass); add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false); if (use_sss) { struct GPUTexture *sss_tex_profile = NULL; - struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat, - stl->effects->sss_sample_count, - &sss_tex_profile); + struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get( + *gpumat, + stl->effects->sss_sample_count, + &sss_tex_profile); if (sss_profile) { if (use_translucency) { @@ -1188,7 +1244,8 @@ static void material_opaque( static void material_transparent( Material *ma, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth) + bool do_cull, bool use_flat_nor, + struct GPUMaterial **gpumat, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; @@ -1196,8 +1253,10 @@ static void material_transparent( EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; EEVEE_LampsInfo *linfo = sldata->lamps; - const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0); - + const bool use_refract = ( + ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && + ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0) + ); float *color_p = &ma->r; float *metal_p = &ma->ray_mirror; float *spec_p = &ma->spec; @@ -1209,8 +1268,9 @@ static void material_transparent( static float half = 0.5f; /* Shading */ - *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract, - false, false, linfo->shadow_method); + *gpumat = EEVEE_material_mesh_get( + scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract, + false, false, linfo->shadow_method); switch (GPU_material_status(*gpumat)) { case GPU_MAT_SUCCESS: @@ -1251,8 +1311,11 @@ static void material_transparent( const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKSIDE) != 0); - DRWState all_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | - DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY; + DRWState all_state = ( + DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | + DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY + ); DRWState cur_state = DRW_STATE_WRITE_COLOR; cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL; @@ -1383,10 +1446,11 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld char *auto_layer_names; int *auto_layer_is_srgb; int auto_layer_count; - struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, - &auto_layer_names, - &auto_layer_is_srgb, - &auto_layer_count); + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, + &auto_layer_names, + &auto_layer_is_srgb, + &auto_layer_count); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { EEVEE_ObjectEngineData *oedata = NULL; @@ -1440,17 +1504,20 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld struct GPUMaterial *gpumat; switch (ma->blend_shadow) { case MA_BS_SOLID: - EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob); + EEVEE_lights_cache_shcaster_add( + sldata, stl, mat_geom[i], ob); *cast_shadow = true; break; case MA_BS_CLIP: gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true); - EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold); *cast_shadow = true; break; case MA_BS_HASHED: gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true); - EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, NULL); *cast_shadow = true; break; case MA_BS_NONE: @@ -1563,6 +1630,45 @@ void EEVEE_materials_cache_finish(EEVEE_Data *vedata) { EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + /* Look-Dev */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + if (v3d && v3d->drawtype == OB_MATERIAL) { + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_LampsInfo *linfo = sldata->lamps; + struct Gwn_Batch *sphere = DRW_cache_sphere_get(); + static float mat1[4][4]; + static float color[3] = {0.8f, 0.8f, 0.8f}; + static float metallic_on = 1.0f; + static float metallic_off = 0.00f; + static float specular_off = 0.5f; + static float specular_on = 1.0f; + static float roughness_off = 0.05f; + static float roughness_on = 1.00f; + + float view_mat[4][4]; + DRW_viewport_matrix_get(view_mat, DRW_MAT_VIEWINV); + + DRWShadingGroup *shgrp = EEVEE_lookdev_shading_group_get(sldata, vedata, false, linfo->shadow_method); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_on, 1); + DRW_shgroup_uniform_float(shgrp, "specular", &specular_on, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_off, 1); + unit_m4(mat1); + mul_m4_m4m4(mat1, mat1, view_mat); + translate_m4(mat1, -1.5f, 0.0f, -5.0f); + DRW_shgroup_call_add(shgrp, sphere, mat1); + + shgrp = EEVEE_lookdev_shading_group_get(sldata, vedata, false, linfo->shadow_method); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_off, 1); + DRW_shgroup_uniform_float(shgrp, "specular", &specular_off, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_on, 1); + translate_m4(mat1, 3.0f, 0.0f, 0.0f); + DRW_shgroup_call_add(shgrp, sphere, mat1); + } + /* END */ + BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN); BLI_ghash_free(stl->g_data->hair_material_hash, NULL, NULL); } @@ -1578,6 +1684,7 @@ void EEVEE_materials_free(void) DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh); DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh); DRW_SHADER_FREE_SAFE(e_data.default_background); + DRW_SHADER_FREE_SAFE(e_data.default_studiolight_background); DRW_SHADER_FREE_SAFE(e_data.update_noise_sh); DRW_TEXTURE_FREE_SAFE(e_data.util_tex); DRW_TEXTURE_FREE_SAFE(e_data.noise_tex); diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 305daef87d1..f39fbe33a71 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -77,7 +77,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_GTAO_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { const float *viewport_size = DRW_viewport_size_get(); const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; @@ -91,14 +91,14 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->ao_quality = 1.0f - scene_eval->eevee.gtao_quality; common_data->ao_settings = 1.0f; /* USE_AO */ - if (scene_eval->flag & SCE_EEVEE_GTAO_BENT_NORMALS) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BENT_NORMALS) { common_data->ao_settings += 2.0f; /* USE_BENT_NORMAL */ } - if (scene_eval->flag & SCE_EEVEE_GTAO_BOUNCE) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) { common_data->ao_settings += 4.0f; /* USE_DENOISE */ } - common_data->ao_bounce_fac = (scene_eval->flag & SCE_EEVEE_GTAO_BOUNCE) ? 1.0f : 0.0f; + common_data->ao_bounce_fac = (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) ? 1.0f : 0.0f; effects->gtao_horizons = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA8, &draw_engine_eevee_type); @@ -141,7 +141,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_GTAO_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index c95e51548d0..10a53db5e35 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -101,28 +101,29 @@ enum { /* Material shader variations */ enum { - VAR_MAT_MESH = (1 << 0), - VAR_MAT_PROBE = (1 << 1), - VAR_MAT_HAIR = (1 << 2), - VAR_MAT_FLAT = (1 << 3), - VAR_MAT_BLEND = (1 << 4), - VAR_MAT_VSM = (1 << 5), - VAR_MAT_ESM = (1 << 6), - VAR_MAT_VOLUME = (1 << 7), + VAR_MAT_MESH = (1 << 0), + VAR_MAT_PROBE = (1 << 1), + VAR_MAT_HAIR = (1 << 2), + VAR_MAT_FLAT = (1 << 3), + VAR_MAT_BLEND = (1 << 4), + VAR_MAT_VSM = (1 << 5), + VAR_MAT_ESM = (1 << 6), + VAR_MAT_VOLUME = (1 << 7), + VAR_MAT_LOOKDEV = (1 << 8), /* Max number of variation */ /* IMPORTANT : Leave it last and set * it's value accordingly. */ - VAR_MAT_MAX = (1 << 8), + VAR_MAT_MAX = (1 << 9), /* These are options that are not counted in VAR_MAT_MAX * because they are not cumulative with the others above. */ - VAR_MAT_CLIP = (1 << 9), - VAR_MAT_HASH = (1 << 10), - VAR_MAT_MULT = (1 << 11), - VAR_MAT_SHADOW = (1 << 12), - VAR_MAT_REFRACT = (1 << 13), - VAR_MAT_SSS = (1 << 14), - VAR_MAT_TRANSLUC = (1 << 15), - VAR_MAT_SSSALBED = (1 << 16), + VAR_MAT_CLIP = (1 << 10), + VAR_MAT_HASH = (1 << 11), + VAR_MAT_MULT = (1 << 12), + VAR_MAT_SHADOW = (1 << 13), + VAR_MAT_REFRACT = (1 << 14), + VAR_MAT_SSS = (1 << 15), + VAR_MAT_TRANSLUC = (1 << 16), + VAR_MAT_SSSALBED = (1 << 17), }; typedef struct EEVEE_BoundSphere { @@ -205,6 +206,7 @@ typedef struct EEVEE_PassList { struct DRWPass *transparent_pass; struct DRWPass *background_pass; struct DRWPass *update_noise_pass; + struct DRWPass *lookdev_pass; } EEVEE_PassList; typedef struct EEVEE_FramebufferList { @@ -277,6 +279,7 @@ typedef struct EEVEE_StorageList { struct EEVEE_EffectsInfo *effects; struct EEVEE_PrivateData *g_data; + } EEVEE_StorageList; /* ************ LIGHT UBO ************* */ @@ -289,6 +292,9 @@ typedef struct EEVEE_Light { float forwardvec[3], lamptype; } EEVEE_Light; +/* Special type for elliptic area lamps, matches lamps_lib.glsl */ +#define LAMPTYPE_AREA_ELLIPSE 100.0f + typedef struct EEVEE_Shadow { float near, far, bias, exp; float shadow_start, data_start, multi_shadow_count, shadow_blur; @@ -449,6 +455,8 @@ typedef struct EEVEE_LightProbesInfo { float visibility_blur; float intensity_fac; int shres; + int studiolight_index; + float studiolight_rot_z; /* List of probes in the scene. */ /* XXX This is fragile, can get out of sync quickly. */ struct Object *probes_cube_ref[MAX_PROBE]; @@ -458,7 +466,7 @@ typedef struct EEVEE_LightProbesInfo { struct EEVEE_LightProbe probe_data[MAX_PROBE]; struct EEVEE_LightGrid grid_data[MAX_GRID]; struct EEVEE_PlanarReflection planar_data[MAX_PLANAR]; - /* Probe Visibility Group */ + /* Probe Visibility Collection */ EEVEE_LightProbeVisTest vis_data; } EEVEE_LightProbesInfo; @@ -780,6 +788,8 @@ typedef struct EEVEE_PrivateData { float persmat[4][4], persinv[4][4]; float viewmat[4][4], viewinv[4][4]; float winmat[4][4], wininv[4][4]; + float studiolight_matrix[3][3]; + /* Mist Settings */ float mist_start, mist_inv_dist, mist_falloff; } EEVEE_PrivateData; /* Transient data */ @@ -806,8 +816,10 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct struct GPUMaterial *EEVEE_material_mesh_get( struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method); -struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma); -struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow); +struct GPUMaterial *EEVEE_material_mesh_volume_get( + struct Scene *scene, Material *ma); +struct GPUMaterial *EEVEE_material_mesh_depth_get( + struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow); struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method); void EEVEE_materials_free(void); void EEVEE_draw_default_passes(EEVEE_PassList *psl); @@ -924,6 +936,10 @@ void EEVEE_render_cache(void *vedata, struct Object *ob, struct RenderEngine *en void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const struct rcti *rect); void EEVEE_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); +/** eevee_lookdev.c */ +void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, DRWShadingGroup **grp, GPUShader *shader, DRWPass *pass, EEVEE_LightProbesInfo *pinfo); +void EEVEE_lookdev_draw_background(EEVEE_Data *vedata); + /* Shadow Matrix */ static const float texcomat[4][4] = { /* From NDC to TexCo */ {0.5f, 0.0f, 0.0f, 0.0f}, diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 1a46e0b5c33..6ee3b9cc286 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -150,7 +150,7 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_SSS_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) { DRW_texture_ensure_fullscreen_2D(&txl->sss_dir_accum, GPU_RGBA16F, 0); DRW_texture_ensure_fullscreen_2D(&txl->sss_col_accum, GPU_RGBA16F, 0); diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl index 55f66f5500a..9d27224b5c9 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -184,7 +184,8 @@ void integrate_slice(vec3 normal, vec2 t_phi, vec2 horizons, inout float visibil bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5); } -void gtao_deferred(vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal) +void gtao_deferred( + vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal) { /* Fetch early, hide latency! */ vec4 horizons = texelFetch(horizonBuffer, ivec2(gl_FragCoord.xy), 0); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl index d5b54097638..aad71b3e48e 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl @@ -47,6 +47,16 @@ float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector) return ltc_evaluate_quad(corners, N); } +float direct_diffuse_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector) +{ + vec3 points[3]; + points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; + points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; + points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + + return ltc_evaluate_disk(N, V, mat3(1), points); +} + float direct_diffuse_unit_disc(LightData ld, vec3 N, vec3 V) { float NL = dot(N, -ld.l_forward); @@ -107,6 +117,26 @@ vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughn return spec; } +vec3 direct_ggx_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +{ + vec3 points[3]; + points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; + points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; + points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + + vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); + vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; + vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; + mat3 ltc_mat = ltc_matrix(ltc_lut); + + float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); + bsdf *= brdf_lut.b; /* Bsdf intensity */ + + vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; + + return spec; +} + vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) { vec3 corners[4]; diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl index 6d941ae6ec3..fd1a10de548 100644 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -15,5 +15,9 @@ Closure nodetree_exec(void) Closure result = Closure(out_spec + out_diff * albedo, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0); +#ifdef LOOKDEV + gl_FragDepth = 0.0; +#endif + return result; } diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl index 90af87756f0..472d9c577b4 100644 --- a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl @@ -1,9 +1,57 @@ +#define M_PI 3.14159265358979323846 uniform float backgroundAlpha; +uniform mat4 ProjectionMatrix; +uniform mat4 ProjectionMatrixInverse; +uniform mat4 ViewMatrixInverse; +#ifdef LOOKDEV +uniform mat3 StudioLightMatrix; +uniform sampler2D image; +in vec3 viewPosition; +#else uniform vec3 color; +#endif out vec4 FragColor; +void background_transform_to_world(vec3 viewvec, out vec3 worldvec) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + worldvec = (ViewMatrixInverse * co).xyz; +} + +float hypot(float x, float y) +{ + return sqrt(x * x + y * y); +} + +void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color) +{ + vec3 nco = normalize(co); + float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; + float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; + + /* Fix pole bleeding */ + float half_width = 0.5 / float(textureSize(ima, 0).x); + v = clamp(v, half_width, 1.0 - half_width); + + /* Fix u = 0 seam */ + /* This is caused by texture filtering, since uv don't have smooth derivatives + * at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain + * texels. So we force the highest mipmap and don't do anisotropic filtering. */ + color = textureLod(ima, vec2(u, v), 0.0); +} + void main() { - FragColor = vec4(color, backgroundAlpha); +#ifdef LOOKDEV + vec3 worldvec; + vec4 color; + background_transform_to_world(viewPosition, worldvec); + node_tex_environment_equirectangular(StudioLightMatrix * worldvec, image, color); +#endif + + FragColor = vec4(clamp(color.rgb, vec3(0.0), vec3(1e10)), backgroundAlpha); } diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl index 198a05ccf97..0e6f976187a 100644 --- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl @@ -15,11 +15,13 @@ layout(std140) uniform light_block { }; /* type */ -#define POINT 0.0 -#define SUN 1.0 -#define SPOT 2.0 -#define HEMI 3.0 -#define AREA 4.0 +#define POINT 0.0 +#define SUN 1.0 +#define SPOT 2.0 +#define HEMI 3.0 +#define AREA_RECT 4.0 +/* Used to define the area lamp shape, doesn't directly correspond to a Blender lamp type. */ +#define AREA_ELLIPSE 100.0 #if defined(SHADOW_VSM) #define ShadowSample vec2 @@ -174,7 +176,7 @@ float light_visibility(LightData ld, vec3 W, vis *= spotmask; vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } @@ -253,9 +255,12 @@ float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) if (ld.l_type == SUN) { return direct_diffuse_unit_disc(ld, N, V); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT) { return direct_diffuse_rectangle(ld, N, V, l_vector); } + else if (ld.l_type == AREA_ELLIPSE) { + return direct_diffuse_ellipse(ld, N, V, l_vector); + } else { return direct_diffuse_sphere(ld, N, l_vector); } @@ -275,9 +280,12 @@ vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness if (ld.l_type == SUN) { return direct_ggx_unit_disc(ld, N, V, roughness, f0); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT) { return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0); } + else if (ld.l_type == AREA_ELLIPSE) { + return direct_ggx_ellipse(ld, N, V, l_vector, roughness, f0); + } else { return direct_ggx_sphere(ld, N, V, l_vector, roughness, f0); } @@ -373,8 +381,11 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) /* XXX : Removing Area Power. */ /* TODO : put this out of the shader. */ float falloff; - if (ld.l_type == AREA) { + if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + if (ld.l_type == AREA_ELLIPSE) { + vis *= M_PI * 0.25; + } vis *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ vis /= (l_vector.w * l_vector.w); falloff = dot(N, l_vector.xyz / l_vector.w); @@ -412,7 +423,7 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) vis *= spotmask; vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } } diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index 6c1571d5306..0ffc0cc4b49 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -120,7 +120,8 @@ float probe_attenuation_planar(PlanarData pd, vec3 W, vec3 N, float roughness) vec2 dist_to_clip; dist_to_clip.x = dot(pd.pl_clip_pos_x, W); dist_to_clip.y = dot(pd.pl_clip_pos_y, W); - fac *= step(2.0, dot(step(pd.pl_clip_edges, dist_to_clip.xxyy), vec2(-1.0, 1.0).xyxy)); /* compare and add all tests */ + /* compare and add all tests */ + fac *= step(2.0, dot(step(pd.pl_clip_edges, dist_to_clip.xxyy), vec2(-1.0, 1.0).xyxy)); /* Decrease influence for high roughness */ fac *= saturate(1.0 - roughness * 10.0); diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index aa1dda6b3b5..d035a4329b1 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -61,7 +61,8 @@ float refine_isect(float prev_delta, float curr_delta) return saturate(prev_delta / (prev_delta - curr_delta)); } -void prepare_raycast(vec3 ray_origin, vec3 ray_dir, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time) +void prepare_raycast( + vec3 ray_origin, vec3 ray_dir, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time) { /* Negate the ray direction if it goes towards the camera. * This way we don't need to care if the projected point diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl index 1a8167c2830..5f641c5d490 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl @@ -66,8 +66,11 @@ vec3 light_volume(LightData ld, vec4 l_vector) /* XXX : Removing Area Power. */ /* TODO : put this out of the shader. */ /* See eevee_light_setup(). */ - if (ld.l_type == AREA) { + if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + if (ld.l_type == AREA_ELLIPSE) { + power *= M_PI * 0.25; + } power *= 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ } else if (ld.l_type == SUN) { diff --git a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl index 19838161a73..4e44f6e1914 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl @@ -7,4 +7,4 @@ void main() } else { gl_FragDepth = 1.0; } -}
\ No newline at end of file +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index 2550f44271b..88b715f55a8 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -1,5 +1,5 @@ #define NO_OBJECT_ID uint(0) - +#define EPSILON 0.00001 /* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ #define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) const vec4 dither_mat4x4[4] = vec4[4]( @@ -62,3 +62,10 @@ void fresnel(vec3 I, vec3 N, float ior, out float kr) // As a consequence of the conservation of energy, transmittance is given by: // kt = 1 - kr; } + +vec4 calculate_transparent_accum(vec4 premultiplied) { + float a = min(1.0, premultiplied.a) * 8.0 + 0.01; + float b = -gl_FragCoord.z * 0.95 + 1.0; + float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2); + return premultiplied * w; +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl index 2d6f78082e3..12d6296655d 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl @@ -2,7 +2,9 @@ out vec4 fragColor; uniform usampler2D objectId; uniform sampler2D transparentAccum; +#ifdef WORKBENCH_REVEALAGE_ENABLED uniform sampler2D transparentRevealage; +#endif uniform vec2 invertedViewportSize; layout(std140) uniform world_block { @@ -15,7 +17,9 @@ void main() vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; uint object_id = texelFetch(objectId, texel, 0).r; vec4 transparent_accum = texelFetch(transparentAccum, texel, 0); - float revealage = texelFetch(transparentRevealage, texel, 0).r; +#ifdef WORKBENCH_REVEALAGE_ENABLED + float transparent_revealage = texelFetch(transparentRevealage, texel, 0).r; +#endif vec4 color; #ifdef V3D_SHADING_OBJECT_OUTLINE @@ -27,7 +31,11 @@ void main() if (object_id == NO_OBJECT_ID) { color = vec4(background_color(world_data, uv_viewport.y), 0.0); } else { - color = transparent_accum / transparent_accum.a; +#ifdef WORKBENCH_REVEALAGE_ENABLED + color = vec4((transparent_accum.xyz / max(transparent_accum.a, EPSILON)) * (1.0 - transparent_revealage), 1.0); +#else + color = vec4(transparent_accum.xyz / max(transparent_accum.a, EPSILON), 1.0); +#endif } fragColor = vec4(mix(world_data.object_outline_color.rgb, color.xyz, outline), 1.0); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index 6428ed44f6b..309ae063284 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -17,12 +17,7 @@ layout(std140) uniform world_block { layout(location=0) out vec4 transparentAccum; -vec4 calculate_transparent_accum(vec4 premultiplied) { - float a = min(1.0, premultiplied.a) * 8.0 + 0.01; - float b = -gl_FragCoord.z * 0.95 + 1.0; - float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2); - return vec4(premultiplied.rgb, premultiplied.a); -} + void main() { vec4 diffuse_color; @@ -47,7 +42,7 @@ void main() vec3 shaded_color = diffuse_color.rgb; #endif /* V3D_LIGHTING_STUDIO */ - float alpha = 0.1; + float alpha = 0.5 ; vec4 premultiplied = vec4(shaded_color.rgb * alpha, alpha); transparentAccum = calculate_transparent_accum(premultiplied); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl new file mode 100644 index 00000000000..da87fe8f542 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl @@ -0,0 +1,7 @@ +layout(location=0) out float transparentRevealage; + +void main() +{ + transparentRevealage = 0.5; +} + diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl index 5d286bd1090..32b31718cf8 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl @@ -4,8 +4,6 @@ #define USE_INVOC_EXT #endif -#define DOUBLE_MANIFOLD - #ifdef DOUBLE_MANIFOLD # ifdef USE_INVOC_EXT # define invoc_ct 4 diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl index ff835326236..5a31aa34932 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl @@ -4,8 +4,6 @@ #define USE_INVOC_EXT #endif -#define DOUBLE_MANIFOLD - #ifdef DOUBLE_MANIFOLD # ifdef USE_INVOC_EXT # define invoc_ct 2 diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 9f8023b38aa..bbd8c57a5b9 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -11,7 +11,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) if (v3d) { wpd->shading = v3d->shading; wpd->drawtype = v3d->drawtype; - wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light); + wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, 0); } else { memset(&wpd->shading, 0, sizeof(wpd->shading)); diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 70de6f71ae8..6a96822984d 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -49,12 +49,19 @@ // #define DEBUG_SHADOW_VOLUME +#ifdef DEBUG_SHADOW_VOLUME +# include "draw_debug.h" +#endif + static struct { struct GPUShader *prepass_sh_cache[MAX_SHADERS]; struct GPUShader *composite_sh_cache[MAX_SHADERS]; struct GPUShader *shadow_fail_sh; + struct GPUShader *shadow_fail_manifold_sh; struct GPUShader *shadow_pass_sh; + struct GPUShader *shadow_pass_manifold_sh; struct GPUShader *shadow_caps_sh; + struct GPUShader *shadow_caps_manifold_sh; struct GPUTexture *object_id_tx; /* ref only, not alloced */ struct GPUTexture *color_buffer_tx; /* ref only, not alloced */ @@ -65,7 +72,7 @@ static struct { float light_direction_vs[3]; int next_object_id; float normal_world_matrix[3][3]; -} e_data = {NULL}; +} e_data = {{NULL}}; /* Shaders */ extern char datatoc_workbench_prepass_vert_glsl[]; @@ -83,8 +90,6 @@ extern char datatoc_workbench_data_lib_glsl[]; extern char datatoc_workbench_object_outline_lib_glsl[]; extern char datatoc_workbench_world_light_lib_glsl[]; - - static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd) { char *str = NULL; @@ -123,15 +128,14 @@ static char *workbench_build_prepass_frag(void) return str; } - - static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, int drawtype) { if (e_data.prepass_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, drawtype); char *composite_frag = workbench_build_composite_frag(wpd); char *prepass_frag = workbench_build_prepass_frag(); - e_data.prepass_sh_cache[index] = DRW_shader_create(datatoc_workbench_prepass_vert_glsl, NULL, prepass_frag, defines); + e_data.prepass_sh_cache[index] = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, prepass_frag, defines); if (drawtype == OB_SOLID) { e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); } @@ -161,6 +165,7 @@ static void workbench_init_object_data(ObjectEngineData *engine_data) { WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)engine_data; data->object_id = e_data.next_object_id++; + data->shadow_bbox_dirty = true; } void workbench_deferred_engine_init(WORKBENCH_Data *vedata) @@ -174,26 +179,44 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) memset(e_data.prepass_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); e_data.next_object_id = 1; - #ifdef DEBUG_SHADOW_VOLUME - const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; - #else - const char *shadow_frag = NULL; - #endif - e_data.shadow_pass_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_PASS\n"); - e_data.shadow_fail_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_FAIL\n"); - e_data.shadow_caps_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_caps_geom_glsl, - shadow_frag, - NULL); +#ifdef DEBUG_SHADOW_VOLUME + const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; +#else + const char *shadow_frag = NULL; +#endif + e_data.shadow_pass_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_pass_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n"); + e_data.shadow_fail_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_fail_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); + e_data.shadow_caps_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_caps_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); } if (!stl->g_data) { @@ -208,12 +231,16 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R32UI, &draw_engine_workbench_solid); e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid); - e_data.composite_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); + e_data.composite_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); if (NORMAL_ENCODING_ENABLED()) { - e_data.normal_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RG16, &draw_engine_workbench_solid); - } else { - e_data.normal_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA32F, &draw_engine_workbench_solid); + e_data.normal_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RG16, &draw_engine_workbench_solid); + } + else { + e_data.normal_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA32F, &draw_engine_workbench_solid); } GPU_framebuffer_ensure_config(&fbl->prepass_fb, { @@ -242,8 +269,11 @@ void workbench_deferred_engine_free() DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); } DRW_SHADER_FREE_SAFE(e_data.shadow_pass_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_pass_manifold_sh); DRW_SHADER_FREE_SAFE(e_data.shadow_fail_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_fail_manifold_sh); DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh); } static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp) @@ -292,7 +322,8 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) e_data.display.shadow_shift = scene->display.shadow_shift; if (SHADOW_ENABLED(wpd)) { - psl->composite_pass = DRW_pass_create("Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL); + psl->composite_pass = DRW_pass_create( + "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL); grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); workbench_composite_uniforms(wpd, grp); DRW_shgroup_stencil_mask(grp, 0x00); @@ -302,23 +333,36 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + /* Stencil Shadow passes. */ #ifdef DEBUG_SHADOW_VOLUME - psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Debug Pass", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); - grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); - psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Debug Fail", DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); - grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); - psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Depth Fail Caps", DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); - grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; + DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; #else - psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Depth Pass", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS); + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS; + DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL; +#endif + psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state); + psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state); + psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Fail", depth_fail_state); + psl->shadow_depth_fail_mani_pass = DRW_pass_create("Shadow Fail Mani", depth_fail_state); + psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Fail Caps", depth_fail_state); + psl->shadow_depth_fail_caps_mani_pass = DRW_pass_create("Shadow Fail Caps Mani", depth_fail_state); + +#ifndef DEBUG_SHADOW_VOLUME + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); DRW_shgroup_stencil_mask(grp, 0xFF); - psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Depth Fail", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL); + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); DRW_shgroup_stencil_mask(grp, 0xFF); - psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Depth Fail Caps", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL); + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); psl->composite_shadow_pass = DRW_pass_create("Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL); grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass); @@ -330,16 +374,21 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); #endif + + studiolight_update_light(wpd, e_data.display.light_direction); } else { - psl->composite_pass = DRW_pass_create("Composite", DRW_STATE_WRITE_COLOR); + psl->composite_pass = DRW_pass_create( + "Composite", DRW_STATE_WRITE_COLOR); grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); workbench_composite_uniforms(wpd, grp); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } } } -static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) + +static WORKBENCH_MaterialData *get_or_create_material_data( + WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) { WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_PassList *psl = vedata->psl; @@ -359,7 +408,8 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat material = BLI_ghash_lookup(wpd->material_hash, SET_UINT_IN_POINTER(hash)); if (material == NULL) { material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); - material->shgrp = DRW_shgroup_create(drawtype == OB_SOLID ? wpd->prepass_solid_sh : wpd->prepass_texture_sh, psl->prepass_pass); + material->shgrp = DRW_shgroup_create( + drawtype == OB_SOLID ? wpd->prepass_solid_sh : wpd->prepass_texture_sh, psl->prepass_pass); DRW_shgroup_stencil_mask(material->shgrp, 0xFF); material->object_id = engine_object_data->object_id; copy_v4_v4(material->color, material_template.color); @@ -473,7 +523,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) gpumat_array[i] = NULL; } - struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, NULL, NULL, NULL); + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { Material *mat = give_current_material(ob, i + 1); @@ -485,7 +536,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) } if (SHADOW_ENABLED(wpd) && (ob->display.flag & OB_SHOW_SHADOW) > 0) { - struct Gwn_Batch *geom_shadow = DRW_cache_object_edge_detection_get(ob); + bool is_manifold; + struct Gwn_Batch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold); if (geom_shadow) { if (is_sculpt_mode) { /* Currently unsupported in sculpt mode. We could revert to the slow @@ -497,26 +549,60 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_object_engine_data_ensure( ob, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); - invert_m4_m4(ob->imat, ob->obmat); - mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); + if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) { - DRWShadingGroup *grp; - if (true) { - grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_call_object_add(grp, geom_shadow, ob); - } - else { - struct Gwn_Batch *geom_caps = DRW_cache_object_surface_get(ob); - if (geom_caps) { - grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_call_object_add(grp, geom_caps, ob); + invert_m4_m4(ob->imat, ob->obmat); + mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); + + DRWShadingGroup *grp; + bool use_shadow_pass_technique = !studiolight_camera_in_object_shadow(wpd, ob, engine_object_data); + + /* Unless we expose a parameter to the user, it's better to use the depth pass technique if the object is + * non manifold. Exposing a switch to the user to force depth fail in this case can be beneficial for + * planes and non-closed terrains. */ + if (!is_manifold) { + use_shadow_pass_technique = true; } - grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_call_object_add(grp, geom_shadow, ob); + if (use_shadow_pass_technique) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); +#ifdef DEBUG_SHADOW_VOLUME + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); +#endif + } + else { + /* TODO(fclem): only use caps if they are in the view frustum. */ + const bool need_caps = true; + if (need_caps) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat); + } + + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); +#ifdef DEBUG_SHADOW_VOLUME + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); +#endif + } } } } @@ -560,14 +646,16 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) #ifdef DEBUG_SHADOW_VOLUME GPU_framebuffer_bind(fbl->composite_fb); DRW_draw_pass(psl->composite_pass); - DRW_draw_pass(psl->shadow_depth_pass_pass); - DRW_draw_pass(psl->shadow_depth_fail_pass); - DRW_draw_pass(psl->shadow_depth_fail_caps_pass); #else GPU_framebuffer_bind(dfbl->depth_only_fb); +#endif DRW_draw_pass(psl->shadow_depth_pass_pass); + DRW_draw_pass(psl->shadow_depth_pass_mani_pass); DRW_draw_pass(psl->shadow_depth_fail_pass); + DRW_draw_pass(psl->shadow_depth_fail_mani_pass); DRW_draw_pass(psl->shadow_depth_fail_caps_pass); + DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass); +#ifndef DEBUG_SHADOW_VOLUME GPU_framebuffer_bind(fbl->composite_fb); DRW_draw_pass(psl->composite_pass); DRW_draw_pass(psl->composite_shadow_pass); diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 823ca904415..d2c262bc4ac 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -50,21 +50,28 @@ static struct { struct GPUShader *composite_sh_cache[MAX_SHADERS]; struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS]; + struct GPUShader *transparent_revealage_sh; struct GPUShader *object_outline_sh; struct GPUShader *depth_sh; struct GPUShader *checker_depth_sh; struct GPUTexture *object_id_tx; /* ref only, not alloced */ struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ +#endif struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ int next_object_id; float normal_world_matrix[3][3]; -} e_data = {NULL}; +} e_data = {{NULL}}; /* Shaders */ extern char datatoc_workbench_forward_composite_frag_glsl[]; extern char datatoc_workbench_forward_depth_frag_glsl[]; extern char datatoc_workbench_forward_transparent_accum_frag_glsl[]; +#ifdef WORKBENCH_REVEALAGE_ENABLED +extern char datatoc_workbench_forward_transparent_revealage_frag_glsl[]; +#endif extern char datatoc_workbench_data_lib_glsl[]; extern char datatoc_workbench_background_lib_glsl[]; extern char datatoc_workbench_checkerboard_depth_frag_glsl[]; @@ -104,6 +111,22 @@ static char *workbench_build_forward_transparent_accum_frag(void) return str; } +#ifdef WORKBENCH_REVEALAGE_ENABLED +static char *workbench_build_forward_transparent_revealage_frag(void) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_revealage_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} +#endif + static char *workbench_build_forward_composite_frag(void) { char *str = NULL; @@ -127,7 +150,8 @@ static void workbench_init_object_data(ObjectEngineData *engine_data) data->object_id = e_data.next_object_id++; } -static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) +static WORKBENCH_MaterialData *get_or_create_material_data( + WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) { WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_PassList *psl = vedata->psl; @@ -150,7 +174,9 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); /* transparent accum */ - grp = DRW_shgroup_create(drawtype == OB_SOLID ? wpd->transparent_accum_sh : wpd->transparent_accum_texture_sh, psl->transparent_accum_pass); + grp = DRW_shgroup_create( + drawtype == OB_SOLID ? wpd->transparent_accum_sh : wpd->transparent_accum_texture_sh, + psl->transparent_accum_pass); DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); copy_v4_v4(material->color, material_template.color); @@ -190,7 +216,8 @@ static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, int dr if (e_data.transparent_accum_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, drawtype); char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); - e_data.transparent_accum_sh_cache[index] = DRW_shader_create(datatoc_workbench_prepass_vert_glsl, NULL, transparent_accum_frag, defines); + e_data.transparent_accum_sh_cache[index] = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, transparent_accum_frag, defines); MEM_freeN(transparent_accum_frag); MEM_freeN(defines); @@ -231,12 +258,21 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); - /* XXX: forward depth does not use any defines ATM. */ char *defines = workbench_material_build_defines(wpd, OB_SOLID); char *forward_depth_frag = workbench_build_forward_depth_frag(); - e_data.object_outline_sh = DRW_shader_create(datatoc_workbench_prepass_vert_glsl, NULL, forward_depth_frag, defines); + e_data.object_outline_sh = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, forward_depth_frag, defines); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + char *forward_transparent_revealage_frag = workbench_build_forward_transparent_revealage_frag(); + e_data.transparent_revealage_sh = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, forward_transparent_revealage_frag, defines); + MEM_freeN(forward_transparent_revealage_frag); +#endif + e_data.depth_sh = DRW_shader_create_3D_depth_only(); - e_data.checker_depth_sh = DRW_shader_create_fullscreen(datatoc_workbench_checkerboard_depth_frag_glsl, NULL); + e_data.checker_depth_sh = DRW_shader_create_fullscreen( + datatoc_workbench_checkerboard_depth_frag_glsl, NULL); MEM_freeN(forward_depth_frag); MEM_freeN(defines); } @@ -245,9 +281,16 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) const float *viewport_size = DRW_viewport_size_get(); const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); - e_data.transparent_accum_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); - e_data.composite_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); + e_data.object_id_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); + e_data.transparent_accum_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); +#ifdef WORKBENCH_REVEALAGE_ENABLED + e_data.transparent_revealage_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent); +#endif + e_data.composite_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); GPU_framebuffer_ensure_config(&fbl->object_outline_fb, { GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), @@ -256,6 +299,14 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), }); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + GPU_framebuffer_ensure_config(&fbl->transparent_revealage_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx), + }); +#endif + GPU_framebuffer_ensure_config(&fbl->composite_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), @@ -264,6 +315,12 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) DRW_stats_group_start("Clear Buffers"); GPU_framebuffer_bind(fbl->transparent_accum_fb); GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + const float clear_color1[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + GPU_framebuffer_bind(fbl->transparent_revealage_fb); + GPU_framebuffer_clear_color(fbl->transparent_revealage_fb, clear_color1); +#endif GPU_framebuffer_bind(fbl->object_outline_fb); GPU_framebuffer_clear_color_depth(fbl->object_outline_fb, clear_color, 1.0f); DRW_stats_group_end(); @@ -273,6 +330,17 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) int state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL; psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); } + +#ifdef WORKBENCH_REVEALAGE_ENABLED + /* Treansparecy Revealage */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSPARENT_REVEALAGE; + psl->transparent_revealage_pass = DRW_pass_create("Transparent Revealage", state); + grp = DRW_shgroup_create(e_data.transparent_revealage_sh, psl->transparent_revealage_pass); + wpd->transparent_revealage_shgrp = grp; + } +#endif + /* Depth */ { int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; @@ -286,6 +354,9 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.transparent_accum_tx); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx); +#endif DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); @@ -305,6 +376,9 @@ void workbench_forward_engine_free() DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]); } +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_SHADER_FREE_SAFE(e_data.transparent_revealage_sh); +#endif DRW_SHADER_FREE_SAFE(e_data.object_outline_sh); DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh); } @@ -315,6 +389,10 @@ void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata)) static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, Object *ob) { +#ifdef WORKBENCH_REVEALAGE_ENABLED + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; +#endif const DRWContextState *draw_ctx = DRW_context_state_get(); if (ob == draw_ctx->object_edit) { return; @@ -335,6 +413,9 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O if (draw_as == PART_DRAW_PATH) { struct Gwn_Batch *geom = DRW_cache_particles_get_hair(ob, psys, NULL); WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, NULL, NULL, OB_SOLID); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_add(wpd->transparent_revealage_shgrp, geom, mat); +#endif DRW_shgroup_call_add(material->shgrp_object_outline, geom, mat); DRW_shgroup_call_add(material->shgrp, geom, mat); } @@ -376,6 +457,9 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) mat_drawtype = OB_TEXTURE; } material = get_or_create_material_data(vedata, ob, mat, image, mat_drawtype); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom_array[i], ob); +#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); } @@ -391,10 +475,16 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); if (geom) { if (is_sculpt_mode) { +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_sculpt_add(wpd->transparent_revealage_shgrp, ob, ob->obmat); +#endif DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); } else { +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom, ob); +#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob); DRW_shgroup_call_object_add(material->shgrp, geom, ob); } @@ -407,11 +497,15 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) gpumat_array[i] = NULL; } - struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, NULL, NULL, NULL); + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { Material *mat = give_current_material(ob, i + 1); material = get_or_create_material_data(vedata, ob, mat, NULL, OB_SOLID); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, mat_geom[i], ob); +#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); } @@ -450,7 +544,10 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata) /* Shade */ GPU_framebuffer_bind(fbl->transparent_accum_fb); DRW_draw_pass(psl->transparent_accum_pass); - +#ifdef WORKBENCH_REVEALAGE_ENABLED + GPU_framebuffer_bind(fbl->transparent_revealage_fb); + DRW_draw_pass(psl->transparent_revealage_pass); +#endif /* Composite */ GPU_framebuffer_bind(fbl->composite_fb); DRW_draw_pass(psl->composite_pass); diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 9b364d8ff09..6028d3816d4 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -77,6 +77,10 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype) BLI_dynstr_appendf(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); } +#ifdef WORKBENCH_REVEALAGE_ENABLED + BLI_dynstr_appendf(ds, "#define WORKBENCH_REVEALAGE_ENABLED\n"); +#endif + str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); return str; @@ -117,7 +121,8 @@ int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype return index; } -void workbench_material_set_normal_world_matrix(DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]) +void workbench_material_set_normal_world_matrix( + DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]) { if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) { float view_matrix_inverse[4][4]; diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 087ed5100d9..bffac99c6d7 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -44,6 +44,7 @@ #define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW) #define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (wpd->shading.light & V3D_LIGHTING_STUDIO || SHADOW_ENABLED(wpd)) #define NORMAL_ENCODING_ENABLED() (true) +#define WORKBENCH_REVEALAGE_ENABLED #define STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd) (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD) @@ -55,6 +56,10 @@ typedef struct WORKBENCH_FramebufferList { /* Forward render buffers */ struct GPUFrameBuffer *object_outline_fb; struct GPUFrameBuffer *transparent_accum_fb; + +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct GPUFrameBuffer *transparent_revealage_fb; +#endif } WORKBENCH_FramebufferList; typedef struct WORKBENCH_StorageList { @@ -65,13 +70,19 @@ typedef struct WORKBENCH_PassList { /* deferred rendering */ struct DRWPass *prepass_pass; struct DRWPass *shadow_depth_pass_pass; + struct DRWPass *shadow_depth_pass_mani_pass; struct DRWPass *shadow_depth_fail_pass; + struct DRWPass *shadow_depth_fail_mani_pass; struct DRWPass *shadow_depth_fail_caps_pass; + struct DRWPass *shadow_depth_fail_caps_mani_pass; struct DRWPass *composite_pass; struct DRWPass *composite_shadow_pass; /* forward rendering */ struct DRWPass *transparent_accum_pass; +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct DRWPass *transparent_revealage_pass; +#endif struct DRWPass *object_outline_pass; struct DRWPass *depth_pass; struct DRWPass *checker_depth_pass; @@ -111,8 +122,19 @@ typedef struct WORKBENCH_PrivateData { struct GPUUniformBuffer *world_ubo; struct DRWShadingGroup *shadow_shgrp; struct DRWShadingGroup *depth_shgrp; +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct DRWShadingGroup *transparent_revealage_shgrp; +#endif WORKBENCH_UBO_World world_data; float shadow_multiplier; + float cached_shadow_direction[3]; + float shadow_mat[4][4]; + float shadow_inv[4][4]; + float shadow_near_corners[4][3]; /* Near plane corners in shadow space. */ + float shadow_near_min[3]; /* min and max of shadow_near_corners. allow fast test */ + float shadow_near_max[3]; + float shadow_near_sides[2][4]; /* This is a parallelogram, so only 2 normal and distance to the edges. */ + bool shadow_changed; } WORKBENCH_PrivateData; /* Transient data */ typedef struct WORKBENCH_MaterialData { @@ -137,6 +159,9 @@ typedef struct WORKBENCH_ObjectData { int recalc; /* Shadow direction in local object space. */ float shadow_dir[3]; + float shadow_min[3], shadow_max[3]; /* Min, max in shadow space */ + BoundBox shadow_bbox; + bool shadow_bbox_dirty; int object_id; } WORKBENCH_ObjectData; @@ -172,10 +197,14 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype) void workbench_material_get_solid_color(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, float *color); uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template); int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype); -void workbench_material_set_normal_world_matrix(DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]); +void workbench_material_set_normal_world_matrix( + DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]); /* workbench_studiolight.c */ void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd); +void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]); +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); /* workbench_data.c */ void workbench_private_data_init(WORKBENCH_PrivateData *wpd); diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c index 2142be3eaf4..4db89717b2a 100644 --- a/source/blender/draw/engines/workbench/workbench_studiolight.c +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -27,7 +27,10 @@ #include "DRW_engine.h" #include "workbench_private.h" +#include "BKE_object.h" + #include "BLI_math.h" +#include "BKE_global.h" void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd) { @@ -40,3 +43,139 @@ void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd) copy_v3_v3(wd->diffuse_light_z_pos, sl->diffuse_light[STUDIOLIGHT_Z_POS]); copy_v3_v3(wd->diffuse_light_z_neg, sl->diffuse_light[STUDIOLIGHT_Z_NEG]); } + +static void compute_parallel_lines_nor_and_dist(const float v1[2], const float v2[2], const float v3[2], float r_line[2]) +{ + sub_v2_v2v2(r_line, v2, v1); + /* Find orthogonal vector. */ + SWAP(float, r_line[0], r_line[1]); + r_line[0] = -r_line[0]; + /* Edge distances. */ + r_line[2] = dot_v2v2(r_line, v1); + r_line[3] = dot_v2v2(r_line, v3); + /* Make sure r_line[2] is the minimum. */ + if (r_line[2] > r_line[3]) { + SWAP(float, r_line[2], r_line[3]); + } +} + +void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]) +{ + wpd->shadow_changed = !compare_v3v3(wpd->cached_shadow_direction, light_direction, 1e-5f); + + if (wpd->shadow_changed) { + float up[3] = {0.0f, 0.0f, 1.0f}; + unit_m4(wpd->shadow_mat); + + /* TODO fix singularity. */ + copy_v3_v3(wpd->shadow_mat[2], light_direction); + cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up); + normalize_v3(wpd->shadow_mat[0]); + cross_v3_v3v3(wpd->shadow_mat[1], wpd->shadow_mat[2], wpd->shadow_mat[0]); + + invert_m4_m4(wpd->shadow_inv, wpd->shadow_mat); + + copy_v3_v3(wpd->cached_shadow_direction, light_direction); + + } + + BoundBox frustum_corners; + DRW_culling_frustum_corners_get(&frustum_corners); + + mul_v3_mat3_m4v3(wpd->shadow_near_corners[0], wpd->shadow_inv, frustum_corners.vec[0]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[1], wpd->shadow_inv, frustum_corners.vec[3]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[2], wpd->shadow_inv, frustum_corners.vec[7]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[3], wpd->shadow_inv, frustum_corners.vec[4]); + + INIT_MINMAX(wpd->shadow_near_min, wpd->shadow_near_max); + for (int i = 0; i < 4; ++i) { + minmax_v3v3_v3(wpd->shadow_near_min, wpd->shadow_near_max, wpd->shadow_near_corners[i]); + } + + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[0], wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_sides[0]); + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_corners[0], wpd->shadow_near_sides[1]); +} + +static BoundBox *studiolight_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + if ((oed->shadow_bbox_dirty) || (wpd->shadow_changed)) { + float tmp_mat[4][4]; + mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->obmat); + + /* Get AABB in shadow space. */ + INIT_MINMAX(oed->shadow_min, oed->shadow_max); + + /* From object space to shadow space */ + BoundBox *bbox = BKE_object_boundbox_get(ob); + for (int i = 0; i < 8; ++i) { + float corner[3]; + mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]); + minmax_v3v3_v3(oed->shadow_min, oed->shadow_max, corner); + } + /* Extend towards infinity. */ + oed->shadow_max[2] += 1e4; + + /* Get extended AABB in world space. */ + BKE_boundbox_init_from_minmax(&oed->shadow_bbox, oed->shadow_min, oed->shadow_max); + for (int i = 0; i < 8; ++i) { + mul_m4_v3(wpd->shadow_mat, oed->shadow_bbox.vec[i]); + } + } + + return &oed->shadow_bbox; +} + +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); + return DRW_culling_box_test(shadow_bbox); +} + +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + /* Just to be sure the min, max are updated. */ + studiolight_object_shadow_bbox_get(wpd, ob, oed); + + /* Test if near plane is in front of the shadow. */ + if (oed->shadow_min[2] > wpd->shadow_near_max[2]) { + return false; + } + + /* Separation Axis Theorem test */ + + /* Test bbox sides first (faster) */ + if ((oed->shadow_min[0] > wpd->shadow_near_max[0]) || + (oed->shadow_max[0] < wpd->shadow_near_min[0]) || + (oed->shadow_min[1] > wpd->shadow_near_max[1]) || + (oed->shadow_max[1] < wpd->shadow_near_min[1])) + { + return false; + } + + /* Test projected near rectangle sides */ + float pts[4][2] = { + {oed->shadow_min[0], oed->shadow_min[1]}, + {oed->shadow_min[0], oed->shadow_max[1]}, + {oed->shadow_max[0], oed->shadow_min[1]}, + {oed->shadow_max[0], oed->shadow_max[1]} + }; + + for (int i = 0; i < 2; ++i) { + float min_dst = FLT_MAX, max_dst = -FLT_MAX; + for (int j = 0; j < 4; ++j) { + float dst = dot_v2v2(wpd->shadow_near_sides[i], pts[j]); + /* Do min max */ + if (min_dst > dst) min_dst = dst; + if (max_dst < dst) max_dst = dst; + } + + if ((wpd->shadow_near_sides[i][2] > max_dst) || + (wpd->shadow_near_sides[i][3] < min_dst)) + { + return false; + } + } + + /* No separation axis found. Both shape intersect. */ + return true; +} diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 8af3e6c7859..25806062f68 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -152,7 +152,9 @@ typedef struct DrawEngineType { void (*view_update)(void *vedata); void (*id_update)(void *vedata, struct ID *id); - void (*render_to_image)(void *vedata, struct RenderEngine *engine, struct RenderLayer *layer, const struct rcti *rect); + void (*render_to_image)( + void *vedata, struct RenderEngine *engine, + struct RenderLayer *layer, const struct rcti *rect); } DrawEngineType; #ifndef __DRW_ENGINE_H__ @@ -280,6 +282,7 @@ typedef enum { DRW_STATE_BLEND_PREMUL = (1 << 21), /* Use that if color is already premult by alpha. */ DRW_STATE_WIRE_SMOOTH = (1 << 22), DRW_STATE_TRANS_FEEDBACK = (1 << 23), + DRW_STATE_TRANSPARENT_REVEALAGE = (1 << 24), DRW_STATE_WRITE_STENCIL = (1 << 27), DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 28), @@ -317,10 +320,14 @@ DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial DRWShadingGroup *DRW_shgroup_instance_create( struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom, struct Gwn_VertFormat *format); DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass); -DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(struct GPUShader *shader, DRWPass *pass, struct Gwn_VertFormat *format); -DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass); -DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size); -DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, struct Gwn_VertBuf *tf_target); +DRWShadingGroup *DRW_shgroup_line_batch_create_with_format( + struct GPUShader *shader, DRWPass *pass, struct Gwn_VertFormat *format); +DRWShadingGroup *DRW_shgroup_line_batch_create( + struct GPUShader *shader, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_empty_tri_batch_create( + struct GPUShader *shader, DRWPass *pass, int size); +DRWShadingGroup *DRW_shgroup_transform_feedback_create( + struct GPUShader *shader, DRWPass *pass, struct Gwn_VertBuf *tf_target); typedef void (DRWCallGenerateFn)( DRWShadingGroup *shgroup, @@ -439,8 +446,10 @@ void DRW_render_instance_buffer_finish(void); /* ViewLayers */ void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type); -void **DRW_view_layer_engine_data_ensure_ex(struct ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)); -void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage)); +void **DRW_view_layer_engine_data_ensure_ex( + struct ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)); +void **DRW_view_layer_engine_data_ensure( + DrawEngineType *engine_type, void (*callback)(void *storage)); /* Objects */ ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type); @@ -488,6 +497,8 @@ bool DRW_culling_sphere_test(BoundSphere *bsphere); bool DRW_culling_box_test(BoundBox *bbox); bool DRW_culling_plane_test(float plane[4]); +void DRW_culling_frustum_corners_get(BoundBox *corners); + /* Selection */ void DRW_select_load_id(uint id); diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index ed2b52700d9..ed9bb6f8ca9 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -134,7 +134,7 @@ static void drw_shgroup_bone_octahedral( const float bone_color[4], const float hint_color[4], const float outline_color[4]) { if (g_data.bone_octahedral_outline == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get(); + struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_get(); g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); } if (g_data.bone_octahedral_solid == NULL) { @@ -155,7 +155,7 @@ static void drw_shgroup_bone_box( const float bone_color[4], const float hint_color[4], const float outline_color[4]) { if (g_data.bone_box_wire == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_box_get(); + struct Gwn_Batch *geom = DRW_cache_bone_box_wire_get(); g_data.bone_box_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); } if (g_data.bone_box_solid == NULL) { @@ -313,19 +313,32 @@ static void drw_shgroup_bone_envelope( /* Custom (geometry) */ -static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const float color[4], Object *custom) +static void drw_shgroup_bone_custom_solid( + const float (*bone_mat)[4], + const float bone_color[4], const float hint_color[4], const float outline_color[4], + Object *custom) { /* grr, not re-using instances! */ struct Gwn_Batch *geom = DRW_cache_object_surface_get(custom); if (geom) { - DRWShadingGroup *shgrp_geom_solid = shgroup_instance_solid(g_data.passes.bone_solid, geom); + DRWShadingGroup *shgrp_geom_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom); + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color); + } + + geom = DRW_cache_object_edge_detection_get(custom, NULL); + if (geom && outline_color[3] > 0.0f) { + DRWShadingGroup *shgrp_geom_wire = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); - DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, color); + DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, outline_color); } } -static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float color[4], Object *custom) +static void drw_shgroup_bone_custom_wire( + const float (*bone_mat)[4], + const float color[4], Object *custom) { /* grr, not re-using instances! */ struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom); @@ -373,7 +386,8 @@ static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[ static void drw_shgroup_bone_relationship_lines(const float start[3], const float end[3]) { if (g_data.lines_relationship == NULL) { - g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, g_theme.wire_color); + g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color( + g_data.passes.relationship_lines, g_theme.wire_color); } /* reverse order to have less stipple overlap */ float v[3]; @@ -956,7 +970,8 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S size_to_mat4(bscalemat, bscale); - /* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */ + /* Note: don't multiply by inverse scale mat here, + * as it causes problems with scaling shearing and breaking segment chains */ mul_m4_series(result_array[a], result_array[a], bscalemat); } } @@ -1055,7 +1070,8 @@ static void draw_axes(EditBone *eBone, bPoseChannel *pchan) const float *col = (g_theme.const_color) ? g_theme.const_color : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? g_theme.text_hi_color : g_theme.text_color; copy_v4_v4(final_col, col); - final_col[3] = (g_theme.const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.3 : 0.8; /* Mix with axes color. */ + /* Mix with axes color. */ + final_col[3] = (g_theme.const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.3 : 0.8; drw_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_mat), final_col); } @@ -1107,8 +1123,9 @@ static void draw_points( if (eBone) { if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) { if (is_envelope_draw) { - drw_shgroup_bone_envelope(eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root, - &eBone->rad_head, &envelope_ignore); + drw_shgroup_bone_envelope( + eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root, + &eBone->rad_head, &envelope_ignore); } else { drw_shgroup_bone_point(eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root); @@ -1119,8 +1136,9 @@ static void draw_points( Bone *bone = pchan->bone; if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) { if (is_envelope_draw) { - drw_shgroup_bone_envelope(pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root, - &bone->rad_head, &envelope_ignore); + drw_shgroup_bone_envelope( + pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root, + &bone->rad_head, &envelope_ignore); } else { drw_shgroup_bone_point(pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root); @@ -1137,7 +1155,8 @@ static void draw_points( if (is_envelope_draw) { const float *rad_tail = eBone ? &eBone->rad_tail : &pchan->bone->rad_tail; drw_shgroup_bone_envelope( - BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, col_hint_tail, col_wire_tail, &envelope_ignore, rad_tail); + BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, col_hint_tail, col_wire_tail, + &envelope_ignore, rad_tail); } else { drw_shgroup_bone_point(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail, col_hint_tail, col_wire_tail); @@ -1163,6 +1182,7 @@ static void draw_bone_custom_shape( { const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag); const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag); const float (*disp_mat)[4] = pchan->disp_mat; if (select_id != -1) { @@ -1170,9 +1190,11 @@ static void draw_bone_custom_shape( } if ((boneflag & BONE_DRAWWIRE) == 0) { - drw_shgroup_bone_custom_solid(disp_mat, col_solid, pchan->custom); + drw_shgroup_bone_custom_solid(disp_mat, col_solid, col_hint, col_wire, pchan->custom); + } + else { + drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom); } - drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom); if (select_id != -1) { DRW_select_load_id(-1); @@ -1211,7 +1233,9 @@ static void draw_bone_envelope( DRW_select_load_id(select_id | BONESEL_BONE); } - drw_shgroup_bone_envelope(BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire, rad_head, rad_tail); + drw_shgroup_bone_envelope( + BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire, + rad_head, rad_tail); if (select_id != -1) { DRW_select_load_id(-1); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 6065e7f0fc5..b08735860c9 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -72,7 +72,8 @@ static struct DRWShapeCache { Gwn_Batch *drw_lamp; Gwn_Batch *drw_lamp_shadows; Gwn_Batch *drw_lamp_sunrays; - Gwn_Batch *drw_lamp_area; + Gwn_Batch *drw_lamp_area_square; + Gwn_Batch *drw_lamp_area_disk; Gwn_Batch *drw_lamp_hemi; Gwn_Batch *drw_lamp_spot; Gwn_Batch *drw_lamp_spot_square; @@ -502,11 +503,11 @@ Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob) } /* Returns a buffer texture. */ -Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob) +Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold) { switch (ob->type) { case OB_MESH: - return DRW_cache_mesh_edge_detection_get(ob); + return DRW_cache_mesh_edge_detection_get(ob, r_is_manifold); /* TODO, should match 'DRW_cache_object_surface_get' */ default: @@ -1122,9 +1123,9 @@ Gwn_Batch *DRW_cache_lamp_sunrays_get(void) return SHC.drw_lamp_sunrays; } -Gwn_Batch *DRW_cache_lamp_area_get(void) +Gwn_Batch *DRW_cache_lamp_area_square_get(void) { - if (!SHC.drw_lamp_area) { + if (!SHC.drw_lamp_area_square) { float v1[3] = {0.0f, 0.0f, 0.0f}; /* Position Only 3D format */ @@ -1151,9 +1152,40 @@ Gwn_Batch *DRW_cache_lamp_area_get(void) v1[1] = 0.5f; GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v1); - SHC.drw_lamp_area = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + SHC.drw_lamp_area_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); } - return SHC.drw_lamp_area; + return SHC.drw_lamp_area_square; +} + +Gwn_Batch *DRW_cache_lamp_area_disk_get(void) +{ +#define NSEGMENTS 32 + if (!SHC.drw_lamp_area_disk) { + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 2 * NSEGMENTS); + + float v[3] = {0.0f, 0.5f, 0.0f}; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v); + for (int a = 1; a < NSEGMENTS; a++) { + v[0] = 0.5f * sinf(2.0f * (float)M_PI * a / NSEGMENTS); + v[1] = 0.5f * cosf(2.0f * (float)M_PI * a / NSEGMENTS); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a - 1, v); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a, v); + } + copy_v3_fl3(v, 0.0f, 0.5f, 0.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, (2 * NSEGMENTS) - 1, v); + + SHC.drw_lamp_area_disk = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_area_disk; +#undef NSEGMENTS } Gwn_Batch *DRW_cache_lamp_hemi_get(void) @@ -1562,6 +1594,7 @@ static const float bone_octahedral_smooth_normals[6][3] = { }; #if 0 /* UNUSED */ + static const uint bone_octahedral_wire[24] = { 0, 1, 1, 5, 5, 3, 3, 0, 0, 4, 4, 5, 5, 2, 2, 0, @@ -1600,6 +1633,13 @@ static const uint bone_octahedral_solid_tris[8][3] = { * the first vertex of the first face aka. vertex 2): * {0, 12, 1, 10, 2, 3} **/ +static const uint bone_octahedral_wire_lines_adjacency[12][4] = { + { 0, 1, 2, 6}, { 0, 12, 1, 6}, { 0, 3, 12, 6}, { 0, 2, 3, 6}, + { 1, 6, 2, 3}, { 1, 12, 6, 3}, { 1, 0, 12, 3}, { 1, 2, 0, 3}, + { 2, 0, 1, 12}, { 2, 3, 0, 12}, { 2, 6, 3, 12}, { 2, 1, 6, 12}, +}; + +#if 0 /* UNUSED */ static const uint bone_octahedral_solid_tris_adjacency[8][6] = { { 0, 12, 1, 10, 2, 3}, { 3, 15, 4, 1, 5, 6}, @@ -1611,6 +1651,7 @@ static const uint bone_octahedral_solid_tris_adjacency[8][6] = { {18, 16, 19, 8, 20, 23}, {21, 19, 22, 11, 23, 14}, }; +#endif /* aligned with bone_octahedral_solid_tris */ static const float bone_octahedral_solid_normals[8][3] = { @@ -1641,30 +1682,43 @@ Gwn_Batch *DRW_cache_bone_octahedral_get(void) Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); GWN_vertbuf_data_alloc(vbo, 24); - Gwn_IndexBufBuilder elb; - GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRIS_ADJ, 6 * 8, 24, false); - for (int i = 0; i < 8; i++) { - GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); - GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][0]]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]); - GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); - GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][1]]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]); - GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); - GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][2]]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]); - for (int j = 0; j < 6; ++j) { - GWN_indexbuf_add_generic_vert(&elb, bone_octahedral_solid_tris_adjacency[i][j]); + for (int j = 0; j < 3; ++j) { + GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); + GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][j]]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]); } } - SHC.drw_bone_octahedral = GWN_batch_create_ex(GWN_PRIM_TRIS_ADJ, vbo, GWN_indexbuf_build(&elb), - GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + SHC.drw_bone_octahedral = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, + GWN_BATCH_OWNS_VBO); } return SHC.drw_bone_octahedral; } +Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void) +{ + if (!SHC.drw_bone_octahedral_wire) { + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 24); + + for (int i = 0; i < 12; i++) { + GWN_indexbuf_add_line_adj_verts(&elb, + bone_octahedral_wire_lines_adjacency[i][0], + bone_octahedral_wire_lines_adjacency[i][1], + bone_octahedral_wire_lines_adjacency[i][2], + bone_octahedral_wire_lines_adjacency[i][3]); + } + + /* HACK Reuse vertex buffer. */ + Gwn_Batch *pos_nor_batch = DRW_cache_bone_octahedral_get(); + + SHC.drw_bone_octahedral_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb), + GWN_BATCH_OWNS_INDEX); + } + return SHC.drw_bone_octahedral_wire; +} + /* XXX TODO move that 1 unit cube to more common/generic place? */ static const float bone_box_verts[8][3] = { { 1.0f, 0.0f, 1.0f}, @@ -1728,6 +1782,13 @@ static const uint bone_box_solid_tris[12][3] = { * Store indices of generated verts from bone_box_solid_tris to define adjacency infos. * See bone_octahedral_solid_tris for more infos. **/ +static const uint bone_box_wire_lines_adjacency[12][4] = { + { 4, 2, 0, 11}, { 0, 1, 2, 8}, { 2, 4, 1, 14}, { 1, 0, 4, 20}, /* bottom */ + { 0, 8, 11, 14}, { 2, 14, 8, 20}, { 1, 20, 14, 11}, { 4, 11, 20, 8}, /* top */ + { 20, 0, 11, 2}, { 11, 2, 8, 1}, { 8, 1, 14, 4}, { 14, 4, 20, 0}, /* sides */ +}; + +#if 0 /* UNUSED */ static const uint bone_box_solid_tris_adjacency[12][6] = { { 0, 5, 1, 14, 2, 8}, { 3, 26, 4, 20, 5, 1}, @@ -1747,6 +1808,7 @@ static const uint bone_box_solid_tris_adjacency[12][6] = { {30, 9, 31, 15, 32, 35}, {33, 31, 34, 21, 35, 27}, }; +#endif /* aligned with bone_box_solid_tris */ static const float bone_box_solid_normals[12][3] = { @@ -1786,26 +1848,43 @@ Gwn_Batch *DRW_cache_bone_box_get(void) Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); GWN_vertbuf_data_alloc(vbo, 36); - Gwn_IndexBufBuilder elb; - GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRIS_ADJ, 6 * 12, 36, false); - for (int i = 0; i < 12; i++) { for (int j = 0; j < 3; j++) { GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]); GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_box_smooth_normals[bone_box_solid_tris[i][j]]); GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]); } - for (int j = 0; j < 6; ++j) { - GWN_indexbuf_add_generic_vert(&elb, bone_box_solid_tris_adjacency[i][j]); - } } - SHC.drw_bone_box = GWN_batch_create_ex(GWN_PRIM_TRIS_ADJ, vbo, GWN_indexbuf_build(&elb), - GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + SHC.drw_bone_box = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, + GWN_BATCH_OWNS_VBO); } return SHC.drw_bone_box; } +Gwn_Batch *DRW_cache_bone_box_wire_get(void) +{ + if (!SHC.drw_bone_box_wire) { + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 36); + + for (int i = 0; i < 12; i++) { + GWN_indexbuf_add_line_adj_verts(&elb, + bone_box_wire_lines_adjacency[i][0], + bone_box_wire_lines_adjacency[i][1], + bone_box_wire_lines_adjacency[i][2], + bone_box_wire_lines_adjacency[i][3]); + } + + /* HACK Reuse vertex buffer. */ + Gwn_Batch *pos_nor_batch = DRW_cache_bone_box_get(); + + SHC.drw_bone_box_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb), + GWN_BATCH_OWNS_INDEX); + } + return SHC.drw_bone_box_wire; +} + /* Helpers for envelope bone's solid sphere-with-hidden-equatorial-cylinder. * Note that here we only encode head/tail in forth component of the vector. */ static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3]) @@ -2014,9 +2093,9 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void) for (int a = 0; a < CIRCLE_RESOL; a++) { v1[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); v1[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); - GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); - GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); copy_v2_v2(v0, v1); } @@ -2506,12 +2585,12 @@ Gwn_Batch *DRW_cache_mesh_wire_outline_get(Object *ob) return DRW_mesh_batch_cache_get_fancy_edges(me); } -Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob) +Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold) { BLI_assert(ob->type == OB_MESH); Mesh *me = ob->data; - return DRW_mesh_batch_cache_get_edge_detection(me); + return DRW_mesh_batch_cache_get_edge_detection(me, r_is_manifold); } Gwn_Batch *DRW_cache_mesh_surface_get(Object *ob) diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 8bc609ffe1f..1fd6b22c221 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -48,7 +48,7 @@ struct Gwn_Batch *DRW_cache_screenspace_circle_get(void); /* Common Object */ struct Gwn_Batch *DRW_cache_object_wire_outline_get(struct Object *ob); -struct Gwn_Batch *DRW_cache_object_edge_detection_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_object_edge_detection_get(struct Object *ob, bool *r_is_manifold); struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob); struct Gwn_Batch **DRW_cache_object_surface_material_get( struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, @@ -78,7 +78,8 @@ struct Gwn_Batch *DRW_cache_field_cone_limit_get(void); struct Gwn_Batch *DRW_cache_lamp_get(void); struct Gwn_Batch *DRW_cache_lamp_shadows_get(void); struct Gwn_Batch *DRW_cache_lamp_sunrays_get(void); -struct Gwn_Batch *DRW_cache_lamp_area_get(void); +struct Gwn_Batch *DRW_cache_lamp_area_square_get(void); +struct Gwn_Batch *DRW_cache_lamp_area_disk_get(void); struct Gwn_Batch *DRW_cache_lamp_hemi_get(void); struct Gwn_Batch *DRW_cache_lamp_spot_get(void); struct Gwn_Batch *DRW_cache_lamp_spot_square_get(void); @@ -98,7 +99,9 @@ struct Gwn_Batch *DRW_cache_lightprobe_planar_get(void); /* Bones */ struct Gwn_Batch *DRW_cache_bone_octahedral_get(void); +struct Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void); struct Gwn_Batch *DRW_cache_bone_box_get(void); +struct Gwn_Batch *DRW_cache_bone_box_wire_get(void); struct Gwn_Batch *DRW_cache_bone_envelope_solid_get(void); struct Gwn_Batch *DRW_cache_bone_envelope_outline_get(void); struct Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void); @@ -117,7 +120,7 @@ void DRW_cache_mesh_normals_overlay_get( struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts); struct Gwn_Batch *DRW_cache_face_centers_get(struct Object *ob); struct Gwn_Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob); -struct Gwn_Batch *DRW_cache_mesh_edge_detection_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold); struct Gwn_Batch *DRW_cache_mesh_surface_get(struct Object *ob); struct Gwn_Batch *DRW_cache_mesh_surface_weights_get(struct Object *ob); struct Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob); @@ -166,11 +169,16 @@ struct Gwn_Batch *DRW_cache_lattice_wire_get(struct Object *ob, bool use_weight) struct Gwn_Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob); /* Particles */ -struct Gwn_Batch *DRW_cache_particles_get_hair(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); -struct Gwn_Batch *DRW_cache_particles_get_dots(struct Object *object, struct ParticleSystem *psys); -struct Gwn_Batch *DRW_cache_particles_get_edit_strands(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_cache_particles_get_edit_inner_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_cache_particles_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_hair( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); +struct Gwn_Batch *DRW_cache_particles_get_dots( + struct Object *object, struct ParticleSystem *psys); +struct Gwn_Batch *DRW_cache_particles_get_edit_strands( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_edit_inner_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_edit_tip_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); struct Gwn_Batch *DRW_cache_particles_get_prim(int type); /* Metaball */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 3ca53b92946..f77dafc9b31 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -64,7 +64,8 @@ struct Gwn_Batch *DRW_curve_batch_cache_get_normal_edge( struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu); struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu); -struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu, struct CurveCache *ob_curve_cache); +struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals( + struct Curve *cu, struct CurveCache *ob_curve_cache); struct Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded( struct Curve *cu, struct CurveCache *ob_curve_cache, struct GPUMaterial **gpumat_array, uint gpumat_array_len); @@ -109,7 +110,7 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mes struct Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me); -struct Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me); @@ -124,10 +125,15 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me); /* Particles */ -struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); -struct Gwn_Batch *DRW_particles_batch_cache_get_dots(struct Object *object, struct ParticleSystem *psys); -struct Gwn_Batch *DRW_particles_batch_cache_get_edit_strands(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_hair( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); +struct Gwn_Batch *DRW_particles_batch_cache_get_dots( + struct Object *object, struct ParticleSystem *psys); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_strands( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); #endif /* __DRAW_CACHE_IMPL_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index 09531220d9a..3eecff024a1 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -176,7 +176,8 @@ Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb) Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len) { - Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN(sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__); + Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN( + sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__); Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len); const int tri_len = curve_render_surface_tri_len_get(lb); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index e8add4890d8..cf972434ba5 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1633,6 +1633,9 @@ typedef struct MeshBatchCache { /* XXX, only keep for as long as sculpt mode uses shaded drawing. */ bool is_sculpt_points_tag; + + /* Valid only if edges_adjacency is up to date. */ + bool is_manifold; } MeshBatchCache; /* Gwn_Batch cache management. */ @@ -1953,7 +1956,8 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, GWN_vertformat_alias_add(format, attrib_name); /* +1 include null terminator. */ - auto_ofs += 1 + BLI_snprintf_rlen(cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); + auto_ofs += 1 + BLI_snprintf_rlen( + cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); cache->auto_layer_is_srgb[auto_id++] = 0; /* tag as not srgb */ if (i == rdata->cd.layers.uv_active) { @@ -1988,7 +1992,8 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, GWN_vertformat_alias_add(format, attrib_name); /* +1 include null terminator. */ - auto_ofs += 1 + BLI_snprintf_rlen(cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); + auto_ofs += 1 + BLI_snprintf_rlen( + cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); cache->auto_layer_is_srgb[auto_id++] = 1; /* tag as srgb */ } @@ -3232,6 +3237,8 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, const int vert_len = mesh_render_data_verts_len_get(rdata); const int tri_len = mesh_render_data_looptri_len_get(rdata); + cache->is_manifold = true; + /* Allocate max but only used indices are sent to GPU. */ Gwn_IndexBufBuilder elb; GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, tri_len * 3, vert_len); @@ -3277,6 +3284,7 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, /* Don't share edge if triangles have non matching winding. */ GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0); GWN_indexbuf_add_line_adj_verts(&elb, v_opposite, v1, v2, v_opposite); + cache->is_manifold = false; } else { GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v_opposite); @@ -3301,6 +3309,7 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, SWAP(unsigned int, v1, v2); } GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0); + cache->is_manifold = false; } BLI_edgehashIterator_free(ehi); BLI_edgehash_free(eh, NULL); @@ -3820,7 +3829,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me) return cache->fancy_edges; } -Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me) +Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold) { MeshBatchCache *cache = mesh_batch_cache_get(me); @@ -3829,12 +3838,17 @@ Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me) MeshRenderData *rdata = mesh_render_data_create(me, options); - cache->edge_detection = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), - mesh_batch_cache_get_edges_adjacency(rdata, cache), 0); + cache->edge_detection = GWN_batch_create_ex( + GWN_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), + mesh_batch_cache_get_edges_adjacency(rdata, cache), 0); mesh_render_data_free(rdata); } + if (r_is_manifold) { + *r_is_manifold = cache->is_manifold; + } + return cache->edge_detection; } diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index c6cc243638b..c89ea67a39c 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -599,7 +599,9 @@ static void particle_batch_cache_ensure_pos(Object *object, val = len_v3(pa->state.vel) / psys->part->color_vec_max; break; case PART_DRAW_COL_ACC: - val = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max); + val = len_v3v3( + pa->state.vel, + pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max); break; default: val = -1.0f; diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index b51b15b20ed..11e04306143 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -224,8 +224,8 @@ DRWShadingGroup *shgroup_dynlines_flat_color(DRWPass *pass) GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); DRW_shgroup_instance_format(g_formats.dynlines_color, { - {"pos" , DRW_ATTRIB_FLOAT, 3}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"pos", DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 4} }); DRWShadingGroup *grp = DRW_shgroup_line_batch_create_with_format(sh, pass, g_formats.dynlines_color); @@ -288,7 +288,7 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *g DRW_shgroup_instance_format(g_formats.instance_screenspace, { {"world_pos", DRW_ATTRIB_FLOAT, 3}, - {"color" , DRW_ATTRIB_FLOAT, 3} + {"color", DRW_ATTRIB_FLOAT, 3} }); DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screenspace); @@ -307,7 +307,7 @@ DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom) DRW_shgroup_instance_format(g_formats.instance_color, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"color", DRW_ATTRIB_FLOAT, 4} }); DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); @@ -322,7 +322,7 @@ DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom) DRW_shgroup_instance_format(g_formats.instance_color, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"color", DRW_ATTRIB_FLOAT, 4} }); DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); @@ -335,8 +335,8 @@ DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED); DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -351,8 +351,8 @@ DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *ge GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS); DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -367,8 +367,8 @@ DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom) GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE); DRW_shgroup_instance_format(g_formats.instance_scaled, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 3}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -382,8 +382,8 @@ DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_Batch *geom) GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE); DRW_shgroup_instance_format(g_formats.instance_sized, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -397,8 +397,8 @@ DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct Gwn_Batch *geom, GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE); DRW_shgroup_instance_format(g_formats.instance_outline, { - {"callId" , DRW_ATTRIB_INT, 1}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"callId", DRW_ATTRIB_INT, 1}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -413,10 +413,10 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom) GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA); DRW_shgroup_instance_format(g_formats.instance_camera, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"corners" , DRW_ATTRIB_FLOAT, 8}, - {"depth" , DRW_ATTRIB_FLOAT, 1}, - {"tria" , DRW_ATTRIB_FLOAT, 4}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"corners", DRW_ATTRIB_FLOAT, 8}, + {"depth", DRW_ATTRIB_FLOAT, 1}, + {"tria", DRW_ATTRIB_FLOAT, 4}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -431,9 +431,9 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch static float point_size = 4.0f; DRW_shgroup_instance_format(g_formats.instance_distance_lines, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"start" , DRW_ATTRIB_FLOAT, 1}, - {"end" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"start", DRW_ATTRIB_FLOAT, 1}, + {"end", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -450,7 +450,7 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom) static const int False = false; DRW_shgroup_instance_format(g_formats.instance_spot, { - {"color" , DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 3}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -472,12 +472,13 @@ DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_color, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"color", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_axes, - pass, DRW_cache_bone_arrows_get(), - g_formats.instance_color); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_axes, + pass, DRW_cache_bone_arrows_get(), + g_formats.instance_color); DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2); return grp; @@ -492,15 +493,16 @@ DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_bone_envelope_outline, { - {"headSphere" , DRW_ATTRIB_FLOAT, 4}, - {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, - {"outlineColorSize" , DRW_ATTRIB_FLOAT, 4}, - {"xAxis" , DRW_ATTRIB_FLOAT, 3} + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_envelope_outline, - pass, DRW_cache_bone_envelope_outline_get(), - g_formats.instance_bone_envelope_outline); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope_outline, + pass, DRW_cache_bone_envelope_outline_get(), + g_formats.instance_bone_envelope_outline); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -515,14 +517,15 @@ DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_bone_envelope_distance, { - {"headSphere" , DRW_ATTRIB_FLOAT, 4}, - {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, - {"xAxis" , DRW_ATTRIB_FLOAT, 3} + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_envelope_distance, - pass, DRW_cache_bone_envelope_solid_get(), - g_formats.instance_bone_envelope_distance); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope_distance, + pass, DRW_cache_bone_envelope_solid_get(), + g_formats.instance_bone_envelope_distance); return grp; } @@ -536,16 +539,17 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_bone_envelope, { - {"headSphere" , DRW_ATTRIB_FLOAT, 4}, - {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, - {"boneColor" , DRW_ATTRIB_FLOAT, 3}, - {"stateColor" , DRW_ATTRIB_FLOAT, 3}, - {"xAxis" , DRW_ATTRIB_FLOAT, 3} + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_envelope, - pass, DRW_cache_bone_envelope_solid_get(), - g_formats.instance_bone_envelope); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope, + pass, DRW_cache_bone_envelope_solid_get(), + g_formats.instance_bone_envelope); return grp; } @@ -559,14 +563,15 @@ DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_mball_handles, { - {"ScaleTranslationMatrix" , DRW_ATTRIB_FLOAT, 12}, - {"radius" , DRW_ATTRIB_FLOAT, 1}, - {"color" , DRW_ATTRIB_FLOAT, 3} + {"ScaleTranslationMatrix", DRW_ATTRIB_FLOAT, 12}, + {"radius", DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.mball_handles, pass, - DRW_cache_screenspace_circle_get(), - g_formats.instance_mball_handles); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.mball_handles, pass, + DRW_cache_screenspace_circle_get(), + g_formats.instance_mball_handles); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); return grp; @@ -585,11 +590,12 @@ DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct Gwn_B DRW_shgroup_instance_format(g_formats.instance_bone_outline, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"outlineColorSize" , DRW_ATTRIB_FLOAT, 4} + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.shape_outline, - pass, geom, g_formats.instance_bone_outline); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.shape_outline, + pass, geom, g_formats.instance_bone_outline); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -605,12 +611,13 @@ DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, struct Gwn_Bat DRW_shgroup_instance_format(g_formats.instance_bone, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"boneColor" , DRW_ATTRIB_FLOAT, 3}, - {"stateColor" , DRW_ATTRIB_FLOAT, 3} + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.shape_solid, - pass, geom, g_formats.instance_bone); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.shape_solid, + pass, geom, g_formats.instance_bone); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -626,12 +633,13 @@ DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_bone, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"boneColor" , DRW_ATTRIB_FLOAT, 3}, - {"stateColor" , DRW_ATTRIB_FLOAT, 3} + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_sphere, - pass, DRW_cache_bone_point_get(), g_formats.instance_bone); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_sphere, + pass, DRW_cache_bone_point_get(), g_formats.instance_bone); return grp; } @@ -646,12 +654,13 @@ DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_bone_outline, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"outlineColorSize" , DRW_ATTRIB_FLOAT, 4} + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_sphere_outline, - pass, DRW_cache_bone_point_wire_outline_get(), - g_formats.instance_bone_outline); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_sphere_outline, + pass, DRW_cache_bone_point_wire_outline_get(), + g_formats.instance_bone_outline); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -667,16 +676,17 @@ DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_bone_stick, { {"boneStart", DRW_ATTRIB_FLOAT, 3}, - {"boneEnd" , DRW_ATTRIB_FLOAT, 3}, + {"boneEnd", DRW_ATTRIB_FLOAT, 3}, {"wireColor", DRW_ATTRIB_FLOAT, 4}, /* TODO port theses to uchar color */ {"boneColor", DRW_ATTRIB_FLOAT, 4}, {"headColor", DRW_ATTRIB_FLOAT, 4}, {"tailColor", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_stick, - pass, DRW_cache_bone_stick_get(), - g_formats.instance_bone_stick); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_stick, + pass, DRW_cache_bone_stick_get(), + g_formats.instance_bone_stick); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -727,10 +737,10 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color case TH_ACTIVE: *r_color = ts.colorActive; break; case TH_SELECT: *r_color = ts.colorSelect; break; case TH_TRANSFORM: *r_color = ts.colorTransform; break; - case OB_SPEAKER: *r_color = ts.colorSpeaker; break; - case OB_CAMERA: *r_color = ts.colorCamera; break; - case OB_EMPTY: *r_color = ts.colorEmpty; break; - case OB_LAMP: *r_color = ts.colorLamp; break; + case TH_SPEAKER: *r_color = ts.colorSpeaker; break; + case TH_CAMERA: *r_color = ts.colorCamera; break; + case TH_EMPTY: *r_color = ts.colorEmpty; break; + case TH_LAMP: *r_color = ts.colorLamp; break; default: *r_color = ts.colorWire; break; } } @@ -749,10 +759,10 @@ float *DRW_color_background_blend_get(int theme_id) case TH_ACTIVE: ret = colors[1]; break; case TH_SELECT: ret = colors[2]; break; case TH_TRANSFORM: ret = colors[5]; break; - case OB_SPEAKER: ret = colors[6]; break; - case OB_CAMERA: ret = colors[7]; break; - case OB_EMPTY: ret = colors[8]; break; - case OB_LAMP: ret = colors[9]; break; + case TH_SPEAKER: ret = colors[6]; break; + case TH_CAMERA: ret = colors[7]; break; + case TH_EMPTY: ret = colors[8]; break; + case TH_LAMP: ret = colors[9]; break; default: ret = colors[10]; break; } diff --git a/source/blender/draw/intern/draw_debug.c b/source/blender/draw/intern/draw_debug.c new file mode 100644 index 00000000000..b30f7936758 --- /dev/null +++ b/source/blender/draw/intern/draw_debug.c @@ -0,0 +1,151 @@ +/* + * Copyright 2018, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_debug.c + * \ingroup draw + * + * \brief Simple API to draw debug shapes in the viewport. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" + +#include "BLI_link_utils.h" + +#include "GPU_immediate.h" + +#include "draw_debug.h" +#include "draw_manager.h" + +/* --------- Register --------- */ + +/* Matrix applied to all points before drawing. Could be a stack if needed. */ +static float g_modelmat[4][4]; + +void DRW_debug_modelmat_reset(void) +{ + unit_m4(g_modelmat); +} + +void DRW_debug_modelmat(const float modelmat[4][4]) +{ + copy_m4_m4(g_modelmat, modelmat); +} + +void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4]) +{ + DRWDebugLine *line = MEM_mallocN(sizeof(DRWDebugLine), "DRWDebugLine"); + mul_v3_m4v3(line->pos[0], g_modelmat, v1); + mul_v3_m4v3(line->pos[1], g_modelmat, v2); + copy_v4_v4(line->color, color); + BLI_LINKS_PREPEND(DST.debug.lines, line); +} + +void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4]) +{ + BLI_assert(vert_len > 1); + + for (int i = 0; i < vert_len; ++i) { + DRW_debug_line_v3v3(v[i], v[(i+1)%vert_len], color); + } +} + +/* NOTE: g_modelmat is still applied on top. */ +void DRW_debug_m4(const float m[4][4]) +{ + float v0[3] = {0.0f, 0.0f, 0.0f}; + float v1[3] = {1.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 1.0f, 0.0f}; + float v3[3] = {0.0f, 0.0f, 1.0f}; + + mul_m4_v3(m, v0); + mul_m4_v3(m, v1); + mul_m4_v3(m, v2); + mul_m4_v3(m, v3); + + DRW_debug_line_v3v3(v0, v1, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); + DRW_debug_line_v3v3(v0, v2, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); + DRW_debug_line_v3v3(v0, v3, (float[4]){0.0f, 0.0f, 1.0f, 1.0f}); +} + +void DRW_debug_bbox(const BoundBox *bbox, const float color[4]) +{ + DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[1], color); + DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[2], color); + DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[3], color); + DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[0], color); + + DRW_debug_line_v3v3(bbox->vec[4], bbox->vec[5], color); + DRW_debug_line_v3v3(bbox->vec[5], bbox->vec[6], color); + DRW_debug_line_v3v3(bbox->vec[6], bbox->vec[7], color); + DRW_debug_line_v3v3(bbox->vec[7], bbox->vec[4], color); + + DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[4], color); + DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[5], color); + DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[6], color); + DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[7], color); +} + +/* --------- Render --------- */ + +static void drw_debug_draw_lines(void) +{ + int count = BLI_linklist_count((LinkNode *)DST.debug.lines); + + if (count == 0) { + return; + } + + Gwn_VertFormat *vert_format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint col = GWN_vertformat_attr_add(vert_format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBegin(GWN_PRIM_LINES, count * 2); + + while (DST.debug.lines) { + void *next = DST.debug.lines->next; + + immAttrib4fv(col, DST.debug.lines->color); + immVertex3fv(pos, DST.debug.lines->pos[0]); + + immAttrib4fv(col, DST.debug.lines->color); + immVertex3fv(pos, DST.debug.lines->pos[1]); + + MEM_freeN(DST.debug.lines); + DST.debug.lines = next; + } + immEnd(); + + immUnbindProgram(); +} + +void drw_debug_draw(void) +{ + drw_debug_draw_lines(); +} + +void drw_debug_init(void) +{ + DRW_debug_modelmat_reset(); +}
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_debug.h b/source/blender/draw/intern/draw_debug.h new file mode 100644 index 00000000000..1dab431fc88 --- /dev/null +++ b/source/blender/draw/intern/draw_debug.h @@ -0,0 +1,39 @@ +/* + * Copyright 2018, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_debug.h + * \ingroup draw + */ + +#ifndef __DRAW_DEBUG_H__ +#define __DRAW_DEBUG_H__ + +struct BoundBox; + +void DRW_debug_modelmat_reset(void); +void DRW_debug_modelmat(const float modelmat[4][4]); + +void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4]); +void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4]); +void DRW_debug_m4(const float m[4][4]); +void DRW_debug_bbox(const BoundBox *bbox, const float color[4]); + +#endif /* __DRAW_DEBUG_H__ */ diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h index a4a02941ddb..bc3c0c2e04c 100644 --- a/source/blender/draw/intern/draw_instance_data.h +++ b/source/blender/draw/intern/draw_instance_data.h @@ -31,7 +31,7 @@ #include "GPU_batch.h" -#define MAX_INSTANCE_DATA_SIZE 42 /* Can be adjusted for more */ +#define MAX_INSTANCE_DATA_SIZE 48 /* Can be adjusted for more */ typedef struct DRWInstanceData DRWInstanceData; typedef struct DRWInstanceDataList DRWInstanceDataList; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 29adb6b47f4..a57a91363eb 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -587,7 +587,8 @@ static void drw_viewport_var_init(void) void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) { BLI_assert(type >= 0 && type < DRW_MAT_COUNT); - BLI_assert(((DST.override_mat & (1 << type)) != 0) || DST.draw_ctx.rv3d != NULL); /* Can't use this in render mode. */ + /* Can't use this in render mode. */ + BLI_assert(((DST.override_mat & (1 << type)) != 0) || DST.draw_ctx.rv3d != NULL); copy_m4_m4(mat, DST.view_data.matstate.mat[type]); } @@ -700,7 +701,8 @@ void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type) return NULL; } -void **DRW_view_layer_engine_data_ensure_ex(ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)) +void **DRW_view_layer_engine_data_ensure_ex( + ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)) { ViewLayerEngineData *sled; @@ -1023,7 +1025,7 @@ static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int dr case OB_SOLID: case OB_TEXTURE: - if (shading_flags & V3D_SHADING_SEE_THROUGH) { + if (shading_flags & V3D_SHADING_XRAY) { use_drw_engine(&draw_engine_workbench_transparent); } else { @@ -1273,6 +1275,8 @@ void DRW_draw_render_loop_ex( /* Update ubos */ DRW_globals_update(); + drw_debug_init(); + /* No framebuffer allowed before drawing. */ BLI_assert(GPU_framebuffer_current_get() == 0); @@ -1340,6 +1344,8 @@ void DRW_draw_render_loop_ex( DRW_state_reset(); + drw_debug_draw(); + drw_engines_draw_text(); if (DST.draw_ctx.evil_C) { @@ -1558,7 +1564,8 @@ static void draw_select_framebuffer_setup(const rcti *rect) } if (g_select_buffer.texture_depth == NULL) { - g_select_buffer.texture_depth = GPU_texture_create_2D(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GPU_DEPTH_COMPONENT24, NULL, NULL); + g_select_buffer.texture_depth = GPU_texture_create_2D( + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GPU_DEPTH_COMPONENT24, NULL, NULL); GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 0f9a68552fe..267826d2d9a 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -272,6 +272,14 @@ typedef struct ViewUboStorage { float clipplanes[2][4]; } ViewUboStorage; +/* ------------- DRAW DEBUG ------------ */ + +typedef struct DRWDebugLine { + struct DRWDebugLine *next; /* linked list */ + float pos[2][3]; + float color[4]; +} DRWDebugLine; + /* ------------- DRAW MANAGER ------------ */ #define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */ @@ -359,6 +367,11 @@ typedef struct DRWManager { char *bound_ubo_slots; int bind_ubo_inc; } RST; + + struct { + /* TODO(fclem) optimize: use chunks. */ + DRWDebugLine *lines; + } debug; } DRWManager; extern DRWManager DST; /* TODO : get rid of this and allow multithreaded rendering */ @@ -374,4 +387,7 @@ void *drw_viewport_engine_data_ensure(void *engine_type); void drw_state_set(DRWState state); +void drw_debug_draw(void); +void drw_debug_init(void); + #endif /* __DRAW_MANAGER_H__ */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 1e2036714bf..b4dce47413e 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -797,7 +797,8 @@ DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPas return shgroup; } -DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(struct GPUShader *shader, DRWPass *pass, Gwn_VertFormat *format) +DRWShadingGroup *DRW_shgroup_line_batch_create_with_format( + struct GPUShader *shader, DRWPass *pass, Gwn_VertFormat *format) { DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); shgroup->type = DRW_SHG_LINE_BATCH; diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 9f4adac0106..110691373ab 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -221,7 +221,8 @@ void drw_state_set(DRWState state) int test; if (CHANGED_ANY_STORE_VAR( DRW_STATE_BLEND | DRW_STATE_BLEND_PREMUL | DRW_STATE_ADDITIVE | - DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION | DRW_STATE_ADDITIVE_FULL, + DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION | DRW_STATE_ADDITIVE_FULL | + DRW_STATE_TRANSPARENT_REVEALAGE, test)) { if (test) { @@ -240,6 +241,9 @@ void drw_state_set(DRWState state) else if ((state & DRW_STATE_TRANSMISSION) != 0) { glBlendFunc(GL_ONE, GL_SRC_ALPHA); } + else if ((state & DRW_STATE_TRANSPARENT_REVEALAGE) != 0) { + glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + } else if ((state & DRW_STATE_ADDITIVE) != 0) { /* Do not let alpha accumulate but premult the source RGB by it. */ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, /* RGB */ @@ -329,8 +333,8 @@ void drw_state_set(DRWState state) } else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) != 0) { glStencilMask(0xFF); - glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR_WRAP, GL_KEEP); - glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR_WRAP, GL_KEEP); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); } /* Stencil Test */ else if ((state & (DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)) != 0) { @@ -703,6 +707,12 @@ bool DRW_culling_plane_test(float plane[4]) return false; } +void DRW_culling_frustum_corners_get(BoundBox *corners) +{ + draw_clipping_setup_from_view(); + memcpy(corners, &DST.clipping.frustum_corners, sizeof(BoundBox)); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -818,7 +828,8 @@ static void draw_geometry_execute_ex( } /* step 2 : bind vertex array & draw */ - GWN_batch_program_set_no_use(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); + GWN_batch_program_set_no_use( + geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */ geom->program_in_use = true; diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 2c4e5f8b151..726d77a9925 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -682,7 +682,7 @@ void DRW_draw_cursor(void) immUniformThemeColor3(TH_VIEW_OVERLAY); immBegin(GWN_PRIM_LINES, 12); - const float scale = ED_view3d_pixel_size(rv3d, cursor->location) * 20; + const float scale = ED_view3d_pixel_size_no_ui_scale(rv3d, cursor->location) * U.widget_unit; #define CURSOR_VERT(axis_vec, axis, fac) \ immVertex3f( \ diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index 8ac3cff2e1c..c0c4e7e4295 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -116,7 +116,9 @@ static void EDIT_METABALL_cache_init(void *vedata) { /* Create a pass */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE); psl->pass = DRW_pass_create("My Pass", state); /* Create a shadingGroup using a function in draw_common.c or custom one */ diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c index b5cbb1baa55..7074ba3d024 100644 --- a/source/blender/draw/modes/edit_surface_mode.c +++ b/source/blender/draw/modes/edit_surface_mode.c @@ -149,7 +149,9 @@ static void EDIT_SURFACE_cache_init(void *vedata) { /* Create a pass */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE); psl->pass = DRW_pass_create("My Pass", state); /* Create a shadingGroup using a function in draw_common.c or custom one */ diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 58cdfd4e413..52749a5429f 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -175,7 +175,8 @@ typedef struct OBJECT_PrivateData { DRWShadingGroup *lamp_distance; DRWShadingGroup *lamp_buflimit; DRWShadingGroup *lamp_buflimit_points; - DRWShadingGroup *lamp_area; + DRWShadingGroup *lamp_area_square; + DRWShadingGroup *lamp_area_disk; DRWShadingGroup *lamp_hemi; DRWShadingGroup *lamp_spot_cone; DRWShadingGroup *lamp_spot_blend; @@ -288,6 +289,7 @@ enum { PLANE_YZ = (1 << 6), CLIP_ZPOS = (1 << 7), CLIP_ZNEG = (1 << 8), + GRID_BACK = (1 << 9), }; /* *********** FUNCTIONS *********** */ @@ -446,18 +448,21 @@ static void OBJECT_engine_init(void *vedata) e_data.grid_flag |= SHOW_AXIS_Y; e_data.grid_flag |= SHOW_AXIS_Z; e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; } else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { e_data.grid_flag = PLANE_XY; e_data.grid_flag |= SHOW_AXIS_X; e_data.grid_flag |= SHOW_AXIS_Y; e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; } else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { e_data.grid_flag = PLANE_XZ; e_data.grid_flag |= SHOW_AXIS_X; e_data.grid_flag |= SHOW_AXIS_Z; e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; } else { /* RV3D_VIEW_USER */ e_data.grid_flag = PLANE_XY; @@ -987,7 +992,7 @@ static void OBJECT_cache_init(void *vedata) { /* Solid bones */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; psl->bone_solid = DRW_pass_create("Bone Solid Pass", state); psl->bone_outline = DRW_pass_create("Bone Outline Pass", state); } @@ -1164,8 +1169,11 @@ static void OBJECT_cache_init(void *vedata) stl->g_data->lamp_groundline = shgroup_groundlines_uniform_color(psl->non_meshes, ts.colorLamp); stl->g_data->lamp_groundpoint = shgroup_groundpoints_uniform_color(psl->non_meshes, ts.colorLamp); - geom = DRW_cache_lamp_area_get(); - stl->g_data->lamp_area = shgroup_instance(psl->non_meshes, geom); + geom = DRW_cache_lamp_area_square_get(); + stl->g_data->lamp_area_square = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_area_disk_get(); + stl->g_data->lamp_area_disk = shgroup_instance(psl->non_meshes, geom); geom = DRW_cache_lamp_hemi_get(); stl->g_data->lamp_hemi = shgroup_instance(psl->non_meshes, geom); @@ -1398,13 +1406,18 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, ViewLayer *vie else if (la->type == LA_AREA) { float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; - if (la->area_shape == LA_AREA_RECT) { + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { size[1] = la->area_sizey / la->area_size; size_to_mat4(sizemat, size); mul_m4_m4m4(shapemat, shapemat, sizemat); } - DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area, color, &la->area_size, shapemat); + if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area_disk, color, &la->area_size, shapemat); + } + else { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area_square, color, &la->area_size, shapemat); + } } /* Line and point going to the ground */ diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index e2b381347ff..c4b64e03c48 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -76,7 +76,8 @@ static void overlay_engine_init(void *vedata) if (!e_data.face_orientation_sh) { /* Face orientation */ - e_data.face_orientation_sh = DRW_shader_create(datatoc_overlay_face_orientation_vert_glsl, NULL, datatoc_overlay_face_orientation_frag_glsl, "\n"); + e_data.face_orientation_sh = DRW_shader_create( + datatoc_overlay_face_orientation_vert_glsl, NULL, datatoc_overlay_face_orientation_frag_glsl, "\n"); } } @@ -100,7 +101,8 @@ static void overlay_cache_init(void *vedata) if (stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { int state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; psl->face_orientation_pass = DRW_pass_create("Face Orientation", state); - stl->g_data->face_orientation_shgrp = DRW_shgroup_create(e_data.face_orientation_sh, psl->face_orientation_pass); + stl->g_data->face_orientation_shgrp = DRW_shgroup_create( + e_data.face_orientation_sh, psl->face_orientation_pass); } } diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl index dc7ed5e202a..11924b19cf8 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl @@ -1,11 +1,9 @@ -/* TODO: See perf with multiple invocations. */ -layout(triangles_adjacency) in; -layout(triangle_strip, max_vertices = 16) out; +layout(lines_adjacency) in; +layout(triangle_strip, max_vertices = 6) out; in vec4 pPos[]; -in float vZ[]; -in float vFacing[]; +in vec3 vPos[]; in vec2 ssPos[]; in vec2 ssNor[]; in vec4 vColSize[]; @@ -22,21 +20,18 @@ vec2 compute_dir(vec2 v0, vec2 v1) return dir; } -void emit_edge(const ivec3 edges, vec2 thick, bool is_persp) +void emit_edge(vec2 edge_dir, vec2 hidden_dir, vec2 thick, bool is_persp) { - vec2 edge_dir = compute_dir(ssPos[edges.x], ssPos[edges.y]); - vec2 hidden_dir = normalize(ssPos[edges.z] - ssPos[edges.x]); - float fac = dot(-hidden_dir, edge_dir); - vec2 t = thick * (is_persp ? vZ[edges.x] : 1.0); - gl_Position = pPos[edges.x]; + vec2 t = thick * (is_persp ? abs(vPos[1].z) : 1.0); + gl_Position = pPos[1]; EmitVertex(); gl_Position.xy += t * edge_dir * sign(fac); EmitVertex(); - t = thick * (is_persp ? vZ[edges.y] : 1.0); - gl_Position = pPos[edges.y]; + t = thick * (is_persp ? abs(vPos[2].z) : 1.0); + gl_Position = pPos[2]; EmitVertex(); gl_Position.xy += t * edge_dir * sign(fac); EmitVertex(); @@ -45,7 +40,7 @@ void emit_edge(const ivec3 edges, vec2 thick, bool is_persp) void emit_corner(const int e, vec2 thick, bool is_persp) { vec2 corner_dir = ssNor[e]; - vec2 t = thick * (is_persp ? vZ[e] : 1.0); + vec2 t = thick * (is_persp ? abs(vPos[e].z) : 1.0); gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0); EmitVertex(); @@ -55,41 +50,38 @@ void main(void) { finalColor = vec4(vColSize[0].rgb, 1.0); - vec2 thick = vColSize[0].w * (lineThickness / viewportSize); bool is_persp = (ProjectionMatrix[3][3] == 0.0); - const ivec3 edges = ivec3(0, 2, 4); - vec4 facing = vec4(vFacing[1], vFacing[3], vFacing[5], vFacing[0]); - bvec4 do_edge = greaterThanEqual(facing, vec4(0.0)); + vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); + vec3 v10 = vPos[0] - vPos[1]; + vec3 v12 = vPos[2] - vPos[1]; + vec3 v13 = vPos[3] - vPos[1]; - /* Only generate outlines from backfaces. */ - if (do_edge.w) - return; + vec3 n0 = cross(v12, v10); + vec3 n3 = cross(v13, v12); - if (do_edge.x) { - emit_corner(edges.x, thick, is_persp); - emit_edge(edges.xyz, thick, is_persp); - } + float fac0 = dot(view_vec, n0); + float fac3 = dot(view_vec, n3); - if (any(do_edge.xy)) { - emit_corner(edges.y, thick, is_persp); - } + /* If both adjacent verts are facing the camera the same way, + * then it isn't an outline edge. */ + if (sign(fac0) == sign(fac3)) + return; - if (do_edge.y) { - emit_edge(edges.yzx, thick, is_persp); - } - else { - EndPrimitive(); - } + /* Don't outline if concave edge. */ + if (dot(n0, v13) > 0.0) + return; - if (any(do_edge.yz)) { - emit_corner(edges.z, thick, is_persp); - } + vec2 thick = vColSize[0].w * (lineThickness / viewportSize); + vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]); - if (do_edge.z) { - emit_edge(edges.zxy, thick, is_persp); - emit_corner(edges.x, thick, is_persp); - } + /* Take the farthest point to compute edge direction + * (avoid problems with point behind near plane). */ + vec2 hidden_point = (vPos[0].z < vPos[3].z) ? ssPos[0] : ssPos[3]; + vec2 hidden_dir = normalize(hidden_point - ssPos[1]); + emit_corner(1, thick, is_persp); + emit_edge(edge_dir, hidden_dir, thick, is_persp); + emit_corner(2, thick, is_persp); EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl index 0d09114579c..3e7a185bb62 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl @@ -15,8 +15,7 @@ in mat4 InstanceModelMatrix; in vec4 outlineColorSize; out vec4 pPos; -out float vZ; -out float vFacing; +out vec3 vPos; out vec2 ssPos; out vec2 ssNor; out vec4 vColSize; @@ -34,25 +33,15 @@ void main() mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); vec4 viewpos = ViewMatrix * (InstanceModelMatrix * vec4(pos, 1.0)); - pPos = ProjectionMatrix * viewpos; - vZ = abs(viewpos.z); - /* if perspective */ - vec3 V = (ProjectionMatrix[3][3] == 0.0) ? normalize(-viewpos.xyz) : vec3(0.0, 0.0, 1.0); + vPos = viewpos.xyz; + pPos = ProjectionMatrix * viewpos; /* TODO FIX: there is still a problem with this vector * when the bone is scaled or in persp mode. But it's * barelly visible at the outline corners. */ ssNor = normalize((NormalMatrix * snor).xy); - vec3 normal = normalize(NormalMatrix * nor); - /* Add a small bias to avoid loosing outline - * on faces orthogonal to the view. - * (test case: octahedral bone without rotation in front view.) */ - normal.z += 1e-6; - - vFacing = dot(V, normal); - ssPos = proj(pPos); vColSize = outlineColorSize; diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl index 248281f4e79..89f4d97f29b 100644 --- a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl @@ -1,5 +1,5 @@ -flat in vec4 finalColor; +in vec4 finalColor; out vec4 fragColor; diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl index 701fc9c38ab..505868c9dcf 100644 --- a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl @@ -16,7 +16,7 @@ in mat4 InstanceModelMatrix; in vec3 boneColor; in vec3 stateColor; -flat out vec4 finalColor; +out vec4 finalColor; void main() { diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index baf508fd854..2b04bb0d855 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -29,22 +29,23 @@ uniform int gridFlag; #define PLANE_XY (1 << 4) #define PLANE_XZ (1 << 5) #define PLANE_YZ (1 << 6) +#define GRID_BACK (1 << 9) /* grid is behind objects */ #define GRID_LINE_SMOOTH 1.15 -float get_grid(vec3 co, vec3 fwidthCos, float grid_size) +float get_grid(vec2 co, vec2 fwidthCos, float grid_size) { float half_size = grid_size / 2.0; - /* triangular wave pattern, amplitude is [0, grid_size] */ - vec3 grid_domain = abs(mod(co + half_size, grid_size) - half_size); + /* triangular wave pattern, amplitude is [0, half_size] */ + vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size); /* modulate by the absolute rate of change of the coordinates * (make lines have the same width under perspective) */ grid_domain /= fwidthCos; /* collapse waves and normalize */ - grid_domain.x = min(grid_domain.x, min(grid_domain.y, grid_domain.z)) / grid_size; + grid_domain.x = min(grid_domain.x, grid_domain.y) / half_size; - return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x); + return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x * 0.5); } vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size) @@ -137,18 +138,6 @@ void main() } } - /* Manual, non hard, depth test: - * Progressively fade the grid below occluders - * (avoids poping visuals due to depth buffer precision) */ - float scene_depth = texture(depthBuffer, sPos).r; - /* Add a small bias so the grid will always - * be on top of a mesh with the same depth. */ - float grid_depth = gl_FragCoord.z - 1e-8; - /* Harder settings tend to flicker more, - * but have less "see through" appearance. */ - const float test_hardness = 1e4; - fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0); - if ((gridFlag & GRID) > 0) { float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv; @@ -160,9 +149,23 @@ void main() float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0)); float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0)); - float gridA = get_grid(wPos, fwidthPos, scaleA); - float gridB = get_grid(wPos, fwidthPos, scaleB); - float gridC = get_grid(wPos, fwidthPos, scaleC); + vec2 grid_pos, grid_fwidth; + if ((gridFlag & PLANE_XZ) > 0) { + grid_pos = wPos.xz; + grid_fwidth = fwidthPos.xz; + } + else if ((gridFlag & PLANE_YZ) > 0) { + grid_pos = wPos.yz; + grid_fwidth = fwidthPos.yz; + } + else { + grid_pos = wPos.xy; + grid_fwidth = fwidthPos.xy; + } + + float gridA = get_grid(grid_pos, grid_fwidth, scaleA); + float gridB = get_grid(grid_pos, grid_fwidth, scaleB); + float gridC = get_grid(grid_pos, grid_fwidth, scaleC); FragColor = vec4(colorGrid.rgb, gridA * blend); FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB); @@ -203,5 +206,22 @@ void main() } } + float scene_depth = texture(depthBuffer, sPos).r; + if ((gridFlag & GRID_BACK) > 0) { + fade *= (scene_depth == 1.0) ? 1.0 : 0.0; + } + else { + /* Manual, non hard, depth test: + * Progressively fade the grid below occluders + * (avoids poping visuals due to depth buffer precision) */ + /* Add a small bias so the grid will always + * be on top of a mesh with the same depth. */ + float grid_depth = gl_FragCoord.z - 1e-8; + /* Harder settings tend to flicker more, + * but have less "see through" appearance. */ + const float test_hardness = 1e4; + fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0); + } + FragColor.a *= fade; } diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index abdc6450abd..9169df1407b 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -79,6 +79,9 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale) if (adt) { adt->recalc |= ADT_RECALC_ANIM; DEG_id_tag_update(id, OB_RECALC_TIME); + if (adt->action != NULL) { + DEG_id_tag_update(&adt->action->id, DEG_TAG_COPY_ON_WRITE); + } } /* update data */ diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h index c571da1ba74..824c1d58f44 100644 --- a/source/blender/editors/animation/anim_intern.h +++ b/source/blender/editors/animation/anim_intern.h @@ -79,6 +79,7 @@ void ANIM_OT_keying_set_active_set(struct wmOperatorType *ot); /* Driver management operators for UI buttons (RMB menu) */ void ANIM_OT_driver_button_add(struct wmOperatorType *ot); void ANIM_OT_driver_button_remove(struct wmOperatorType *ot); +void ANIM_OT_driver_button_edit(struct wmOperatorType *ot); void ANIM_OT_copy_driver_button(struct wmOperatorType *ot); void ANIM_OT_paste_driver_button(struct wmOperatorType *ot); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index eace5af4701..1136dcd129e 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -512,6 +512,7 @@ void ED_operatortypes_anim(void) WM_operatortype_append(ANIM_OT_driver_button_add); WM_operatortype_append(ANIM_OT_driver_button_remove); + WM_operatortype_append(ANIM_OT_driver_button_edit); WM_operatortype_append(ANIM_OT_copy_driver_button); WM_operatortype_append(ANIM_OT_paste_driver_button); diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index f792bd2ea9b..2c28ecfac5d 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -41,6 +41,7 @@ #include "DNA_anim_types.h" #include "DNA_object_types.h" +#include "DNA_space_types.h" #include "DNA_texture_types.h" #include "BKE_animsys.h" @@ -967,6 +968,46 @@ void ANIM_OT_driver_button_remove(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array"); } +/* Edit Driver Button Operator ------------------------ */ + +static int edit_driver_button_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; + const bool all = 0; // RNA_boolean_get(op->ptr, "all"); + + /* try to find driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (all) + index = -1; + + if (ptr.id.data && ptr.data && prop) { + UI_popover_panel_invoke(C, SPACE_IPO, RGN_TYPE_UI, "GRAPH_PT_drivers_popover", true, op->reports); + } + + return OPERATOR_INTERFACE; +} + +void ANIM_OT_driver_button_edit(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Edit Driver"; + ot->idname = "ANIM_OT_driver_button_edit"; + ot->description = "Edit the drivers for the property connected represented by the highlighted button"; + + /* callbacks */ + ot->exec = edit_driver_button_exec; + //op->poll = ??? // TODO: need to have some driver to be able to do this... + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + + /* properties */ + //RNA_def_boolean(ot->srna, "all", 1, "All", "Edit drivers for all elements of the array"); +} + /* Copy Driver Button Operator ------------------------ */ static int copy_driver_button_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index b03aa66df04..f0dc680598c 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -299,7 +299,22 @@ void ED_pose_deselect_all_multi(Object **objects, uint objects_len, int select_m for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; + bArmature *arm = ob_iter->data; + ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility); + + /* if there are some dependencies for visualizing armature state + * (e.g. Mask Modifier in 'Armature' mode), force update + */ + if (arm->flag & ARM_HAS_VIZ_DEPS) { + /* NOTE: ob not ob_act here is intentional - it's the source of the + * bones being selected [T37247] + */ + DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA); + } + + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } @@ -368,6 +383,9 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve /* mask modifier ('armature' mode), etc. */ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } + + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); return OPERATOR_FINISHED; } @@ -907,6 +925,9 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); + /* report done status */ if (changed) return OPERATOR_FINISHED; @@ -1001,6 +1022,9 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); + + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } FOREACH_OBJECT_IN_MODE_END; diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index af9d94c0bac..1657fe4eaea 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -780,6 +780,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, ViewLayer *view_layer = CTX_data_view_layer(C); FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob_iter) { + Object *ob_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), ob_iter); // XXX: UGLY HACK (for autokey + clear transforms) ListBase dsources = {NULL, NULL}; bool changed = false; @@ -797,6 +798,11 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, } /* tag for autokeying later */ ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan); + +#if 1 /* XXX: Ugly Hack - Run clearing function on evaluated copy of pchan */ + bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); + clear_func(pchan_eval); +#endif } else { /* add unkeyed tags */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index eb180c6bde9..1987fe56bdb 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -5026,7 +5026,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) const float mval[2] = {UNPACK2(event->mval)}; struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), vc.scene, CTX_data_depsgraph(C), 0, vc.ar, vc.v3d); + vc.scene, CTX_data_depsgraph(C), 0, vc.ar, vc.v3d); ED_transform_snap_object_project_view3d( snap_context, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index a91d373ac46..b10d915553e 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -248,6 +248,7 @@ int ED_operator_screen_mainwinactive(struct bContext *C); int ED_operator_areaactive(struct bContext *C); int ED_operator_regionactive(struct bContext *C); +int ED_operator_scene(struct bContext *C); int ED_operator_scene_editable(struct bContext *C); int ED_operator_objectmode(struct bContext *C); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 36f87e1b494..c005f83b3fb 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -103,6 +103,7 @@ enum TfmMode { #define CTX_MASK (1 << 7) #define CTX_PAINT_CURVE (1 << 8) #define CTX_GPENCIL_STROKES (1 << 9) +#define CTX_CURSOR (1 << 10) /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) @@ -153,7 +154,8 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_NO_TEXSPACE (1 << 11) #define P_CENTER (1 << 12) #define P_GPENCIL_EDIT (1 << 13) -#define P_CLNOR_INVALIDATE (1 << 14) +#define P_CURSOR_EDIT (1 << 14) +#define P_CLNOR_INVALIDATE (1 << 15) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 8ac7dfcf9d8..18d5101ebf7 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -79,9 +79,9 @@ struct SnapObjectParams { typedef struct SnapObjectContext SnapObjectContext; SnapObjectContext *ED_transform_snap_object_context_create( - struct Main *bmain, struct Scene *scene, struct Depsgraph *depsgraph, int flag); + struct Scene *scene, struct Depsgraph *depsgraph, int flag); SnapObjectContext *ED_transform_snap_object_context_create_view3d( - struct Main *bmain, struct Scene *scene, struct Depsgraph *depsgraph, int flag, + struct Scene *scene, struct Depsgraph *depsgraph, int flag, /* extra args for view3d */ const struct ARegion *ar, const struct View3D *v3d); void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx); diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index d6e8b6e9504..4d5e4585221 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -54,6 +54,11 @@ bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obe bool ED_uvedit_center(Scene *scene, Image *ima, struct Object *obedit, float cent[2], char mode); void ED_uvedit_select_all(struct BMesh *bm); +bool ED_uvedit_minmax_multi( + struct Scene *scene, struct Image *ima, struct Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]); +bool ED_uvedit_center_multi( + Scene *scene, Image *ima, struct Object **objects_edit, uint objects_len, float r_cent[2], char mode); + bool ED_object_get_active_image( struct Object *ob, int mat_nr, struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 28e2c5e0d71..e1a6d59a748 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -106,9 +106,11 @@ void ED_view3d_cursor3d_update(struct bContext *C, const int mval[2]); struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d); void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist); -void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist); +void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist); -void ED_view3d_from_object(struct Object *ob, float ofs[3], float quat[4], float *dist, float *lens); +void ED_view3d_from_object( + const struct Object *ob, + float ofs[3], float quat[4], float *dist, float *lens); void ED_view3d_to_object( const struct Depsgraph *depsgraph, struct Object *ob, const float ofs[3], const float quat[4], const float dist); @@ -227,6 +229,7 @@ eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const fl eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]); +float ED_view3d_pixel_size_no_ui_scale(const struct RegionView3D *rv3d, const float co[3]); float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]); @@ -304,12 +307,14 @@ float ED_view3d_radius_to_dist_persp(const float angle, const float radius); float ED_view3d_radius_to_dist_ortho(const float lens, const float radius); float ED_view3d_radius_to_dist( const struct View3D *v3d, const struct ARegion *ar, + const struct Depsgraph *depsgraph, const char persp, const bool use_aspect, const float radius); void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos); /* backbuffer select and draw support */ +void ED_view3d_backbuf_validate_with_select_mode(struct ViewContext *vc, short select_mode); void ED_view3d_backbuf_validate(struct ViewContext *vc); struct ImBuf *ED_view3d_backbuf_read( struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 142f4590c16..896d161f664 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -429,11 +429,9 @@ void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *b typedef struct uiPopover uiPopover; -void UI_popover_panel_from_type( - struct bContext *C, struct uiLayout *layout, struct PanelType *pt); int UI_popover_panel_invoke( struct bContext *C, int space_id, int region_id, const char *idname, - struct ReportList *reports); + bool keep_open, struct ReportList *reports); uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL(1); void UI_popover_end(struct bContext *C, struct uiPopover *head, struct wmKeyMap *keymap); @@ -949,6 +947,7 @@ const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing struct MenuType *UI_but_menutype_get(uiBut *but); struct PanelType *UI_but_paneltype_get(uiBut *but); void UI_menutype_draw(struct bContext *C, struct MenuType *mt, struct uiLayout *layout); +void UI_paneltype_draw(struct bContext *C, struct PanelType *pt, struct uiLayout *layout); /* Only for convenience. */ void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but); @@ -962,6 +961,7 @@ void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect); void uiLayoutSetScaleX(uiLayout *layout, float scale); void uiLayoutSetScaleY(uiLayout *layout, float scale); void uiLayoutSetEmboss(uiLayout *layout, char emboss); +void uiLayoutSetPropSep(uiLayout *layout, bool is_sep); int uiLayoutGetOperatorContext(uiLayout *layout); bool uiLayoutGetActive(uiLayout *layout); @@ -973,6 +973,7 @@ int uiLayoutGetWidth(uiLayout *layout); float uiLayoutGetScaleX(uiLayout *layout); float uiLayoutGetScaleY(uiLayout *layout); int uiLayoutGetEmboss(uiLayout *layout); +bool uiLayoutGetPropSep(uiLayout *layout); /* layout specifiers */ uiLayout *uiLayoutRow(uiLayout *layout, int align); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index e4b298fecf0..a9995001659 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2887,7 +2887,7 @@ void ui_but_update_ex(uiBut *but, const bool validate) switch (but->type) { case UI_BTYPE_MENU: - if (BLI_rctf_size_x(&but->rect) > 24.0f) { + if (BLI_rctf_size_x(&but->rect) >= (UI_UNIT_X * 2)) { /* only needed for menus in popup blocks that don't recreate buttons on redraw */ if (but->block->flag & UI_BLOCK_LOOP) { if (but->rnaprop && (RNA_property_type(but->rnaprop) == PROP_ENUM)) { @@ -3212,7 +3212,9 @@ static uiBut *ui_def_but( } #ifdef USE_NUMBUTS_LR_ALIGN else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { - but->drawflag |= UI_BUT_TEXT_LEFT; + if (slen != 0) { + but->drawflag |= UI_BUT_TEXT_LEFT; + } } #endif @@ -4626,6 +4628,9 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) PointerRNA *opptr = UI_but_operator_ptr_get(but); wmOperatorType *ot = but->optype; + /* so the context is passed to itemf functions */ + WM_operator_properties_sanitize(opptr, false); + /* if the default property of the operator is enum and it is set, * fetch the tooltip of the selected value so that "Snap" and "Mirror" * operator menus in the Anim Editors will show tooltips for the different @@ -4645,9 +4650,6 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) if (!item) { int i; - /* so the context is passed to itemf functions */ - WM_operator_properties_sanitize(ptr, false); - RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items); for (i = 0, item = items; i < totitems; i++, item++) { if (item->identifier[0] && item->value == value) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 70cd53c440f..0ebe079703b 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1780,23 +1780,20 @@ static bool ui_but_drag_init( /* TODO support more button pointer types */ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { - RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color); + ui_but_v3_get(but, drag_info->color); drag_info->gamma_corrected = true; valid = true; } else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) { - RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color); + ui_but_v3_get(but, drag_info->color); drag_info->gamma_corrected = false; valid = true; } - else if (but->pointype == UI_BUT_POIN_FLOAT) { + else if (ELEM(but->pointype, UI_BUT_POIN_FLOAT, UI_BUT_POIN_CHAR)) { + ui_but_v3_get(but, drag_info->color); copy_v3_v3(drag_info->color, (float *)but->poin); valid = true; } - else if (but->pointype == UI_BUT_POIN_CHAR) { - rgb_uchar_to_float(drag_info->color, (unsigned char *)but->poin); - valid = true; - } if (valid) { WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA); @@ -6783,8 +6780,11 @@ static bool ui_but_menu(bContext *C, uiBut *but) ICON_NONE, "ANIM_OT_paste_driver_button"); } + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"), + ICON_DRIVER, "ANIM_OT_driver_button_edit"); + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_DRIVER, "SCREEN_OT_drivers_editor_show"); + ICON_NONE, "SCREEN_OT_drivers_editor_show"); } else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { /* pass */ @@ -6809,7 +6809,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) } uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_DRIVER, "SCREEN_OT_drivers_editor_show"); + ICON_NONE, "SCREEN_OT_drivers_editor_show"); } /* Keying Sets */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 51c3cff721a..bacea087677 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -783,7 +783,7 @@ static DrawInfo *icon_create_drawinfo(Icon *icon) IconImage *img = MEM_mallocN(sizeof(IconImage), __func__); img->w = STUDIOLIGHT_SIZE; img->h = STUDIOLIGHT_SIZE; - img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE); + img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE, icon->id_type); di->data.buffer.image = img; } else { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index b851d1d8c5b..c7cf03a44dd 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -794,6 +794,8 @@ void ui_resources_free(void); void ui_layout_add_but(uiLayout *layout, uiBut *but); void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop); void ui_layout_list_set_labels_active(uiLayout *layout); +/* menu callback */ +void ui_item_paneltype_func(struct bContext *C, struct uiLayout *layout, void *arg_pt); /* interface_align.c */ bool ui_but_can_align(const uiBut *but) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3a4d35296f7..7991f03ea31 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -71,6 +71,7 @@ return_statement; \ } (void)0 \ +#define UI_ITEM_PROP_SEP_DIVIDE 0.5f /* uiLayoutRoot */ @@ -128,6 +129,7 @@ enum { UI_ITEM_MIN = 1 << 1, UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */ + UI_ITEM_PROP_SEP = 1 << 3, }; typedef struct uiButtonItem { @@ -181,7 +183,7 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_ int len = strlen(name); if (len != 0 && len + 1 < UI_MAX_NAME_STR) { - BLI_strncpy(namestr, name, UI_MAX_NAME_STR); + memcpy(namestr, name, len); namestr[len] = ':'; namestr[len + 1] = '\0'; return namestr; @@ -394,7 +396,7 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index) static void ui_item_array( uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h), - bool expand, bool slider, bool toggle, bool icon_only, bool compact) + bool expand, bool slider, bool toggle, bool icon_only, bool compact, bool show_text) { uiStyle *style = layout->root->style; uiBut *but; @@ -411,8 +413,9 @@ static void ui_item_array( UI_block_layout_set_current(block, sub); /* create label */ - if (name[0]) + if (name[0] && show_text) { uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + } /* create buttons */ if (type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) { @@ -530,7 +533,7 @@ static void ui_item_array( /* layout for known array subtypes */ char str[3] = {'\0'}; - if (!icon_only) { + if (!icon_only && show_text) { if (type != PROP_BOOLEAN) { str[1] = ':'; } @@ -542,19 +545,21 @@ static void ui_item_array( RNA_property_boolean_get_array(ptr, prop, boolarr); } + const char *str_buf = show_text ? str: ""; for (a = 0; a < len; a++) { int width_item; - if (!icon_only) { + if (!icon_only && show_text) { str[0] = RNA_property_array_item_char(prop, a); } if (boolarr) { icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; } + width_item = (compact && type == PROP_BOOLEAN) ? - min_ii(w, ui_text_icon_width(layout, str, icon, false)) : w; + min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) : w; - but = uiDefAutoButR(block, ptr, prop, a, str, icon, 0, 0, width_item, UI_UNIT_Y); + but = uiDefAutoButR(block, ptr, prop, a, str_buf, icon, 0, 0, width_item, UI_UNIT_Y); if (slider && but->type == UI_BTYPE_NUM) but->type = UI_BTYPE_NUM_SLIDER; if (toggle && but->type == UI_BTYPE_CHECKBOX) @@ -1401,7 +1406,8 @@ static void ui_item_rna_size( if (index == RNA_NO_INDEX && len > 0) { if (!name[0] && icon == ICON_NONE) h = 0; - + if (layout->item.flag & UI_ITEM_PROP_SEP) + h = 0; if (ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) h += 2 * UI_UNIT_Y; else if (subtype == PROP_MATRIX) @@ -1431,6 +1437,7 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index int len, w, h; bool slider, toggle, expand, icon_only, no_bg, compact; bool is_array; + const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); UI_block_layout_set_current(block, layout); @@ -1456,17 +1463,23 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index /* pass */ } else if (ELEM(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) { - name = ui_item_name_add_colon(name, namestr); + if (use_prop_sep == false) { + name = ui_item_name_add_colon(name, namestr); + } } else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) { - name = ui_item_name_add_colon(name, namestr); + if (use_prop_sep == false) { + name = ui_item_name_add_colon(name, namestr); + } } else if (type == PROP_ENUM && index != RNA_ENUM_VALUE) { if (flag & UI_ITEM_R_COMPACT) { name = ""; } else { - name = ui_item_name_add_colon(name, namestr); + if (use_prop_sep == false) { + name = ui_item_name_add_colon(name, namestr); + } } } @@ -1505,11 +1518,56 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index layout->emboss = UI_EMBOSS_NONE; } + /* Split the label / property. */ + if (use_prop_sep) { + uiLayout *layout_split = uiLayoutSplit(layout, UI_ITEM_PROP_SEP_DIVIDE, true); + layout_split->space = 0; + uiLayout *layout_sub = uiLayoutColumn(layout_split, true); + layout_sub->space = 0; + + if (index == RNA_NO_INDEX && is_array) { + char name_with_suffix[UI_MAX_DRAW_STR + 2]; + char str[2] = {'\0'}; + for (int a = 0; a < len; a++) { + str[0] = RNA_property_array_item_char(prop, a); + const bool use_prefix = (a == 0 && name && name[0]); + if (use_prefix) { + char *s = name_with_suffix; + s += STRNCPY_RLEN(name_with_suffix, name); + *s++ = ' '; + *s++ = str[0]; + *s++ = '\0'; + } + but = uiDefBut( + block, UI_BTYPE_LABEL, 0, use_prefix ? name_with_suffix : str, + 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; + } + } + else { + if (name) { + but = uiDefBut( + 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; + } + } + + /* Watch out! We can only write into the new column now. */ + layout = uiLayoutColumn(layout_split, true); + layout->space = 0; + name = ""; + } + /* End split. */ + /* array property */ - if (index == RNA_NO_INDEX && is_array) + if (index == RNA_NO_INDEX && is_array) { ui_item_array( - layout, block, name, icon, ptr, prop, len, 0, 0, w, h, - expand, slider, toggle, icon_only, compact); + layout, block, name, icon, ptr, prop, len, 0, 0, w, h, + expand, slider, toggle, icon_only, compact, !use_prop_sep); + } /* enum item */ else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) { if (icon && name[0] && !icon_only) @@ -1848,19 +1906,13 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } -static void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt) +void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt) { PanelType *pt = (PanelType *)arg_pt; + UI_paneltype_draw(C, pt, layout); - if (layout->context) { - CTX_store_set(C, layout->context); - } - - UI_popover_panel_from_type(C, layout, pt); - - if (layout->context) { - CTX_store_set(C, NULL); - } + /* panels are created flipped (from event handling pov) */ + layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } static uiBut *ui_item_menu( @@ -2935,6 +2987,7 @@ 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); BLI_addtail(&layout->items, litem); } @@ -3169,6 +3222,16 @@ void uiLayoutSetEmboss(uiLayout *layout, char emboss) layout->emboss = emboss; } +bool uiLayoutGetPropSep(uiLayout *layout) +{ + return (layout->item.flag & UI_ITEM_PROP_SEP) != 0; +} + +void uiLayoutSetPropSep(uiLayout *layout, bool is_sep) +{ + SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP); +} + bool uiLayoutGetActive(uiLayout *layout) { return layout->active; @@ -3740,3 +3803,32 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout) CTX_store_set(C, NULL); } } + +/** + * Used for popup panels only. + */ +void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout) +{ + Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); + panel->type = pt; + + if (layout->context) { + CTX_store_set(C, layout->context); + } + + if (pt->draw_header) { + panel->layout = uiLayoutRow(layout, false); + pt->draw_header(C, panel); + panel->layout = NULL; + } + + panel->layout = layout; + pt->draw(C, panel); + panel->layout = NULL; + + if (layout->context) { + CTX_store_set(C, NULL); + } + + MEM_freeN(panel); +} diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 7bf70b3d6fe..5711f76e3e9 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -753,12 +753,12 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con /* draw collapse icon */ /* itemrect smaller */ - itemrect.xmin = headrect.xmin + 5.0f / block->aspect; + itemrect.xmin = headrect.xmin + 3.0f / block->aspect; itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&headrect); itemrect.ymin = headrect.ymin; itemrect.ymax = headrect.ymax; - BLI_rctf_scale(&itemrect, 0.35f); + BLI_rctf_scale(&itemrect, 0.25f); if (is_closed_y) ui_draw_tria_rect(&itemrect, 'h'); diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index b6248d3daa1..9d10713c868 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -189,17 +189,20 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v UI_block_flag_enable(block, UI_BLOCK_LOOP); UI_block_direction_set(block, block->direction); block->minbounds = UI_MENU_WIDTH_MIN; + bool use_place_under_active = !handle->refresh; - uiBut *but = NULL; - for (but = block->buttons.first; but; but = but->next) { - if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) { - break; + if (use_place_under_active) { + uiBut *but = NULL; + for (but = block->buttons.first; but; but = but->next) { + if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) { + break; + } } - } - if (but) { - offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect)); - offset[1] = -(but->rect.ymin + 0.5f * BLI_rctf_size_y(&but->rect)); + if (but) { + offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect)); + offset[1] = -(but->rect.ymin + 0.5f * BLI_rctf_size_y(&but->rect)); + } } UI_block_bounds_set_popup(block, block_margin, offset[0], offset[1]); @@ -256,30 +259,9 @@ uiPopupBlockHandle *ui_popover_panel_create( /** \name Standard Popover Panels * \{ */ - -void UI_popover_panel_from_type(bContext *C, uiLayout *layout, PanelType *pt) -{ - /* TODO: move into UI_paneltype_draw */ - Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); - panel->type = pt; - - - if (pt->draw_header) { - panel->layout = uiLayoutRow(layout, false); - pt->draw_header(C, panel); - panel->layout = NULL; - } - - panel->layout = layout; - pt->draw(C, panel); - panel->layout = NULL; - - MEM_freeN(panel); -} - int UI_popover_panel_invoke( bContext *C, int space_id, int region_id, const char *idname, - ReportList *reports) + bool keep_open, ReportList *reports) { uiLayout *layout; PanelType *pt = UI_paneltype_find(space_id, region_id, idname); @@ -296,13 +278,15 @@ int UI_popover_panel_invoke( return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } - uiPopover *pup = UI_popover_begin(C); - - layout = UI_popover_layout(pup); - - UI_popover_panel_from_type(C, layout, pt); - - UI_popover_end(C, pup, NULL); + if (keep_open) { + ui_popover_panel_create(C, NULL, NULL, ui_item_paneltype_func, pt); + } + else { + uiPopover *pup = UI_popover_begin(C); + layout = UI_popover_layout(pup); + UI_paneltype_draw(C, pt, layout); + UI_popover_end(C, pup, NULL); + } return OPERATOR_INTERFACE; } @@ -371,6 +355,9 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap) * The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set. * For now close this style of popvers when accessed. */ UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN); + + /* panels are created flipped (from event handling pov) */ + pup->block->flag ^= UI_BLOCK_IS_FLIP; } uiLayout *UI_popover_layout(uiPopover *pup) @@ -386,7 +373,3 @@ void UI_popover_once_clear(uiPopover *pup) #endif /** \} */ - -/* We may want to support this in future */ -/* Similar to UI_popup_menu_invoke */ -// int UI_popover_panel_invoke(bContext *C, const char *idname, ReportList *reports); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 0cea9824249..e4faac5129e 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1881,7 +1881,9 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } #ifdef USE_NUMBUTS_LR_ALIGN - if (!drawstr_right && ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && + if (!drawstr_right && + (but->drawflag & UI_BUT_TEXT_LEFT) && + ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && /* if we're editing or multi-drag (fake editing), then use left alignment */ (but->editstr == NULL) && (drawstr == but->drawstr)) { @@ -4755,7 +4757,7 @@ void ui_draw_popover_back(ARegion *ar, uiStyle *UNUSED(style), uiBlock *block, r if (block) { float mval_origin[2] = {block->mx, block->my}; ui_window_to_block_fl(ar, block, &mval_origin[0], &mval_origin[1]); - ui_draw_popover_back_impl(&wcol_menu_back, rect, block->direction, mval_origin); + ui_draw_popover_back_impl(wt->wcol_theme, rect, block->direction, mval_origin); } else { wt->state(wt, 0); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index acfae0a6f0a..979a2164199 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -165,6 +165,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case SPACE_TOPBAR: ts = &btheme->ttopbar; break; + case SPACE_STATUSBAR: + ts = &btheme->tstatusbar; + break; default: ts = &btheme->tv3d; break; @@ -1238,6 +1241,9 @@ void ui_theme_init_default(void) copy_v4_v4_char(tmp, btheme->ttopbar.header); copy_v4_v4_char(btheme->ttopbar.header, btheme->ttopbar.tab_inactive); copy_v4_v4_char(btheme->ttopbar.back, tmp); + + /* space statusbar */ + btheme->tstatusbar = btheme->tv3d; } void ui_style_init_default(void) @@ -3001,6 +3007,12 @@ void init_userdef_do_versions(void) } } + if (!USER_VERSION_ATLEAST(280, 16)) { + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + btheme->tstatusbar = btheme->tv3d; + } + } + /** * Include next version bump. */ diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 4081e3b0302..64d890a7314 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -29,6 +29,8 @@ * \ingroup edmesh */ +#include "MEM_guardedalloc.h" + #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_mesh_types.h" @@ -41,6 +43,7 @@ #include "BLI_math.h" #include "BLI_linklist.h" +#include "BKE_layer.h" #include "BKE_context.h" #include "BKE_editmesh.h" #include "BKE_report.h" @@ -726,67 +729,87 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot) static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMesh *bm = em->bm; - BMIter iter; - BMEditSelection *ese_src, *ese_dst; - BMElem *ele_src = NULL, *ele_dst = NULL, *ele; + bool found_valid_elements = false; + + 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(view_layer, &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); + BMesh *bm = em->bm; + BMIter iter; + BMEditSelection *ese_src, *ese_dst; + BMElem *ele_src = NULL, *ele_dst = NULL, *ele; + + if ((em->bm->totvertsel == 0) && + (em->bm->totedgesel == 0) && + (em->bm->totfacesel == 0)) + { + continue; + } - /* first try to find vertices in edit selection */ - ese_src = bm->selected.last; - if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype == ese_dst->htype)) { - ele_src = ese_src->ele; - ele_dst = ese_dst->ele; - } - else { - /* if selection history isn't available, find two selected elements */ - ele_src = ele_dst = NULL; - if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) { - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - if (ele_src == NULL) ele_src = ele; - else if (ele_dst == NULL) ele_dst = ele; - else break; + /* first try to find vertices in edit selection */ + ese_src = bm->selected.last; + if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype == ese_dst->htype)) { + ele_src = ese_src->ele; + ele_dst = ese_dst->ele; + } + else { + /* if selection history isn't available, find two selected elements */ + ele_src = ele_dst = NULL; + if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) { + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + if (ele_src == NULL) ele_src = ele; + else if (ele_dst == NULL) ele_dst = ele; + else break; + } } } - } - if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) { - ele_src = NULL; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - if (ele_src == NULL) ele_src = ele; - else if (ele_dst == NULL) ele_dst = ele; - else break; + if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) { + ele_src = NULL; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + if (ele_src == NULL) ele_src = ele; + else if (ele_dst == NULL) ele_dst = ele; + else break; + } } } - } - if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) { - ele_src = NULL; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - if (ele_src == NULL) ele_src = ele; - else if (ele_dst == NULL) ele_dst = ele; - else break; + if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) { + ele_src = NULL; + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + if (ele_src == NULL) ele_src = ele; + else if (ele_dst == NULL) ele_dst = ele; + else break; + } } } } - } - if (ele_src && ele_dst) { - struct PathSelectParams op_params; - path_select_params_from_op(op, &op_params); + if (ele_src && ele_dst) { + struct PathSelectParams op_params; + path_select_params_from_op(op, &op_params); - edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst); + edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst); - return OPERATOR_FINISHED; + found_valid_elements = true; + } } - else { - BKE_report(op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected"); + MEM_freeN(objects); + + if (!found_valid_elements) { + BKE_report(op->reports, + RPT_WARNING, + "Path selection requires two matching elements to be selected"); return OPERATOR_CANCELLED; } + + return OPERATOR_FINISHED; } void MESH_OT_shortest_path_select(wmOperatorType *ot) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 11f87b3710d..fd8efcd84e3 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -397,6 +397,18 @@ bool EDBM_backbuf_circle_init( * to avoid the bias interfering with distance comparisons when mixing types. * \{ */ +#define FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, select_mode_required) \ + short select_mode = select_mode_required; \ + bool fake_select_mode = (select_mode & (vc)->scene->toolsettings->selectmode) == 0; \ + if (fake_select_mode) { \ + (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \ + } ((void)0) + +#define FAKE_SELECT_MODE_END(vc, fake_select_mode) \ + if (fake_select_mode) { \ + (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \ + } ((void)0) + #define FIND_NEAR_SELECT_BIAS 5 #define FIND_NEAR_CYCLE_THRESHOLD_MIN 3 @@ -470,11 +482,16 @@ BMVert *EDBM_vert_find_nearest_ex( BMVert *eve; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); + { + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX); + ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); - index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); - eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; + index = ED_view3d_backbuf_sample_rect( + vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); + eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; + + FAKE_SELECT_MODE_END(vc, fake_select_mode); + } if (eve) { if (dist_test < *r_dist) { @@ -657,23 +674,16 @@ BMEdge *EDBM_edge_find_nearest_ex( unsigned int index; BMEdge *eed; - /* Make sure that the edges also are considered to find nearest. - * TODO: cleanup: add `selectmode` as a parameter - * XXX: Without selectmode as parameter we need to resort to this super ugly hack, - * because we should never write to evaluate data. */ - const short ts_selectmode = vc->scene->toolsettings->selectmode; - - Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); - scene_eval->toolsettings->selectmode |= SCE_SELECT_EDGE; - /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); - - /* restore `selectmode` */ - scene_eval->toolsettings->selectmode = ts_selectmode; - - index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); - eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; + { + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE); + ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); + + index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); + eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; + + FAKE_SELECT_MODE_END(vc, fake_select_mode); + } if (r_eed_zbuf) { *r_eed_zbuf = eed; @@ -834,10 +844,15 @@ BMFace *EDBM_face_find_nearest_ex( unsigned int index; BMFace *efa; - ED_view3d_backbuf_validate(vc); + { + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE); + ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); + + index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); + efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; - index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); - efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; + FAKE_SELECT_MODE_END(vc, fake_select_mode); + } if (r_efa_zbuf) { *r_efa_zbuf = efa; @@ -1067,6 +1082,9 @@ static bool unified_findnearest( return (hit.v.ele || hit.e.ele || hit.f.ele); } +#undef FAKE_SELECT_MODE_BEGIN +#undef FAKE_SELECT_MODE_END + /** \} */ /* -------------------------------------------------------------------- */ @@ -1703,17 +1721,6 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de mvalf[1] = (float)(vc.mval[1] = mval[1]); em = vc.em; - /* Make sure that the edges are also considered for selection. - * TODO: cleanup: add `selectmode` as a parameter */ - const short ts_selectmode = vc.scene->toolsettings->selectmode; - vc.scene->toolsettings->selectmode |= SCE_SELECT_EDGE; - - /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */ - ED_view3d_backbuf_validate(&vc); - - /* restore `selectmode` */ - vc.scene->toolsettings->selectmode = ts_selectmode; - eed = EDBM_edge_find_nearest_ex(&vc, &dist, NULL, true, true, NULL); if (eed == NULL) { return false; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 77c90a6591b..07812cefb6b 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -372,7 +372,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_view3d_init_mats_rv3d(obedit, ar->regiondata); struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, + CTX_data_scene(C), CTX_data_depsgraph(C), 0, ar, CTX_wm_view3d(C)); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -444,7 +444,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op) break; case MESH_DELETE_EDGE: /* Erase Edges */ if (!(em->bm->totedgesel && - EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_FACES))) + EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES))) { continue; } @@ -2318,7 +2318,7 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Number of iterations to smooth the mesh", "", 1, 200); - RNA_def_float(ot->srna, "lambda_factor", 5e-5f, 1e-7f, 1000.0f, + RNA_def_float(ot->srna, "lambda_factor", 1.0f, 1e-7f, 1000.0f, "Lambda factor", "", 1e-7f, 1000.0f); RNA_def_float(ot->srna, "lambda_border", 5e-5f, 1e-7f, 1000.0f, "Lambda factor in border", "", 1e-7f, 1000.0f); @@ -5453,11 +5453,12 @@ static int edbm_split_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (em->bm->totfacesel == 0) { + if ((em->bm->totvertsel == 0) && + (em->bm->totedgesel == 0) && + (em->bm->totfacesel == 0)) + { continue; } - BMOperator bmop; EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, false); BMO_op_exec(em->bm, &bmop); diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 6b22521eedd..77514ca1e8e 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -631,6 +631,10 @@ static int apply_objects_internal( la->area_shape = LA_AREA_RECT; la->area_sizey = la->area_size; } + else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) { + la->area_shape = LA_AREA_ELLIPSE; + la->area_sizey = la->area_size; + } la->area_size *= rsmat[0][0]; la->area_sizey *= rsmat[1][1]; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 7fc3cb8863f..b8a5c138a57 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -428,7 +428,11 @@ static void PE_set_view3d_data(bContext *C, PEData *data) static bool PE_create_shape_tree(PEData *data, Object *shapeob) { - Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_object(shapeob, 0); + ModifierEvalContext ctx = { + .depsgraph = data->depsgraph, + .flag = 0, + }; + Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_object(&ctx, shapeob); memset(&data->shape_bvh, 0, sizeof(data->shape_bvh)); @@ -2959,7 +2963,7 @@ static void PE_mirror_x( } else { newpa->num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_deformed, newpa->num, newpa->fuv, NULL); + psmd->mesh_final, psmd->mesh_original, newpa->num, newpa->fuv, NULL); } /* update edit key pointers */ @@ -3553,7 +3557,7 @@ static int brush_add(const bContext *C, PEData *data, short number) mesh = psmd->mesh_final; } else { - mesh = psmd->mesh_deformed; + mesh = psmd->mesh_original; } BLI_assert(mesh); @@ -3587,11 +3591,11 @@ static int brush_add(const bContext *C, PEData *data, short number) add_pars[n].num = add_pars[n].num_dmcache; add_pars[n].num_dmcache = DMCACHE_ISCHILD; } - else if (mesh == psmd->mesh_deformed) { + else if (mesh == psmd->mesh_original) { /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */ add_pars[n].num = add_pars[n].num_dmcache; add_pars[n].num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_deformed, + psmd->mesh_final, psmd->mesh_original, add_pars[n].num, add_pars[n].fuv, NULL); } else { diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index cb7c90a6c3d..55f518a2a8c 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -680,7 +680,7 @@ static bool remap_hair_emitter( mesh = target_psmd->mesh_final; } else { - mesh = target_psmd->mesh_deformed; + mesh = target_psmd->mesh_original; } target_mesh = target_psmd->mesh_final; if (mesh == NULL) { diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c index b6608ce600f..677fc0a068e 100644 --- a/source/blender/editors/scene/scene_edit.c +++ b/source/blender/editors/scene/scene_edit.c @@ -116,7 +116,7 @@ bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene) static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new) { - ViewLayer *layer_new = BKE_workspace_view_layer_get(workspace, scene_new); + ViewLayer *layer_new = BKE_workspace_view_layer_exists(workspace, scene_new); return layer_new ? layer_new : BKE_view_layer_default_view(scene_new); } @@ -202,10 +202,11 @@ bool ED_scene_view_layer_delete( BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false); ED_workspace_view_layer_unset(bmain, scene, layer, scene->view_layers.first); - BKE_workspace_view_layer_remove_references(bmain, layer); BKE_view_layer_free(layer); + BKE_workspace_view_layer_remove(bmain, layer); + DEG_id_tag_update(&scene->id, 0); DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6392af2a5e0..9b7f767798f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -147,6 +147,14 @@ int ED_operator_screen_mainwinactive(bContext *C) return 1; } +int ED_operator_scene(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + if (scene) + return 1; + return 0; +} + int ED_operator_scene_editable(bContext *C) { Scene *scene = CTX_data_scene(C); @@ -4720,10 +4728,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf) RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); - WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0); - kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "use_hide_panels", true); WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index a054949df22..d54996bad59 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -110,7 +110,7 @@ static void workspace_change_update_view_layer( WorkSpace *workspace_new, const WorkSpace *workspace_old, Scene *scene) { - if (!BKE_workspace_view_layer_get(workspace_new, scene)) { + if (!BKE_workspace_view_layer_exists(workspace_new, scene)) { BKE_workspace_view_layer_set(workspace_new, BKE_workspace_view_layer_get(workspace_old, scene), scene); } } @@ -199,7 +199,7 @@ bool ED_workspace_change( screen_change_update(C, win, screen_new); workspace_change_update(workspace_new, workspace_old, C, wm); - BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL); + BLI_assert(BKE_workspace_view_layer_exists(workspace_new, CTX_data_scene(C)) != NULL); BLI_assert(CTX_wm_workspace(C) == workspace_new); WM_toolsystem_unlink_all(C, workspace_old); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 0479af3c58f..9ecdc44cd10 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -299,7 +299,7 @@ static int image_paint_poll(bContext *C) return image_paint_poll_ex(C, true); } -static int image_paint_poll_ignore_tool(bContext *C) +static int image_paint_ignore_tool_poll(bContext *C) { return image_paint_poll_ex(C, false); } @@ -1011,11 +1011,6 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int sample_color_poll(bContext *C) -{ - return (image_paint_poll_ignore_tool(C) || image_paint_poll_ignore_tool(C)); -} - void PAINT_OT_sample_color(wmOperatorType *ot) { /* identifiers */ @@ -1027,7 +1022,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot) ot->exec = sample_color_exec; ot->invoke = sample_color_invoke; ot->modal = sample_color_modal; - ot->poll = sample_color_poll; + ot->poll = image_paint_ignore_tool_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index a1435d5916a..76449b61d4d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -81,6 +81,7 @@ #include "BKE_texture.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "UI_interface.h" @@ -3083,7 +3084,7 @@ static void proj_paint_state_non_cddm_init(ProjPaintState *ps) } static void proj_paint_state_viewport_init( - ProjPaintState *ps, const char symmetry_flag) + ProjPaintState *ps, const Depsgraph *depsgraph, const char symmetry_flag) { float mat[3][3]; float viewmat[4][4]; @@ -3144,17 +3145,17 @@ static void proj_paint_state_viewport_init( invert_m4_m4(viewinv, viewmat); } else if (ps->source == PROJ_SRC_IMAGE_CAM) { - Object *cam_ob = ps->scene->camera; + Object *cam_ob_eval = DEG_get_evaluated_object(depsgraph, ps->scene->camera); CameraParams params; /* viewmat & viewinv */ - copy_m4_m4(viewinv, cam_ob->obmat); + copy_m4_m4(viewinv, cam_ob_eval->obmat); normalize_m4(viewinv); invert_m4_m4(viewmat, viewinv); /* window matrix, clipping and ortho */ BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, cam_ob); + BKE_camera_params_from_object(¶ms, cam_ob_eval); BKE_camera_params_compute_viewplane(¶ms, ps->winx, ps->winy, 1.0f, 1.0f); BKE_camera_params_compute_matrix(¶ms); @@ -3858,7 +3859,7 @@ static void project_paint_begin( proj_paint_state_cavity_init(ps); } - proj_paint_state_viewport_init(ps, symmetry_flag); + proj_paint_state_viewport_init(ps, CTX_data_depsgraph(C), symmetry_flag); /* calculate vert screen coords * run this early so we can calculate the x/y resolution of our bucket rect */ diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index f8888ad9809..b2f3c49cb00 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -50,13 +50,15 @@ #include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_DerivedMesh.h" +#include "BKE_customdata.h" #include "BKE_image.h" #include "BKE_material.h" +#include "BKE_object.h" #include "BKE_paint.h" #include "BKE_report.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "RNA_access.h" #include "RNA_define.h" @@ -274,26 +276,26 @@ static void imapaint_tri_weights(float matrix[4][4], GLint view[4], } /* compute uv coordinates of mouse in face */ -static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) +static void imapaint_pick_uv(Mesh *me_eval, Scene *scene, Object *ob_eval, unsigned int faceindex, const int xy[2], float uv[2]) { - DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH); - const int tottri = dm->getNumLoopTri(dm); + const int tottri = me_eval->runtime.looptris.len; int i, findex; float p[2], w[3], absw, minabsw; float matrix[4][4], proj[4][4]; GLint view[4]; const eImagePaintMode mode = scene->toolsettings->imapaint.mode; - const MLoopTri *lt = dm->getLoopTriArray(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - const MLoop *mloop = dm->getLoopArray(dm); - const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + const MLoopTri *lt = me_eval->runtime.looptris.array; + const MVert *mvert = me_eval->mvert; + const MPoly *mpoly = me_eval->mpoly; + const MLoop *mloop = me_eval->mloop; + const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); /* get the needed opengl matrices */ glGetIntegerv(GL_VIEWPORT, view); gpuGetModelViewMatrix(matrix); gpuGetProjectionMatrix(proj); view[0] = view[1] = 0; - mul_m4_m4m4(matrix, matrix, ob->obmat); + mul_m4_m4m4(matrix, matrix, ob_eval->obmat); mul_m4_m4m4(matrix, proj, matrix); minabsw = 1e10; @@ -310,25 +312,25 @@ static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, uns const MLoopUV *tri_uv[3]; float tri_co[3][3]; - dm->getVertCo(dm, mloop[lt->tri[0]].v, tri_co[0]); - dm->getVertCo(dm, mloop[lt->tri[1]].v, tri_co[1]); - dm->getVertCo(dm, mloop[lt->tri[2]].v, tri_co[2]); + for (int j = 3; j--; ) { + copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co); + } if (mode == IMAGEPAINT_MODE_MATERIAL) { const Material *ma; const TexPaintSlot *slot; - ma = dm->mat[mp->mat_nr]; + ma = give_current_material(ob_eval, mp->mat_nr); slot = &ma->texpaintslot[ma->paint_active_slot]; if (!(slot && slot->uvname && - (mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, slot->uvname)))) + (mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname)))) { - mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV); + mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV); } } else { - mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV); + mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV); } tri_uv[0] = &mloopuv[lt->tri[0]]; @@ -347,8 +349,6 @@ static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, uns } } } - - dm->release(dm); } /* returns 0 if not found, otherwise 1 */ @@ -452,20 +452,21 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr /* first try getting a colour directly from the mesh faces if possible */ ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); bool sample_success = false; ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); if (ob) { Mesh *me = (Mesh *)ob->data; - DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH); + Mesh *me_eval = BKE_object_get_evaluated_mesh(depsgraph, ob); /* Or shall we just do ob_eval->mesh_evaluated ? */ ViewContext vc; const int mval[2] = {x, y}; unsigned int faceindex; unsigned int totpoly = me->totpoly; - if (dm->getLoopDataArray(dm, CD_MLOOPUV)) { + if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) { ED_view3d_viewcontext_init(C, &vc); view3d_operator_needs_opengl(C); @@ -474,7 +475,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr Image *image; if (use_material) - image = imapaint_face_image(ob, me, faceindex); + image = imapaint_face_image(ob_eval, me_eval, faceindex); else image = imapaint->canvas; @@ -483,7 +484,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr if (ibuf && ibuf->rect) { float uv[2]; float u, v; - imapaint_pick_uv(depsgraph, scene, ob, faceindex, mval, uv); + imapaint_pick_uv(me_eval, scene, ob_eval, faceindex, mval, uv); sample_success = true; u = fmodf(uv[0], 1.0f); @@ -525,7 +526,6 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr } } } - dm->release(dm); } if (!sample_success) { diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 2a0be4eaf0d..cb826d86a21 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -379,6 +379,52 @@ static void action_channel_region_listener( } } +static void saction_channel_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * also same applies for all animation-related datatypes that may appear here, + * so just whitelist the entire structs for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, /* dopesheet filters */ + + &RNA_ActionGroup, /* channel groups */ + + &RNA_FCurve, /* F-Curve */ + &RNA_Keyframe, + &RNA_FCurveSample, + + &RNA_GreasePencil, /* Grease Pencil */ + &RNA_GPencilLayer, + &RNA_GPencilFrame, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + } +} + static void action_main_region_listener( bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) @@ -435,8 +481,8 @@ static void action_main_region_listener( } static void saction_main_region_message_subscribe( - const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), struct Scene *scene, + const struct bContext *C, + struct WorkSpace *workspace, struct Scene *scene, struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, struct wmMsgBus *mbus) { @@ -472,6 +518,9 @@ static void saction_main_region_message_subscribe( WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__); } } + + /* Now run the general "channels region" one - since channels and main should be in sync */ + saction_channel_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus); } /* editor level listener */ @@ -835,6 +884,7 @@ void ED_spacetype_action(void) art->init = action_channel_region_init; art->draw = action_channel_region_draw; art->listener = action_channel_region_listener; + art->message_subscribe = saction_channel_region_message_subscribe; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 8d3647def9e..6ecb454096d 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -525,6 +525,42 @@ static void graph_region_message_subscribe( WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__); } } + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * also same applies for all animation-related datatypes that may appear here, + * so just whitelist the entire structs for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, /* dopesheet filters */ + + &RNA_ActionGroup, /* channel groups */ + &RNA_FCurve, /* F-Curve */ + &RNA_Keyframe, + &RNA_FCurveSample, + + &RNA_FModifier, /* F-Modifiers (XXX: Why can't we just do all subclasses too?) */ + &RNA_FModifierCycles, + &RNA_FModifierEnvelope, + &RNA_FModifierEnvelopeControlPoint, + &RNA_FModifierFunctionGenerator, + &RNA_FModifierGenerator, + &RNA_FModifierLimits, + &RNA_FModifierNoise, + &RNA_FModifierPython, + &RNA_FModifierStepped, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + } } /* editor level listener */ @@ -810,6 +846,7 @@ void ED_spacetype_ipo(void) art->prefsizex = 200 + V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES; art->listener = graph_region_listener; + art->message_subscribe = graph_region_message_subscribe; art->init = graph_channel_region_init; art->draw = graph_channel_region_draw; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 1943cb2c00b..c303a78594d 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -171,12 +171,12 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce simage->spacetype = SPACE_IMAGE; simage->zoom = 1.0f; simage->lock = true; - simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA; + simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS; simage->iuser.ok = true; simage->iuser.fie_ima = 2; simage->iuser.frames = 100; - simage->iuser.flag = IMA_SHOW_STEREO; + simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS; scopes_new(&simage->scopes); simage->sample_line_hist.height = 100; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index dfcf5fd5d8d..d2bfcfa76df 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -410,6 +410,7 @@ static void stats_string(ViewLayer *view_layer) 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; @@ -445,20 +446,25 @@ static void stats_string(ViewLayer *view_layer) /* get memory statistics */ - ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"), - (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); - if (mmap_in_use) - BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, true); + ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem: %s"), formatted_mem); + + if (mmap_in_use) { + BLI_str_format_byte_unit(formatted_mem, mmap_in_use, true); + BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%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); - ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0); + BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, true); + ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem: %s"), formatted_mem); if (gpu_tot_memory) { - BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0); + BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, true); + BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%s"), formatted_mem); } } diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 7245fd9c17f..e56fc12c75b 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -527,6 +527,41 @@ static void nla_channel_region_listener( } } +static void nla_channel_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * so just whitelist the entire struct for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + } +} + /* editor level listener */ static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), WorkSpace *UNUSED(workspace)) @@ -628,6 +663,7 @@ void ED_spacetype_nla(void) art->init = nla_channel_region_init; art->draw = nla_channel_region_draw; art->listener = nla_channel_region_listener; + art->message_subscribe = nla_channel_region_message_subscribe; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index ca6ae5955a9..19e2ae9808a 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1021,6 +1021,21 @@ static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), Pointer uiItemR(layout, ptr, "component", 0, "", ICON_NONE); } +static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *row; + + row = uiLayoutRow(layout, false); + uiItemR(row, ptr, "mode", 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); + else + uiItemR(row, ptr, "filepath", 0, "", ICON_NONE); +} + static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *row; @@ -1189,6 +1204,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_OUTPUT_LINESTYLE: ntype->draw_buttons = node_buts_output_linestyle; break; + case SH_NODE_TEX_IES: + ntype->draw_buttons = node_shader_buts_ies; + break; case SH_NODE_BEVEL: ntype->draw_buttons = node_shader_buts_bevel; break; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 883078bc83c..172669ed122 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -402,7 +402,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) BLI_strncpy(view_layer->name, oldname, sizeof(view_layer->name)); /* Rename, preserving animation and compositing data. */ - BKE_view_layer_rename(scene, view_layer, newname); + BKE_view_layer_rename(bmain, scene, view_layer, newname); WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break; } diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 73494b890ed..7ca1bc9cc9b 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -191,7 +191,6 @@ typedef enum { void outliner_free_tree(ListBase *tree); void outliner_cleanup_tree(struct SpaceOops *soops); void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree); -void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem); void outliner_build_tree( struct Main *mainvar, diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index f42addb30bf..d865896e524 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -153,6 +153,9 @@ static void outliner_storage_cleanup(SpaceOops *soops) } } } + else if (soops->treehash) { + BKE_outliner_treehash_clear_used(soops->treehash); + } } } @@ -813,8 +816,11 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor } case ID_GR: { - Collection *collection = (Collection *)id; - outliner_add_collection_recursive(soops, collection, te); + /* Don't expand for instances, creates too many elements. */ + if (!(te->parent && te->parent->idcode == ID_OB)) { + Collection *collection = (Collection *)id; + outliner_add_collection_recursive(soops, collection, te); + } } default: break; @@ -1182,15 +1188,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i return te; } -/** - * \note Really only removes \a tselem, not it's TreeElement instance or any children. - */ -void outliner_remove_treestore_element(SpaceOops *soops, TreeStoreElem *tselem) -{ - BKE_outliner_treehash_remove_element(soops->treehash, tselem); - BLI_mempool_free(soops->treestore, tselem); -} - /* ======================================================= */ /* Sequencer mode tree building */ diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index 896f6c016d0..6b7035dd326 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -142,13 +142,11 @@ TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id) if (tselem->id == id) { return te; } - /* only deeper on scene collection or object */ - if (ELEM(te->idcode, ID_OB, ID_SCE, ID_GR)) { - TreeElement *tes = outliner_find_id(soops, &te->subtree, id); - if (tes) { - return tes; - } - } + } + + TreeElement *tes = outliner_find_id(soops, &te->subtree, id); + if (tes) { + return tes; } } return NULL; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 8e04a2e17b8..b87d6c0b85e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -610,9 +610,13 @@ static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob) } void draw_object_backbufsel( - Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) + Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, + short select_mode) { ToolSettings *ts = scene->toolsettings; + if (select_mode == -1) { + select_mode = ts->selectmode; + } gpuMultMatrix(ob->obmat); @@ -631,8 +635,8 @@ void draw_object_backbufsel( DM_update_materials(dm, ob); - bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (ts->selectmode & SCE_SELECT_FACE) != 0); - if (ts->selectmode & SCE_SELECT_FACE) + bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (select_mode & SCE_SELECT_FACE) != 0); + if (select_mode & SCE_SELECT_FACE) bm_solidoffs = 1 + em->bm->totface; else { bm_solidoffs = 1; @@ -641,7 +645,7 @@ void draw_object_backbufsel( ED_view3d_polygon_offset(rv3d, 1.0); /* we draw edges if edge select mode */ - if (ts->selectmode & SCE_SELECT_EDGE) { + if (select_mode & SCE_SELECT_EDGE) { bbs_mesh_wire(em, dm, bm_solidoffs); bm_wireoffs = bm_solidoffs + em->bm->totedge; } @@ -651,7 +655,7 @@ void draw_object_backbufsel( } /* we draw verts if vert select mode. */ - if (ts->selectmode & SCE_SELECT_VERTEX) { + if (select_mode & SCE_SELECT_VERTEX) { bbs_mesh_verts(em, dm, bm_wireoffs); bm_vertoffs = bm_wireoffs + em->bm->totvert; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 99f7abba065..b44e2da3583 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -302,6 +302,7 @@ static void view3d_camera_border( { CameraParams params; rctf rect_view, rect_camera; + Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); /* get viewport viewplane */ BKE_camera_params_init(¶ms); @@ -316,7 +317,7 @@ static void view3d_camera_border( /* fallback for non camera objects */ params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); + BKE_camera_params_from_object(¶ms, camera_eval); if (no_shift) { params.shiftx = 0.0f; params.shifty = 0.0f; @@ -1172,7 +1173,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) if (U.uiflag & USER_SHOW_ROTVIEWICON) offset = U.widget_unit + (U.rvisize * 2) + rect->xmin; - BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); + BLF_draw_default(offset, rect->ymin + 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); } /* ******************** view loop ***************** */ @@ -1417,13 +1418,16 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( if (rv3d->persp == RV3D_CAMOB && v3d->camera) { CameraParams params; Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + const Object *camera_eval = DEG_get_evaluated_object( + depsgraph, + camera); BKE_camera_params_init(¶ms); /* fallback for non camera objects */ params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, camera); - BKE_camera_multiview_params(&scene->r, ¶ms, camera, viewname); + BKE_camera_params_from_object(¶ms, camera_eval); + BKE_camera_multiview_params(&scene->r, ¶ms, camera_eval, viewname); BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); @@ -1597,11 +1601,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( { CameraParams params; - Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname); + const Object *view_camera_eval = DEG_get_evaluated_object( + depsgraph, + BKE_camera_multiview_render(scene, v3d.camera, viewname)); BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, view_camera); - BKE_camera_multiview_params(&scene->r, ¶ms, view_camera, viewname); + BKE_camera_params_from_object(¶ms, view_camera_eval); + BKE_camera_multiview_params(&scene->r, ¶ms, view_camera_eval, viewname); BKE_camera_params_compute_viewplane(¶ms, width, height, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 5b0f50b7a68..8505de4c7e0 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -163,7 +163,8 @@ bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const static void backdrawview3d( struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, - Object *obact, Object *obedit) + Object *obact, Object *obedit, + short select_mode) { RegionView3D *rv3d = ar->regiondata; Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); @@ -263,7 +264,7 @@ static void backdrawview3d( G.f |= G_BACKBUFSEL; if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLED) != 0)) { - draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval); + draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); } if (rv3d->gpuoffscreen) @@ -301,13 +302,18 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } -void ED_view3d_backbuf_validate(ViewContext *vc) +void ED_view3d_backbuf_validate_with_select_mode(ViewContext *vc, short select_mode) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit); + backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode); } } +void ED_view3d_backbuf_validate(ViewContext *vc) +{ + ED_view3d_backbuf_validate_with_select_mode(vc, -1); +} + /** * allow for small values [0.5 - 2.5], * and large values, FLT_MAX by clamping by the area size diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 29a61fdf969..3f59a5db9b3 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1110,7 +1110,7 @@ static void view3d_ndof_pan_zoom( static void view3d_ndof_orbit( const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, /* optional, can be NULL*/ - ViewOpsData *vod) + ViewOpsData *vod, const bool apply_dyn_ofs) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; @@ -1173,7 +1173,7 @@ static void view3d_ndof_orbit( mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); } - if (vod) { + if (apply_dyn_ofs) { viewrotate_apply_dyn_ofs(vod, rv3d->viewquat); } } @@ -1342,7 +1342,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) } if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); } } @@ -1424,7 +1424,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); } } else { /* free/explore (like fly mode) */ @@ -1442,7 +1442,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev ED_view3d_distance_set(rv3d, 0.0f); if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false); } ED_view3d_distance_set(rv3d, dist_backup); @@ -2654,7 +2654,7 @@ static void view3d_from_minmax( } if (ok_dist) { - new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN); + new_dist = ED_view3d_radius_to_dist(v3d, ar, CTX_data_depsgraph(C), persp, true, (size / 2) * VIEW3D_MARGIN); if (rv3d->is_persp) { /* don't zoom closer than the near clipping plane */ new_dist = max_ff(new_dist, v3d->near * 1.5f); @@ -2765,6 +2765,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op) view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx); } + if (center) { + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); + } + return OPERATOR_FINISHED; } @@ -3678,7 +3682,8 @@ static void axis_set_view( dist = rv3d->dist; /* so we animate _from_ the camera location */ - ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, &rv3d->dist, NULL); + Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera); + ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL); ED_view3d_smooth_view( C, v3d, ar, smooth_viewtx, @@ -4599,12 +4604,11 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) cursor_curr->rotation[0] *= -1.0f; { - struct Main *bmain = CTX_data_main(C); const float mval_fl[2] = {UNPACK2(mval)}; float ray_no[3]; struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d); + scene, CTX_data_depsgraph(C), 0, ar, v3d); float obmat[4][4]; Object *ob_dummy = NULL; diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 0ee9adfc396..e0f3c412c56 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -225,18 +225,18 @@ void VIEW3D_OT_layers(wmOperatorType *ot) /** \name Toggle Bone selection Overlay Operator * \{ */ -static int toggle_show_see_through(bContext *C, wmOperator *UNUSED(op)) +static int toggle_show_xray(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d = CTX_wm_view3d(C); - v3d->shading.flag ^= V3D_SHADING_SEE_THROUGH; + v3d->shading.flag ^= V3D_SHADING_XRAY; ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C)); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); return OPERATOR_FINISHED; } -static int toggle_show_see_through_poll(bContext *C) +static int toggle_show_xray_poll(bContext *C) { - bool result = (ED_operator_view3d_active(C) && !ED_operator_posemode(C)); + bool result = (ED_operator_view3d_active(C) && !ED_operator_posemode(C) && !ED_operator_editmesh(C)); if (result) { // Additional test for SOLID or TEXTURE mode View3D *v3d = CTX_wm_view3d(C); @@ -245,16 +245,16 @@ static int toggle_show_see_through_poll(bContext *C) return result; } -void VIEW3D_OT_toggle_see_through_draw_option(wmOperatorType *ot) +void VIEW3D_OT_toggle_xray_draw_option(wmOperatorType *ot) { /* identifiers */ - ot->name = "Toggle Show See Though"; - ot->description = "Toggle show see through"; - ot->idname = "VIEW3D_OT_toggle_see_through_draw_option"; + ot->name = "Toggle Show X-Ray"; + ot->description = "Toggle show X-Ray"; + ot->idname = "VIEW3D_OT_toggle_xray_draw_option"; /* api callbacks */ - ot->exec = toggle_show_see_through; - ot->poll = toggle_show_see_through_poll; + ot->exec = toggle_show_xray; + ot->poll = toggle_show_xray_poll; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 794ca0dcad9..da8afa7a390 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -65,7 +65,7 @@ enum { /* view3d_header.c */ void VIEW3D_OT_layers(struct wmOperatorType *ot); -void VIEW3D_OT_toggle_see_through_draw_option(struct wmOperatorType *ot); +void VIEW3D_OT_toggle_xray_draw_option(struct wmOperatorType *ot); /* view3d_ops.c */ void view3d_operatortypes(void); @@ -133,7 +133,9 @@ void VIEW3D_OT_walk(struct wmOperatorType *ot); void VIEW3D_OT_ruler(struct wmOperatorType *ot); /* drawobject.c */ -void draw_object_backbufsel(struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); +void draw_object_backbufsel( + struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, + short select_mode); int view3d_effective_drawtype(const struct View3D *v3d); diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 35127c7c8c6..145f57174fd 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -35,6 +35,7 @@ #include "BLI_utildefines.h" #include "BLI_rect.h" +#include "BKE_action.h" #include "BKE_armature.h" #include "BKE_curve.h" #include "BKE_DerivedMesh.h" @@ -43,6 +44,7 @@ #include "BKE_context.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "bmesh.h" @@ -449,19 +451,21 @@ void pose_foreachScreenBone( void (*func)(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]), void *userData, const eV3DProjTest clip_flag) { - bArmature *arm = vc->obact->data; + const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + const bArmature *arm_eval = ob_eval->data; bPose *pose = vc->obact->pose; bPoseChannel *pchan; ED_view3d_check_mats_rv3d(vc->rv3d); for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if (PBONE_VISIBLE(arm, pchan->bone)) { + if (PBONE_VISIBLE(arm_eval, pchan->bone)) { + bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); float screen_co_a[2], screen_co_b[2]; int points_proj_tot = 0; /* project head location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, pchan->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { points_proj_tot++; } else { @@ -470,7 +474,7 @@ void pose_foreachScreenBone( } /* project tail location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, pchan->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { points_proj_tot++; } else { diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c index 87e550ba638..d3fe17123a0 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c @@ -132,7 +132,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mg struct CameraWidgetGroup *camgroup = mgroup->customdata; Object *ob = CTX_data_active_object(C); const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - Camera *ca = ob->data; + Camera *ca = ob_eval->data; PointerRNA camera_ptr; float dir[3]; @@ -252,6 +252,7 @@ static void WIDGETGROUP_camera_message_subscribe( extern PropertyRNA rna_Camera_shift_x; extern PropertyRNA rna_Camera_shift_y; extern PropertyRNA rna_Camera_type; + extern PropertyRNA rna_Camera_lens; const PropertyRNA *props[] = { &rna_Camera_dof_distance, &rna_Camera_draw_size, @@ -261,6 +262,7 @@ static void WIDGETGROUP_camera_message_subscribe( &rna_Camera_shift_x, &rna_Camera_shift_y, &rna_Camera_type, + &rna_Camera_lens, }; PointerRNA idptr; diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c index 93b6b69a105..e659c67396d 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c @@ -45,6 +45,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "DEG_depsgraph_query.h" + #include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -80,16 +82,18 @@ static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulator static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmManipulatorGroup *mgroup) { + const Depsgraph *depsgraph = CTX_data_depsgraph(C); wmManipulatorWrapper *wwrapper = mgroup->customdata; wmManipulator *mpr = wwrapper->manipulator; Object *ob = CTX_data_active_object(C); + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); Lamp *la = ob->data; float dir[3]; - negate_v3_v3(dir, ob->obmat[2]); + negate_v3_v3(dir, ob_eval->obmat[2]); WM_manipulator_set_matrix_rotation_from_z_axis(mpr, dir); - WM_manipulator_set_matrix_location(mpr, ob->obmat[3]); + WM_manipulator_set_matrix_location(mpr, ob_eval->obmat[3]); /* need to set property here for undo. TODO would prefer to do this in _init */ PointerRNA lamp_ptr; @@ -129,7 +133,7 @@ static void manipulator_area_lamp_prop_matrix_get( const Lamp *la = mpr_prop->custom_func.user_data; matrix[0][0] = la->area_size; - matrix[1][1] = (la->area_shape == LA_AREA_RECT) ? la->area_sizey : la->area_size; + matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey : la->area_size; } static void manipulator_area_lamp_prop_matrix_set( @@ -140,7 +144,7 @@ static void manipulator_area_lamp_prop_matrix_set( BLI_assert(mpr_prop->type->array_length == 16); Lamp *la = mpr_prop->custom_func.user_data; - if (la->area_shape == LA_AREA_RECT) { + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { la->area_size = len_v3(matrix[0]); la->area_sizey = len_v3(matrix[1]); } @@ -179,15 +183,19 @@ static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmManipulator static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmManipulatorGroup *mgroup) { wmManipulatorWrapper *wwrapper = mgroup->customdata; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); Object *ob = CTX_data_active_object(C); - Lamp *la = ob->data; + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + Lamp *la = ob_eval->data; wmManipulator *mpr = wwrapper->manipulator; - copy_m4_m4(mpr->matrix_basis, ob->obmat); + copy_m4_m4(mpr->matrix_basis, ob_eval->obmat); - RNA_enum_set(mpr->ptr, "transform", - ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | - ((la->area_shape == LA_AREA_SQUARE) ? ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM : 0)); + int flag = ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE; + if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) { + flag |= ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM; + } + RNA_enum_set(mpr->ptr, "transform", flag); /* need to set property here for undo. TODO would prefer to do this in _init */ WM_manipulator_target_property_def_func( @@ -264,10 +272,12 @@ static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmManipulat static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) { wmManipulatorWrapper *wwrapper = mgroup->customdata; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); Object *ob = CTX_data_active_object(C); + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); wmManipulator *mpr = wwrapper->manipulator; - copy_m4_m4(mpr->matrix_basis, ob->obmat); + copy_m4_m4(mpr->matrix_basis, ob_eval->obmat); unit_m4(mpr->matrix_offset); mpr->matrix_offset[3][2] = -2.4f / mpr->scale_basis; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c index 8c3b28ffdd8..9cde5ffc5e3 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c @@ -278,7 +278,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, + CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index dd168c26f07..4d362ae5425 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -112,7 +112,7 @@ static void VIEW3D_OT_copybuffer(wmOperatorType *ot) /* api callbacks */ ot->exec = view3d_copybuffer_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_scene; } static int view3d_pastebuffer_exec(bContext *C, wmOperator *op) @@ -149,7 +149,7 @@ static void VIEW3D_OT_pastebuffer(wmOperatorType *ot) /* api callbacks */ ot->exec = view3d_pastebuffer_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_scene_editable; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -222,7 +222,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active); WM_operatortype_append(VIEW3D_OT_toggle_render); - WM_operatortype_append(VIEW3D_OT_toggle_see_through_draw_option); + WM_operatortype_append(VIEW3D_OT_toggle_xray_draw_option); WM_operatortype_append(VIEW3D_OT_ruler_add); @@ -409,7 +409,7 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_string_set(kmi->ptr, "value_2", "TEXTURED"); WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_render", ZKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_see_through_draw_option", ZKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_xray_draw_option", ZKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", ZKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.use_occlude_geometry"); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index eb86800f4a9..d0fb82eaaf4 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -282,6 +282,11 @@ float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3]) return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; } +float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3]) +{ + return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize; +} + /** * Calculate a depth value from \a co, use with #ED_view3d_win_to_delta */ diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index 5b616f29c60..c0af3c7caaa 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -282,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, + CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 711bdac9dc0..be5653a3021 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -2122,25 +2122,24 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b continue; } /* Loop over contiguous bone hits for 'base'. */ - bool bone_selected = false; + bool changed = false; for (; col != col_end; col += 4) { /* should never fail */ if (bone != NULL) { if (select) { if ((bone->flag & BONE_UNSELECTABLE) == 0) { bone->flag |= BONE_SELECTED; - bone_selected = true; } } else { bArmature *arm = base->object->data; if ((bone->flag & BONE_UNSELECTABLE) == 0) { bone->flag &= ~BONE_SELECTED; - bone_selected = true; if (arm->act_bone == bone) arm->act_bone = NULL; } } + changed = true; } else if (!bone_only) { ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); @@ -2154,7 +2153,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b if ((base->object->pose != NULL) && bone_only) { const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16; - bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);; + bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone); bone = pchan ? pchan->bone : NULL; } else { @@ -2163,7 +2162,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b } } - if (bone_selected) { + if (changed) { if (base->object && (base->object->type == OB_ARMATURE)) { bArmature *arm = base->object->data; @@ -2174,6 +2173,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); } + /* copy on write tag is needed (for the armature), or else no refresh happens */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } } @@ -2750,6 +2751,9 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva /* mask modifier ('armature' mode), etc. */ DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); } + + /* copy on write tag is needed (for the armature), or else no refresh happens */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index e18370d04a9..90b1b043de6 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -1067,6 +1067,7 @@ float ED_view3d_radius_to_dist_ortho(const float lens, const float radius) */ float ED_view3d_radius_to_dist( const View3D *v3d, const ARegion *ar, + const struct Depsgraph *depsgraph, const char persp, const bool use_aspect, const float radius) { @@ -1087,7 +1088,8 @@ float ED_view3d_radius_to_dist( BKE_camera_params_init(¶ms); params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); + Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + BKE_camera_params_from_object(¶ms, camera_eval); lens = params.lens; sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); @@ -1277,7 +1279,7 @@ bool ED_view3d_lock(RegionView3D *rv3d) * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. * \param dist The view distance from ofs, normally from RegionView3D.dist. */ -void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) +void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist) { float nmat[3][3]; @@ -1322,13 +1324,14 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c /** * Set the RegionView3D members from an objects transformation and optionally lens. + * \param depsgraph The depsgraph to get the evaluated object for the lens calculation. * \param ob The object to set the view to. * \param ofs The view offset to be set, normally from RegionView3D.ofs. * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat. * \param dist The view distance from ofs to be set, normally from RegionView3D.dist. * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens. */ -void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens) +void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens) { ED_view3d_from_m4(ob->obmat, ofs, quat, dist); @@ -1343,6 +1346,7 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, /** * Set the object transformation from RegionView3D members. + * \param depsgraph The depsgraph to get the evaluated object parent for the transformation calculation. * \param ob The object which has the transformation assigned. * \param ofs The view offset, normally from RegionView3D.ofs. * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 2fe95f596c8..0a490a8b494 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -48,6 +48,7 @@ #include "BKE_scene.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "UI_resources.h" @@ -62,8 +63,6 @@ #include "DRW_engine.h" -#include "DEG_depsgraph_query.h" - #include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -513,25 +512,26 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ Object *camera_ob = v3d ? v3d->camera : scene->camera; + Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); float r_co[3]; /* the new location to apply */ float r_scale; /* only for ortho cameras */ - if (camera_ob == NULL) { + if (camera_ob_eval == NULL) { BKE_report(op->reports, RPT_ERROR, "No active camera"); return OPERATOR_CANCELLED; } /* this function does all the important stuff */ - if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, view_layer, camera_ob, r_co, &r_scale)) { + if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, view_layer, camera_ob_eval, r_co, &r_scale)) { ObjectTfmProtectedChannels obtfm; float obmat_new[4][4]; - if ((camera_ob->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) { + if ((camera_ob_eval->type == OB_CAMERA) && (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) { ((Camera *)camera_ob->data)->ortho_scale = r_scale; } - copy_m4_m4(obmat_new, camera_ob->obmat); + copy_m4_m4(obmat_new, camera_ob_eval->obmat); copy_v3_v3(obmat_new[3], r_co); /* only touch location */ diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 6bbc0b7d985..a7c97ba4d4a 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -602,7 +602,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), walk->scene, CTX_data_depsgraph(C), 0, + walk->scene, CTX_data_depsgraph(C), 0, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 569cd4efafc..b713f18da4c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2137,6 +2137,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->state = TRANS_STARTING; + if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) && RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + options |= CTX_CURSOR; + } + } + if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) { if (RNA_property_boolean_get(op->ptr, prop)) { options |= CTX_TEXTURE; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 136512516e8..3718f1be9a8 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -557,6 +557,8 @@ typedef struct TransInfo { #define T_TEXTURE (1 << 3) /* transforming the camera while in camera view */ #define T_CAMERA (1 << 4) + /* transforming the 3D cursor. */ +#define T_CURSOR (1 << 5) // trans on points, having no rotation/scale #define T_POINTS (1 << 6) /** @@ -601,7 +603,9 @@ typedef struct TransInfo { /** #TransInfo.center has been set, don't change it. */ #define T_OVERRIDE_CENTER (1 << 25) -#define T_CLNOR_REBUILD (1 << 26) +#define T_MODAL_CURSOR_SET (1 << 26) + +#define T_CLNOR_REBUILD (1 << 27) /* TransInfo->modifiers */ #define MOD_CONSTRAINT_SELECT 0x01 diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 73a722d897d..c8b09eef04b 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -345,6 +345,43 @@ static void createTransTexspace(TransInfo *t) copy_v3_v3(td->ext->isize, td->ext->size); } +static void createTransCursor3D(TransInfo *t) +{ + TransData *td; + + Scene *scene = t->scene; + View3D *v3d = ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) ? t->view : NULL; + View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d); + + if ((cursor == &scene->cursor) && ID_IS_LINKED(scene)) { + BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); + return; + } + + { + BLI_assert(t->data_container_len == 1); + TransDataContainer *tc = t->data_container; + tc->data_len = 1; + td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace"); + td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); + } + + td->flag = TD_SELECTED; + copy_v3_v3(td->center, cursor->location); + td->ob = NULL; + + unit_m3(td->mtx); + quat_to_mat3(td->axismtx, cursor->rotation); + normalize_m3(td->axismtx); + pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); + + td->loc = cursor->location; + copy_v3_v3(td->iloc, cursor->location); + + td->ext->quat = cursor->rotation; + copy_qt_qt(td->ext->iquat, cursor->rotation); +} + /* ********************* edge (for crease) ***** */ static void createTransEdge(TransInfo *t) @@ -5583,39 +5620,41 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list) /* transcribe given object into TransData for Transforming */ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) { + Depsgraph *depsgraph = t->depsgraph; Scene *scene = t->scene; + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); bool constinv; bool skip_invert = false; if (t->mode != TFM_DUMMY && ob->rigidbody_object) { float rot[3][3], scale[3]; - float ctime = BKE_scene_frame_get(scene); + float ctime = DEG_get_ctime(depsgraph); /* only use rigid body transform if simulation is running, avoids problems with initial setup of rigid bodies */ + // XXX: This needs fixing for COW. May need rigidbody_world from scene if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) { - /* save original object transform */ - copy_v3_v3(td->ext->oloc, ob->loc); + copy_v3_v3(td->ext->oloc, ob_eval->loc); if (ob->rotmode > 0) { - copy_v3_v3(td->ext->orot, ob->rot); + copy_v3_v3(td->ext->orot, ob_eval->rot); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { - td->ext->orotAngle = ob->rotAngle; - copy_v3_v3(td->ext->orotAxis, ob->rotAxis); + td->ext->orotAngle = ob_eval->rotAngle; + copy_v3_v3(td->ext->orotAxis, ob_eval->rotAxis); } else { - copy_qt_qt(td->ext->oquat, ob->quat); + copy_qt_qt(td->ext->oquat, ob_eval->quat); } /* update object's loc/rot to get current rigid body transform */ - mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); - sub_v3_v3(ob->loc, ob->dloc); + mat4_to_loc_rot_size(ob->loc, rot, scale, ob_eval->obmat); + sub_v3_v3(ob->loc, ob_eval->dloc); BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */ } } /* axismtx has the real orientation */ - copy_m3_m4(td->axismtx, ob->obmat); + copy_m3_m4(td->axismtx, ob_eval->obmat); normalize_m3(td->axismtx); td->con = ob->constraints.first; @@ -5628,6 +5667,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) constinv = constraints_list_needinv(t, &ob->constraints); /* disable constraints inversion for dummy pass */ + // XXX: Should this use ob or ob_eval?! It's not clear! if (t->mode == TFM_DUMMY) skip_invert = true; @@ -5642,7 +5682,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ob = ob; td->loc = ob->loc; - copy_v3_v3(td->iloc, td->loc); + copy_v3_v3(td->iloc, ob_eval->loc); if (ob->rotmode > 0) { td->ext->rot = ob->rot; @@ -5650,8 +5690,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ext->rotAngle = NULL; td->ext->quat = NULL; - copy_v3_v3(td->ext->irot, ob->rot); - copy_v3_v3(td->ext->drot, ob->drot); + copy_v3_v3(td->ext->irot, ob_eval->rot); + copy_v3_v3(td->ext->drot, ob_eval->drot); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { td->ext->rot = NULL; @@ -5659,10 +5699,10 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ext->rotAngle = &ob->rotAngle; td->ext->quat = NULL; - td->ext->irotAngle = ob->rotAngle; - copy_v3_v3(td->ext->irotAxis, ob->rotAxis); - // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented - // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented + td->ext->irotAngle = ob_eval->rotAngle; + copy_v3_v3(td->ext->irotAxis, ob_eval->rotAxis); + // td->ext->drotAngle = ob_eval->drotAngle; // XXX, not implemented + // copy_v3_v3(td->ext->drotAxis, ob_eval->drotAxis); // XXX, not implemented } else { td->ext->rot = NULL; @@ -5670,18 +5710,18 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ext->rotAngle = NULL; td->ext->quat = ob->quat; - copy_qt_qt(td->ext->iquat, ob->quat); - copy_qt_qt(td->ext->dquat, ob->dquat); + copy_qt_qt(td->ext->iquat, ob_eval->quat); + copy_qt_qt(td->ext->dquat, ob_eval->dquat); } - td->ext->rotOrder = ob->rotmode; + td->ext->rotOrder = ob_eval->rotmode; td->ext->size = ob->size; - copy_v3_v3(td->ext->isize, ob->size); - copy_v3_v3(td->ext->dscale, ob->dscale); + copy_v3_v3(td->ext->isize, ob_eval->size); + copy_v3_v3(td->ext->dscale, ob_eval->dscale); - copy_v3_v3(td->center, ob->obmat[3]); + copy_v3_v3(td->center, ob_eval->obmat[3]); - copy_m4_m4(td->ext->obmat, ob->obmat); + copy_m4_m4(td->ext->obmat, ob_eval->obmat); /* is there a need to set the global<->data space conversion matrices? */ if (ob->parent || constinv) { @@ -5691,8 +5731,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) * NOTE: some Constraints, and also Tracking should never get this * done, as it doesn't work well. */ - BKE_object_to_mat3(ob, obmtx); - copy_m3_m4(totmat, ob->obmat); + BKE_object_to_mat3(ob_eval, obmtx); + copy_m3_m4(totmat, ob_eval->obmat); invert_m3_m3(obinv, totmat); mul_m3_m3m3(td->smtx, obmtx, obinv); invert_m3_m3(td->mtx, td->smtx); @@ -6693,6 +6733,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) { /* do nothing */ } + else if (t->flag & T_CURSOR) { + /* do nothing */ + } else { /* Objects */ int i; @@ -8325,7 +8368,14 @@ void createTransData(bContext *C, TransInfo *t) t->data_len_all = -1; /* if tests must match recalcData for correct updates */ - if (t->options & CTX_TEXTURE) { + if (t->options & CTX_CURSOR) { + t->flag |= T_CURSOR; + t->obedit_type = -1; + + createTransCursor3D(t); + countAndCleanTransDataContainer(t); + } + else if (t->options & CTX_TEXTURE) { t->flag |= T_TEXTURE; t->obedit_type = -1; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 818ac86cf0c..576bfddd28c 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1007,6 +1007,11 @@ static void recalcData_objects(TransInfo *t) } } +static void recalcData_cursor(TransInfo *t) +{ + DEG_id_tag_update(&t->scene->id, DEG_TAG_COPY_ON_WRITE); +} + /* helper for recalcData() - for sequencer transforms */ static void recalcData_sequencer(TransInfo *t) { @@ -1056,7 +1061,10 @@ static void recalcData_gpencil_strokes(TransInfo *t) void recalcData(TransInfo *t) { /* if tests must match createTransData for correct updates */ - if (t->options & CTX_TEXTURE) { + if (t->options & CTX_CURSOR) { + recalcData_cursor(t); + } + else if (t->options & CTX_TEXTURE) { recalcData_objects(t); } else if (t->options & CTX_EDGE) { @@ -1323,9 +1331,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve prop_id = "use_even_offset"; } - if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) && - RNA_property_is_set(op->ptr, prop)) - { + if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) { SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM); } } @@ -1629,6 +1635,10 @@ void postTrans(bContext *C, TransInfo *t) if (t->draw_handle_cursor) WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor); + if (t->flag & T_MODAL_CURSOR_SET) { + WM_cursor_modal_restore(CTX_wm_window(C)); + } + /* Free all custom-data */ freeTransCustomDataContainer(t, NULL, &t->custom); FOREACH_TRANS_DATA_CONTAINER (t, tc) { diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 2004bba4f09..270ef08be50 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -351,7 +351,8 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) case HLP_NONE: /* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP */ if (t->flag & T_MODAL) { - WM_cursor_set(win, BC_NSEW_SCROLLCURSOR); + t->flag |= T_MODAL_CURSOR_SET; + WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR); } break; case HLP_SPRING: @@ -360,7 +361,8 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) case HLP_HARROW: case HLP_VARROW: if (t->flag & T_MODAL) { - WM_cursor_set(win, CURSOR_NONE); + t->flag |= T_MODAL_CURSOR_SET; + WM_cursor_modal_set(win, CURSOR_NONE); } break; default: diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c index 891d9cf67f1..b94ccf42325 100644 --- a/source/blender/editors/transform/transform_manipulator_3d.c +++ b/source/blender/editors/transform/transform_manipulator_3d.c @@ -596,8 +596,8 @@ int ED_transform_calc_manipulator_stats( RegionView3D *rv3d = ar->regiondata; Base *base; Object *ob = OBACT(view_layer); - const Object *ob_eval = NULL; - const Object *obedit_eval = NULL; + Object *ob_eval = NULL; + Object *obedit_eval = NULL; bGPdata *gpd = CTX_data_gpencil_data(C); const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); int a, totsel = 0; @@ -629,7 +629,7 @@ int ED_transform_calc_manipulator_stats( case V3D_MANIP_GIMBAL: { float mat[3][3]; - if (gimbal_axis(ob, mat)) { + if (gimbal_axis(ob_eval, mat)) { copy_m4_m3(rv3d->twmat, mat); break; } @@ -947,7 +947,7 @@ int ED_transform_calc_manipulator_stats( int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the manipulator mode, could be mixed bool ok = false; - if ((pivot_point == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) { + if ((pivot_point == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob_eval))) { /* doesn't check selection or visibility intentionally */ Bone *bone = pchan->bone; if (bone) { @@ -958,11 +958,11 @@ int ED_transform_calc_manipulator_stats( } } else { - totsel = count_set_pose_transflags(&mode, 0, ob); + totsel = count_set_pose_transflags(&mode, 0, ob_eval); if (totsel) { /* use channels to get stats */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + for (pchan = ob_eval->pose->chanbase.first; pchan; pchan = pchan->next) { Bone *bone = pchan->bone; if (bone && (bone->flag & BONE_TRANSFORM)) { calc_tw_center(tbounds, pchan->pose_head); @@ -1018,7 +1018,7 @@ int ED_transform_calc_manipulator_stats( if (!TESTBASELIB(base)) { continue; } - const Object *base_object_eval = DEG_get_evaluated_object(depsgraph, base->object); + Object *base_object_eval = DEG_get_evaluated_object(depsgraph, base->object); if (ob == NULL) { ob = base->object; ob_eval = base_object_eval; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 4fbb50d678e..a1b78403fc4 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -566,6 +566,10 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes"); } + if (flags & P_CURSOR_EDIT) { + RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", ""); + } + if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) { RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space"); prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel"); @@ -573,7 +577,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) } if (flags & P_CORRECT_UV) { - RNA_def_boolean(ot->srna, "correct_uv", 0, "Correct UVs", "Correct UV coordinates when transforming"); + RNA_def_boolean(ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming"); } if (flags & P_CENTER) { @@ -612,7 +616,10 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) WM_operatortype_props_advanced_begin(ot); - Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT); + Transform_Properties( + ot, + P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | + P_GPENCIL_EDIT | P_CURSOR_EDIT); } 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 19df46455d7..3065007ea6b 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -56,6 +56,8 @@ #include "BKE_scene.h" #include "BKE_workspace.h" +#include "DEG_depsgraph_query.h" + #include "BLT_translation.h" #include "ED_armature.h" @@ -1014,12 +1016,14 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 } } else if (ob && (ob->mode & OB_MODE_POSE)) { - bArmature *arm = ob->data; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + bArmature *arm = ob_eval->data; bPoseChannel *pchan; float imat[3][3], mat[3][3]; bool ok = false; - if (activeOnly && (pchan = BKE_pose_channel_active(ob))) { + if (activeOnly && (pchan = BKE_pose_channel_active(ob_eval))) { add_v3_v3(normal, pchan->pose_mat[2]); add_v3_v3(plane, pchan->pose_mat[1]); ok = true; @@ -1030,7 +1034,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 totsel = count_bone_select(arm, &arm->bonebase, true); if (totsel) { /* use channels to get stats */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + for (pchan = ob_eval->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { add_v3_v3(normal, pchan->pose_mat[2]); add_v3_v3(plane, pchan->pose_mat[1]); @@ -1043,7 +1047,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 /* use for both active & all */ if (ok) { /* we need the transpose of the inverse for a normal... */ - copy_m3_m4(imat, ob->obmat); + copy_m3_m4(imat, ob_eval->obmat); invert_m3_m3(mat, imat); transpose_m3(mat); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index b858f40a3ff..10de7f3ea36 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -406,11 +406,6 @@ void applyGridAbsolute(TransInfo *t) void applySnapping(TransInfo *t, float *vec) { - if (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE) { - /* Each Trans Data already makes the snap to face */ - return; - } - if (t->tsnap.status & SNAP_FORCED) { t->tsnap.targetSnap(t); @@ -555,7 +550,9 @@ static void initSnappingMode(TransInfo *t) { /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632) * TODO: perform self snap in gpencil_strokes */ - t->tsnap.modeSelect = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_ALL : SNAP_NOT_SELECTED; + t->tsnap.modeSelect = ( + ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ? + SNAP_ALL : SNAP_NOT_SELECTED); } else { /* Grid if snap is not possible */ @@ -585,7 +582,7 @@ static void initSnappingMode(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { if (t->tsnap.object_context == NULL) { t->tsnap.object_context = ED_transform_snap_object_context_create_view3d( - G.main, t->scene, t->depsgraph, 0, t->ar, t->view); + t->scene, t->depsgraph, 0, t->ar, t->view); ED_transform_snap_object_context_set_editmesh_callbacks( t->tsnap.object_context, diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index db1a6cc4240..29497fe801c 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -113,7 +113,6 @@ typedef struct SnapObjectData_EditMesh { } SnapObjectData_EditMesh; struct SnapObjectContext { - Main *bmain; Scene *scene; Depsgraph *depsgraph; @@ -535,6 +534,10 @@ static bool raycastEditMesh( return retval; } } + else { + /* COW hack: Update pointers */ + treedata->em = em; + } float imat[4][4]; float timat[3][3]; /* transpose inverse matrix for normals */ @@ -2265,13 +2268,12 @@ static short snapObjectsRay( * \{ */ SnapObjectContext *ED_transform_snap_object_context_create( - Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag) + Scene *scene, Depsgraph *depsgraph, int flag) { SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__); sctx->flag = flag; - sctx->bmain = bmain; sctx->scene = scene; sctx->depsgraph = depsgraph; @@ -2282,11 +2284,11 @@ SnapObjectContext *ED_transform_snap_object_context_create( } SnapObjectContext *ED_transform_snap_object_context_create_view3d( - Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag, + Scene *scene, Depsgraph *depsgraph, int flag, /* extra args for view3d */ const ARegion *ar, const View3D *v3d) { - SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, depsgraph, flag); + SnapObjectContext *sctx = ED_transform_snap_object_context_create(scene, depsgraph, flag); sctx->use_v3d = true; sctx->v3d_data.ar = ar; @@ -2511,6 +2513,10 @@ static short transform_snap_context_project_view3d_mixed_impl( /* Compute the new clip_pane but do not add it yet. */ float new_clipplane[4]; plane_from_point_normal_v3(new_clipplane, loc, no); + if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) { + /* The plane is facing the wrong direction. */ + negate_v4(new_clipplane); + } /* Try to snap only to the polygon. */ elem = snap_mesh_polygon( diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index f07c32370fd..fceb1532077 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -567,35 +567,45 @@ void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float as } } -bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], float r_max[2]) +bool ED_uvedit_minmax_multi( + Scene *scene, Image *ima, Object **objects_edit, uint objects_len, + float r_min[2], float r_max[2]) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; bool changed = false; + INIT_MINMAX2(r_min, r_max); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects_edit[ob_index]; - INIT_MINMAX2(r_min, r_max); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; - 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - minmax_v2v2_v2(r_min, r_max, luv->uv); - changed = true; + 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) { + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + minmax_v2v2_v2(r_min, r_max, luv->uv); + changed = true; + } } } } - return changed; } +bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], float r_max[2]) +{ + return ED_uvedit_minmax_multi(scene, ima, &obedit, 1, r_min, r_max); +} + /* Be careful when using this, it bypasses all synchronization options */ void ED_uvedit_select_all(BMesh *bm) { @@ -614,27 +624,32 @@ void ED_uvedit_select_all(BMesh *bm) } } -static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2]) +static bool ED_uvedit_median_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2]) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; unsigned int sel = 0; + zero_v2(co); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects_edit[ob_index]; - zero_v2(co); - 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - add_v2_v2(co, luv->uv); - sel++; + 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); + + 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 (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + add_v2_v2(co, luv->uv); + sel++; + } } } } @@ -644,19 +659,24 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[ return (sel != 0); } -bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode) +static bool UNUSED_FUNCTION(ED_uvedit_median)(Scene *scene, Image *ima, Object *obedit, float co[2]) +{ + return ED_uvedit_median_multi(scene, ima, &obedit, 1, co); +} + +bool ED_uvedit_center_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float cent[2], char mode) { bool changed = false; if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */ float min[2], max[2]; - if (ED_uvedit_minmax(scene, ima, obedit, min, max)) { + if (ED_uvedit_minmax_multi(scene, ima, objects_edit, objects_len, min, max)) { mid_v2_v2v2(cent, min, max); changed = true; } } else { - if (ED_uvedit_median(scene, ima, obedit, cent)) { + if (ED_uvedit_median_multi(scene, ima, objects_edit, objects_len, cent)) { changed = true; } } @@ -664,6 +684,11 @@ bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], c return changed; } +bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode) +{ + return ED_uvedit_center_multi(scene, ima, &obedit, 1, cent, mode); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -3357,17 +3382,16 @@ static void uv_snap_cursor_to_pixels(SpaceImage *sima) uv_snap_to_pixel(sima->cursor, width, height); } -static bool uv_snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima) +static bool uv_snap_cursor_to_selection( + Scene *scene, Image *ima, Object **objects_edit, uint objects_len, SpaceImage *sima) { - return ED_uvedit_center(scene, ima, obedit, sima->cursor, sima->around); + return ED_uvedit_center_multi(scene, ima, objects_edit, objects_len, sima->cursor, sima->around); } static int uv_snap_cursor_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - Image *ima = CTX_data_edit_image(C); + bool changed = false; switch (RNA_enum_get(op->ptr, "target")) { @@ -3376,8 +3400,18 @@ static int uv_snap_cursor_exec(bContext *C, wmOperator *op) changed = true; break; case 1: - changed = uv_snap_cursor_to_selection(scene, ima, obedit, sima); + { + Scene *scene = CTX_data_scene(C); + Image *ima = CTX_data_edit_image(C); + 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, &objects_len); + changed = uv_snap_cursor_to_selection(scene, ima, objects, objects_len, sima); + MEM_freeN(objects); break; + } } if (!changed) diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 4306fe17e96..a6bfb09141c 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -396,6 +396,11 @@ void math_abs(float val1, out float outval) outval = abs(val1); } +void math_atan2(float val1, float val2, out float outval) +{ + outval = atan(val1, val2); +} + void squeeze(float val, float width, float center, out float outval) { outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index acf054a94d5..4d59a7c9669 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -397,6 +397,10 @@ typedef enum ID_Type { ID_IS_STATIC_OVERRIDE((_id)) && \ (((ID *)(_id))->override_static->flag & STATICOVERRIDE_AUTO)) +/* No copy-on-write for these types. */ +#define ID_TYPE_IS_COW(_id_type) \ + (!ELEM(_id_type, ID_WM, ID_SCR, ID_SCRN, ID_IM, ID_MC, ID_LI)) + #ifdef GS # undef GS #endif diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index 6294afe00e7..3a4b07cc791 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -148,6 +148,8 @@ typedef struct Lamp { #define LA_AREA_RECT 1 #define LA_AREA_CUBE 2 #define LA_AREA_BOX 3 +#define LA_AREA_DISK 4 +#define LA_AREA_ELLIPSE 5 #endif /* __DNA_LAMP_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 989e0768fc1..1d7d1b34f6b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -740,7 +740,7 @@ typedef struct ParticleSystemModifierData { struct ParticleSystem *psys; struct Mesh *mesh_final; /* Final Mesh - its topology may differ from orig mesh. */ - struct Mesh *mesh_deformed; /* Deformed-only Mesh - its topology is same as orig mesh one. */ + struct Mesh *mesh_original; /* Original mesh that particles are attached to. */ int totdmvert, totdmedge, totdmface; short flag, pad; } ParticleSystemModifierData; @@ -1615,6 +1615,7 @@ typedef struct SDefVert { typedef struct SurfaceDeformModifierData { ModifierData modifier; + struct Depsgraph *depsgraph; struct Object *target; /* bind target object */ SDefVert *verts; /* vertex bind data */ float falloff; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index b5a3752072b..af1045ee059 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -891,6 +891,12 @@ typedef struct NodeShaderUVMap { char uv_map[64]; } NodeShaderUVMap; +typedef struct NodeShaderTexIES { + int mode; + + char filepath[1024]; /* 1024 = FILE_MAX */ +} NodeShaderTexIES; + typedef struct NodeSunBeams { float source[2]; @@ -904,6 +910,9 @@ typedef struct NodeSunBeams { /* script node flag */ #define NODE_SCRIPT_AUTO_UPDATE 1 +/* ies node mode */ +#define NODE_IES_INTERNAL 0 +#define NODE_IES_EXTERNAL 1 /* frame node flags */ #define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ @@ -1058,6 +1067,7 @@ enum { NODE_MATH_GREATER = 16, NODE_MATH_MOD = 17, NODE_MATH_ABS = 18, + NODE_MATH_ATAN2 = 19, }; /* mix rgb node flags */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2c39576d0c9..0559df7950d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -2064,43 +2064,6 @@ typedef enum eGPencil_Placement_Flags { #define PE_TYPE_SOFTBODY 1 #define PE_TYPE_CLOTH 2 -/* ToolSettings.skgen_options */ -#define SKGEN_FILTER_INTERNAL (1 << 0) -#define SKGEN_FILTER_EXTERNAL (1 << 1) -#define SKGEN_SYMMETRY (1 << 2) -#define SKGEN_CUT_LENGTH (1 << 3) -#define SKGEN_CUT_ANGLE (1 << 4) -#define SKGEN_CUT_CORRELATION (1 << 5) -#define SKGEN_HARMONIC (1 << 6) -#define SKGEN_STICK_TO_EMBEDDING (1 << 7) -#define SKGEN_ADAPTIVE_DISTANCE (1 << 8) -#define SKGEN_FILTER_SMART (1 << 9) -#define SKGEN_DISP_LENGTH (1 << 10) -#define SKGEN_DISP_WEIGHT (1 << 11) -#define SKGEN_DISP_ORIG (1 << 12) -#define SKGEN_DISP_EMBED (1 << 13) -#define SKGEN_DISP_INDEX (1 << 14) - -#define SKGEN_SUB_LENGTH 0 -#define SKGEN_SUB_ANGLE 1 -#define SKGEN_SUB_CORRELATION 2 -#define SKGEN_SUB_TOTAL 3 - -/* ToolSettings.skgen_postpro */ -#define SKGEN_SMOOTH 0 -#define SKGEN_AVERAGE 1 -#define SKGEN_SHARPEN 2 - -/* ToolSettings.bone_sketching */ -#define BONE_SKETCHING 1 -#define BONE_SKETCHING_QUICK 2 -#define BONE_SKETCHING_ADJUST 4 - -/* ToolSettings.skgen_retarget_roll */ -#define SK_RETARGET_ROLL_NONE 0 -#define SK_RETARGET_ROLL_VIEW 1 -#define SK_RETARGET_ROLL_JOINT 2 - /* PhysicsSettings.flag */ #define PHYS_GLOBAL_GRAVITY 1 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 326d42d9cb3..9817d44c96b 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -406,6 +406,7 @@ typedef struct bTheme { ThemeSpace tconsole; ThemeSpace tclip; ThemeSpace ttopbar; + ThemeSpace tstatusbar; /* 20 sets of bone colors for this theme */ ThemeWireColor tarm[20]; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index cb6031b0a3e..dd3e0c25992 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -338,7 +338,7 @@ enum { /* View3DShading->flag */ enum { V3D_SHADING_OBJECT_OUTLINE = (1 << 0), - V3D_SHADING_SEE_THROUGH = (1 << 1), + V3D_SHADING_XRAY = (1 << 1), V3D_SHADING_SHADOW = (1 << 2), }; diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h index 83b6867afd3..b29e1f808c0 100644 --- a/source/blender/makesdna/DNA_workspace_types.h +++ b/source/blender/makesdna/DNA_workspace_types.h @@ -126,7 +126,7 @@ typedef struct WorkSpace { /* Store for each hook (so for each window) which layout has * been activated the last time this workspace was visible. */ ListBase hook_layout_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */ - ListBase scene_viewlayer_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */ + ListBase scene_layer_relations; /* WorkSpaceSceneRelation */ /* Feature tagging (use for addons) */ ListBase owner_ids DNA_PRIVATE_WORKSPACE_READ_WRITE; /* wmOwnerID */ @@ -180,13 +180,17 @@ typedef struct WorkSpaceDataRelation { void *parent; /* The value for this parent-data/workspace relation */ void *value; - - /** Use when we reference non-ID data, this allows use to look it up when linking in a workspace. */ - char value_name[64]; /* MAX_NAME. */ } WorkSpaceDataRelation; #endif /* DNA_PRIVATE_WORKSPACE_READ_WRITE */ +typedef struct WorkSpaceSceneRelation { + struct WorkSpaceSceneRelation *next, *prev; + + struct Scene *scene; + char view_layer[64]; /* MAX_NAME */ +} WorkSpaceSceneRelation; + /** * Little wrapper to store data that is going to be per window, but comming from the workspace. * It allows us to keep workspace and window data completely separate. diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 8e0264e208d..7431f48367c 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -527,6 +527,7 @@ extern StructRNA RNA_ShaderNodeCombineRGB; extern StructRNA RNA_ShaderNodeExtendedMaterial; extern StructRNA RNA_ShaderNodeGeometry; extern StructRNA RNA_ShaderNodeHueSaturation; +extern StructRNA RNA_ShaderNodeIESLight; extern StructRNA RNA_ShaderNodeInvert; extern StructRNA RNA_ShaderNodeLampData; extern StructRNA RNA_ShaderNodeMapping; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 1c55925809a..80d1897f604 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3482,7 +3482,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const /* we want the included C files to have warnings enabled but for the generated code * ignore unused-parameter warnings which are hard to prevent */ -#ifdef __GNUC__ +#if defined( __GNUC__) || defined(__clang__) fprintf(f, "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n\n"); #endif diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 952d27fa18d..1ea452bf389 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -500,9 +500,9 @@ static Material *rna_IDMaterials_pop_id(ID *id, Main *bmain, ReportList *reports return ma; } -static void rna_IDMaterials_clear_id(ID *id, int remove_material_slot) +static void rna_IDMaterials_clear_id(ID *id, Main *bmain, int remove_material_slot) { - BKE_material_clear_id(G.main, id, remove_material_slot); + BKE_material_clear_id(bmain, id, remove_material_slot); DEG_id_tag_update(id, OB_RECALC_DATA); WM_main_add_notifier(NC_OBJECT | ND_DRAW, id); @@ -945,6 +945,7 @@ static void rna_def_ID_materials(BlenderRNA *brna) RNA_def_function_return(func, parm); func = RNA_def_function(srna, "clear", "rna_IDMaterials_clear_id"); + RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Remove all materials from the data-block"); RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned"); } diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index a6a834465ff..5a0dec28324 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2064,10 +2064,15 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR else prop->update(bmain, scene, ptr); } -#if 0 - if (prop->noteflag) + +#if 1 + /* TODO(campbell): Should eventually be replaced entirely by message bus (below) + * for now keep since COW, bugs are hard to track when we have other missing updates. */ + if (prop->noteflag) { WM_main_add_notifier(prop->noteflag, ptr->id.data); -#else + } +#endif + /* if C is NULL, we're updating from animation. * avoid slow-down from f-curves by not publishing (for now). */ if (C != NULL) { @@ -2075,9 +2080,15 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR /* we could add NULL check, for now don't */ WM_msg_publish_rna(mbus, ptr, prop); } -#endif + if (ptr->id.data != NULL) { + const short id_type = GS(((ID *)ptr->id.data)->name); + if (ID_TYPE_IS_COW(id_type)) { + DEG_id_tag_update(ptr->id.data, DEG_TAG_COPY_ON_WRITE); + } + } + /* End message bus. */ } - + if (!is_rna || (prop->flag & PROP_IDPROPERTY)) { /* WARNING! This is so property drivers update the display! * not especially nice */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 0819a5e828e..30c643388af 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -168,8 +168,10 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po { ID *id = ptr->id.data; - /* special updates for cases where rigs try to hook into armature drawing stuff - * e.g. Mask Modifier - 'Armature' option + /* 1) special updates for cases where rigs try to hook into armature drawing stuff + * e.g. Mask Modifier - 'Armature' option + * 2) tag armature for copy-on-write, so that selection status (set by addons) + * will update properly, like standard tools do already */ if (id) { if (GS(id->name) == ID_AR) { @@ -178,6 +180,8 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po if (arm->flag & ARM_HAS_VIZ_DEPS) { DEG_id_tag_update(id, OB_RECALC_DATA); } + + DEG_id_tag_update(id, DEG_TAG_COPY_ON_WRITE); } else if (GS(id->name) == ID_OB) { Object *ob = (Object *)id; @@ -186,6 +190,8 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po if (arm->flag & ARM_HAS_VIZ_DEPS) { DEG_id_tag_update(id, OB_RECALC_DATA); } + + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 5bb24f0270d..d123cdb9773 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -394,6 +394,8 @@ static void rna_def_area_lamp(BlenderRNA *brna) static const EnumPropertyItem prop_areashape_items[] = { {LA_AREA_SQUARE, "SQUARE", 0, "Square", ""}, {LA_AREA_RECT, "RECTANGLE", 0, "Rectangle", ""}, + {LA_AREA_DISK, "DISK", 0, "Disk", ""}, + {LA_AREA_ELLIPSE, "ELLIPSE", 0, "Ellipse", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c index d4b94bfb3be..f3091ae5ee1 100644 --- a/source/blender/makesrna/intern/rna_lightprobe.c +++ b/source/blender/makesrna/intern/rna_lightprobe.c @@ -187,17 +187,17 @@ static void rna_def_lightprobe(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Intensity", "Modify the intensity of the lighting captured by this probe"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc"); - prop = RNA_def_property(srna, "visibility_group", PROP_POINTER, PROP_NONE); + prop = RNA_def_property(srna, "visibility_collection", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_pointer_sdna(prop, NULL, "visibility_grp"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Visibility Collection", "Restrict objects visible for this probe"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc"); - prop = RNA_def_property(srna, "invert_visibility_group", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "invert_visibility_collection", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_INVERT_GROUP); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Invert Group", "Invert visibility group"); + RNA_def_property_ui_text(prop, "Invert Collection", "Invert visibility collection"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc"); /* Data preview */ diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 7dc76120097..a40606018e7 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -372,9 +372,9 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clip Threshold", "A pixel is rendered only if its alpha value is above this threshold"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); - prop = RNA_def_property(srna, "transparent_hide_backside", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_HIDE_BACKSIDE); - RNA_def_property_ui_text(prop, "Hide Backside", "Limit transparency to a single layer " + prop = RNA_def_property(srna, "show_transparent_backside", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "blend_flag", MA_BL_HIDE_BACKSIDE); + RNA_def_property_ui_text(prop, "Show Backside", "Limit transparency to a single layer " "(avoids transparency sorting problems)"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); @@ -519,7 +519,8 @@ static void rna_def_tex_slot(BlenderRNA *brna) RNA_def_property_ui_text(prop, "UV Map", "Name of UV map"); RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Material_update"); - prop = RNA_def_property(srna, "valid", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "valid", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Valid", "Slot has a valid image and UV map"); } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 79a1ce73071..d2fb9d19acc 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -143,6 +143,7 @@ const EnumPropertyItem rna_enum_node_math_items[] = { {NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""}, {NODE_MATH_MOD, "MODULO", 0, "Modulo", ""}, {NODE_MATH_ABS, "ABSOLUTE", 0, "Absolute", ""}, + {NODE_MATH_ATAN2, "ARCTAN2", 0, "Arctan2", ""}, {0, NULL, 0, NULL, NULL} }; @@ -730,7 +731,7 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *r return node; } -static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr) +static void rna_NodeTree_node_remove(bNodeTree *ntree, Main *bmain, ReportList *reports, PointerRNA *node_ptr) { bNode *node = node_ptr->data; @@ -746,11 +747,11 @@ static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, Poin nodeFreeNode(ntree, node); RNA_POINTER_INVALIDATE(node_ptr); - ntreeUpdateTree(G.main, ntree); /* update group node socket links */ + ntreeUpdateTree(bmain, ntree); /* update group node socket links */ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_node_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_node_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNode *node = ntree->nodes.first; @@ -768,7 +769,7 @@ static void rna_NodeTree_node_clear(bNodeTree *ntree, ReportList *reports) node = next_node; } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -791,7 +792,7 @@ static void rna_NodeTree_active_node_set(PointerRNA *ptr, const PointerRNA value nodeClearActive(ntree); } -static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports, +static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, Main *bmain, ReportList *reports, bNodeSocket *fromsock, bNodeSocket *tosock, int verify_limits) { @@ -833,15 +834,15 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports, if (tonode) nodeUpdate(ntree, tonode); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); - ED_node_tag_update_nodetree(G.main, ntree, ret->tonode); + ED_node_tag_update_nodetree(bmain, ntree, ret->tonode); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } return ret; } -static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr) +static void rna_NodeTree_link_remove(bNodeTree *ntree, Main *bmain, ReportList *reports, PointerRNA *link_ptr) { bNodeLink *link = link_ptr->data; @@ -856,11 +857,11 @@ static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, Poin nodeRemLink(ntree, link); RNA_POINTER_INVALIDATE(link_ptr); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_link_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_link_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeLink *link = ntree->links.first; @@ -874,7 +875,7 @@ static void rna_NodeTree_link_clear(bNodeTree *ntree, ReportList *reports) link = next_link; } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -937,7 +938,7 @@ static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value) } } -static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name) +static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name) { bNodeSocket *sock; @@ -946,13 +947,13 @@ static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *report sock = ntreeAddSocketInterface(ntree, SOCK_IN, type, name); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); return sock; } -static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name) +static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name) { bNodeSocket *sock; @@ -961,13 +962,13 @@ static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, ReportList *repor sock = ntreeAddSocketInterface(ntree, SOCK_OUT, type, name); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); return sock; } -static void rna_NodeTree_socket_remove(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock) +static void rna_NodeTree_socket_remove(bNodeTree *ntree, Main *bmain, ReportList *reports, bNodeSocket *sock) { if (!rna_NodeTree_check(ntree, reports)) return; @@ -978,12 +979,12 @@ static void rna_NodeTree_socket_remove(bNodeTree *ntree, ReportList *reports, bN else { ntreeRemoveSocketInterface(ntree, sock); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } } -static void rna_NodeTree_inputs_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_inputs_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeSocket *sock, *nextsock; @@ -995,11 +996,11 @@ static void rna_NodeTree_inputs_clear(bNodeTree *ntree, ReportList *reports) ntreeRemoveSocketInterface(ntree, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_outputs_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_outputs_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeSocket *sock, *nextsock; @@ -1011,11 +1012,11 @@ static void rna_NodeTree_outputs_clear(bNodeTree *ntree, ReportList *reports) ntreeRemoveSocketInterface(ntree, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_inputs_move(bNodeTree *ntree, int from_index, int to_index) +static void rna_NodeTree_inputs_move(bNodeTree *ntree, Main *bmain, int from_index, int to_index) { bNodeSocket *sock; @@ -1042,11 +1043,11 @@ static void rna_NodeTree_inputs_move(bNodeTree *ntree, int from_index, int to_in ntree->update |= NTREE_UPDATE_GROUP_IN; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_outputs_move(bNodeTree *ntree, int from_index, int to_index) +static void rna_NodeTree_outputs_move(bNodeTree *ntree, Main *bmain, int from_index, int to_index) { bNodeSocket *sock; @@ -1073,16 +1074,18 @@ static void rna_NodeTree_outputs_move(bNodeTree *ntree, int from_index, int to_i ntree->update |= NTREE_UPDATE_GROUP_OUT; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } static void rna_NodeTree_interface_update(bNodeTree *ntree, bContext *C) { + Main *bmain = CTX_data_main(C); + ntree->update |= NTREE_UPDATE_GROUP; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); - ED_node_tag_update_nodetree(CTX_data_main(C), ntree, NULL); + ED_node_tag_update_nodetree(bmain, ntree, NULL); } @@ -1612,7 +1615,7 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value) BKE_animdata_fix_paths_rename_all(NULL, "nodes", oldname, node->name); } -static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier) +static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, Main *bmain, ReportList *reports, const char *type, const char *name, const char *identifier) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1623,14 +1626,14 @@ static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports BKE_report(reports, RPT_ERROR, "Unable to create socket"); } else { - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } return sock; } -static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier) +static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, Main *bmain, ReportList *reports, const char *type, const char *name, const char *identifier) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1641,14 +1644,14 @@ static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *report BKE_report(reports, RPT_ERROR, "Unable to create socket"); } else { - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } return sock; } -static void rna_Node_socket_remove(ID *id, bNode *node, ReportList *reports, bNodeSocket *sock) +static void rna_Node_socket_remove(ID *id, bNode *node, Main *bmain, ReportList *reports, bNodeSocket *sock) { bNodeTree *ntree = (bNodeTree *)id; @@ -1658,12 +1661,12 @@ static void rna_Node_socket_remove(ID *id, bNode *node, ReportList *reports, bNo else { nodeRemoveSocket(ntree, node, sock); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } } -static void rna_Node_inputs_clear(ID *id, bNode *node) +static void rna_Node_inputs_clear(ID *id, bNode *node, Main *bmain) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock, *nextsock; @@ -1673,11 +1676,11 @@ static void rna_Node_inputs_clear(ID *id, bNode *node) nodeRemoveSocket(ntree, node, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_Node_outputs_clear(ID *id, bNode *node) +static void rna_Node_outputs_clear(ID *id, bNode *node, Main *bmain) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock, *nextsock; @@ -1687,11 +1690,11 @@ static void rna_Node_outputs_clear(ID *id, bNode *node) nodeRemoveSocket(ntree, node, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_Node_inputs_move(ID *id, bNode *node, int from_index, int to_index) +static void rna_Node_inputs_move(ID *id, bNode *node, Main *bmain, int from_index, int to_index) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1717,11 +1720,11 @@ static void rna_Node_inputs_move(ID *id, bNode *node, int from_index, int to_ind } } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_Node_outputs_move(ID *id, bNode *node, int from_index, int to_index) +static void rna_Node_outputs_move(ID *id, bNode *node, Main *bmain, int from_index, int to_index) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1747,7 +1750,7 @@ static void rna_Node_outputs_move(ID *id, bNode *node, int from_index, int to_in } } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -2220,7 +2223,7 @@ static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), Po return; ntree->update |= NTREE_UPDATE_GROUP; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); ED_node_tag_update_nodetree(bmain, ntree, NULL); } @@ -2949,6 +2952,30 @@ static bNodeSocket *rna_NodeOutputFile_slots_new(ID *id, bNode *node, bContext * return sock; } +static void rna_ShaderNodeTexIES_mode_set(PointerRNA *ptr, int value) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderTexIES *nss = node->storage; + + if (nss->mode != value) { + nss->mode = value; + nss->filepath[0] = '\0'; + + /* replace text datablock by filepath */ + if (node->id) { + Text *text = (Text *)node->id; + + if (value == NODE_IES_EXTERNAL && text->name) { + BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath)); + BLI_path_rel(nss->filepath, G.main->name); + } + + id_us_min(node->id); + node->id = NULL; + } + } +} + static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value) { bNode *node = (bNode *)ptr->data; @@ -3291,6 +3318,12 @@ static const EnumPropertyItem node_script_mode_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem node_ies_mode_items[] = { + {NODE_IES_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"}, + {NODE_IES_EXTERNAL, "EXTERNAL", 0, "External", "Use external .ies file"}, + {0, NULL, 0, NULL, NULL} +}; + static const EnumPropertyItem node_principled_distribution_items[] = { {SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""}, {SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""}, @@ -4402,6 +4435,32 @@ static void def_sh_subsurface(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeSubsurface_update"); } +static void def_sh_tex_ies(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "ies", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Text"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_ui_text(prop, "IES Text", "Internal IES file"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "NodeShaderTexIES", "storage"); + + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); + RNA_def_property_ui_text(prop, "File Path", "IES light path"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeTexIES_mode_set", NULL); + RNA_def_property_enum_items(prop, node_ies_mode_items); + RNA_def_property_ui_text(prop, "Source", "Whether the IES file is loaded from disk or from a Text datablock"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "bNode", NULL); +} + static void def_sh_script(StructRNA *srna) { PropertyRNA *prop; @@ -4897,17 +4956,17 @@ static void rna_def_cmp_output_file_slots_api(BlenderRNA *brna, PropertyRNA *cpr func = RNA_def_function(srna, "remove", "rna_Node_socket_remove"); RNA_def_function_ui_description(func, "Remove a file slot from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "clear", "rna_Node_inputs_clear"); RNA_def_function_ui_description(func, "Remove all file slots from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); func = RNA_def_function(srna, "move", "rna_Node_inputs_move"); RNA_def_function_ui_description(func, "Move a file slot to another position"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the socket to move", 0, 10000); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the socket", 0, 10000); @@ -7640,7 +7699,7 @@ static void rna_def_node_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int i func = RNA_def_function(srna, "new", newfunc); RNA_def_function_ui_description(func, "Add a socket to this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_string(func, "type", NULL, MAX_NAME, "Type", "Data type"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); @@ -7652,17 +7711,17 @@ static void rna_def_node_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int i func = RNA_def_function(srna, "remove", "rna_Node_socket_remove"); RNA_def_function_ui_description(func, "Remove a socket from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "clear", clearfunc); RNA_def_function_ui_description(func, "Remove all sockets from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); func = RNA_def_function(srna, "move", movefunc); RNA_def_function_ui_description(func, "Move a socket to another position"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the socket to move", 0, 10000); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the socket", 0, 10000); @@ -8033,14 +8092,14 @@ static void rna_def_nodetree_nodes_api(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove"); RNA_def_function_ui_description(func, "Remove a node from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear"); RNA_def_function_ui_description(func, "Remove all nodes from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Node"); @@ -8063,7 +8122,7 @@ static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new", "rna_NodeTree_link_new"); RNA_def_function_ui_description(func, "Add a node link to this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket"); @@ -8075,14 +8134,14 @@ static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove"); RNA_def_function_ui_description(func, "remove a node link from the node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear"); RNA_def_function_ui_description(func, "remove all node links from the node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); } static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out) @@ -8103,7 +8162,7 @@ static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, func = RNA_def_function(srna, "new", newfunc); RNA_def_function_ui_description(func, "Add a socket to this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_string(func, "type", NULL, MAX_NAME, "Type", "Data type"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); @@ -8114,16 +8173,17 @@ static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, func = RNA_def_function(srna, "remove", "rna_NodeTree_socket_remove"); RNA_def_function_ui_description(func, "Remove a socket from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "The socket to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "clear", clearfunc); RNA_def_function_ui_description(func, "Remove all sockets from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); func = RNA_def_function(srna, "move", movefunc); RNA_def_function_ui_description(func, "Move a socket to another position"); + RNA_def_function_flag(func, FUNC_USE_MAIN); parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the socket to move", 0, 10000); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the socket", 0, 10000); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 04507d1ed7e..a01192dad68 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -89,6 +89,8 @@ static const EnumPropertyItem space_items[] = { #include "DNA_scene_types.h" #include "DNA_view3d_types.h" +#include "DEG_depsgraph_query.h" + #include "MEM_guardedalloc.h" static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports, int action) @@ -173,13 +175,14 @@ static void rna_Object_mat_convert_space(Object *ob, ReportList *reports, bPoseC } static void rna_Object_calc_matrix_camera( - Object *ob, float mat_ret[16], int width, int height, float scalex, float scaley) + Object *ob, Depsgraph *depsgraph, float mat_ret[16], int width, int height, float scalex, float scaley) { + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); CameraParams params; /* setup parameters */ BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, ob); + BKE_camera_params_from_object(¶ms, ob_eval); /* compute matrix, viewplane, .. */ BKE_camera_params_compute_viewplane(¶ms, width, height, scalex, scaley); @@ -189,9 +192,9 @@ static void rna_Object_calc_matrix_camera( } static void rna_Object_camera_fit_coords( - Object *ob, Scene *scene, int num_cos, float *cos, float co_ret[3], float *scale_ret) + Object *ob, Depsgraph *depsgraph, int num_cos, float *cos, float co_ret[3], float *scale_ret) { - BKE_camera_view_frame_fit_to_coords(scene, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret); + BKE_camera_view_frame_fit_to_coords(depsgraph, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret); } /* copied from Mesh_getFromObject and adapted to RNA interface */ @@ -518,6 +521,9 @@ void RNA_api_object(StructRNA *srna) func = RNA_def_function(srna, "calc_matrix_camera", "rna_Object_calc_matrix_camera"); RNA_def_function_ui_description(func, "Generate the camera projection matrix of this object " "(mostly useful for Camera and Lamp types)"); + parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", + "Depsgraph to get evaluated data from"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_property(func, "result", PROP_FLOAT, PROP_MATRIX); RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4); RNA_def_property_ui_text(parm, "", "The camera projection matrix"); @@ -530,7 +536,8 @@ void RNA_api_object(StructRNA *srna) func = RNA_def_function(srna, "camera_fit_coords", "rna_Object_camera_fit_coords"); RNA_def_function_ui_description(func, "Compute the coordinate (and scale for ortho cameras) " "given object should be to 'see' all given coordinates"); - parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to get render size information from, if available"); + parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", + "Depsgraph to get evaluated data from"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_float_array(func, "coordinates", 1, NULL, -FLT_MAX, FLT_MAX, "", "Coordinates to fit in", -FLT_MAX, FLT_MAX); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 27f9932ebde..4599ec0f9c5 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -175,11 +175,10 @@ const EnumPropertyItem rna_enum_snap_element_items[] = { }; const EnumPropertyItem rna_enum_snap_node_element_items[] = { - {SCE_SNAP_MODE_GRID , "GRID" , ICON_SNAP_GRID, "Grid", "Snap to grid"}, - {SCE_SNAP_MODE_NODE_X, "NODE_X" , ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"}, - {SCE_SNAP_MODE_NODE_Y, "NODE_Y" , ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"}, - {SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y, - "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"}, + {SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"}, + {SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"}, + {SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"}, + {SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"}, {0, NULL, 0, NULL, NULL} }; @@ -1486,7 +1485,7 @@ void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value) { Scene *scene = (Scene *)ptr->id.data; ViewLayer *view_layer = (ViewLayer *)ptr->data; - BKE_view_layer_rename(scene, view_layer, value); + BKE_view_layer_rename(G.main, scene, view_layer, value); } static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value) @@ -5866,7 +5865,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_range(prop, 1, INT_MAX); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "taa_reprojection", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_taa_reprojection", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_TAA_REPROJECTION); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Viewport Denoising", "Denoise image using temporal reprojection " @@ -5874,7 +5873,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Screen Space Subsurface Scattering */ - prop = RNA_def_property(srna, "sss_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_sss", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSS_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Subsurface Scattering", "Enable screen space subsurface scattering"); @@ -5892,7 +5891,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "sss_separate_albedo", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_sss_separate_albedo", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSS_SEPARATE_ALBEDO); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Separate Albedo", "Avoid albedo being blured by the subsurface scattering " @@ -5900,19 +5899,19 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Screen Space Reflection */ - prop = RNA_def_property(srna, "ssr_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_ssr", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSR_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Screen Space Reflections", "Enable screen space reflection"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "ssr_refraction", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_ssr_refraction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSR_REFRACTION); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Screen Space Refractions", "Enable screen space Refractions"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "ssr_halfres", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_ssr_halfres", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSR_HALF_RESOLUTION); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Half Res Trace", "Raytrace at a lower resolution"); @@ -5950,7 +5949,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Volumetrics */ - prop = RNA_def_property(srna, "volumetric_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Volumetrics", "Enable scattering and absorbance of volumetric material"); @@ -5988,7 +5987,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Exponential Sampling", "Distribute more samples closer to the camera"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "volumetric_lights", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric_lights", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_LIGHTS); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Volumetric Lighting", "Enable scene lamps interactions with volumetrics"); @@ -6000,7 +5999,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clamp", "Maximum light contribution, reducing noise"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "volumetric_shadows", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric_shadows", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_SHADOWS); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Volumetric Shadows", "Generate shadows from volumetric material (Very expensive)"); @@ -6012,26 +6011,26 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Volumetric Shadow Samples", "Number of samples to compute volumetric shadowing"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_COLORED); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Colored Transmittance", "Enable wavelength dependent volumetric transmittance"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Ambient Occlusion */ - prop = RNA_def_property(srna, "gtao_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_gtao", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Ambient Occlusion", "Enable ambient occlusion to simulate medium scale indirect shadowing"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "gtao_use_bent_normals", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_gtao_bent_normals", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_BENT_NORMALS); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Bent Normals", "Compute main non occluded direction to sample the environment"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "gtao_bounce", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_gtao_bounce", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_BOUNCE); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Bounces Approximation", "An approximation to simulate light bounces " @@ -6059,7 +6058,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Depth of Field */ - prop = RNA_def_property(srna, "dof_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_DOF_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Depth of Field", "Enable depth of field using the values from the active camera"); @@ -6080,7 +6079,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Bloom */ - prop = RNA_def_property(srna, "bloom_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_bloom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_BLOOM_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Bloom", "High brighness pixels generate a glowing effect"); @@ -6127,7 +6126,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Motion blur */ - prop = RNA_def_property(srna, "motion_blur_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_MOTION_BLUR_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Motion Blur", "Enable motion blur effect (only in camera view)"); @@ -6164,7 +6163,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Directional Shadows Resolution", "Size of sun lamps shadow maps"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "shadow_high_bitdepth", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_shadow_high_bitdepth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SHADOW_HIGH_BITDEPTH); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "High Bitdepth", "Use 32bit shadows"); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index a3e403154f9..a307aff6e96 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -144,7 +144,8 @@ static void rna_Scene_update_tagged(Scene *scene, Main *bmain) #endif } -static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int preview, const char *view, char *name) +static void rna_SceneRender_get_frame_path( + RenderData *rd, Main *bmain, int frame, int preview, const char *view, char *name) { const char *suffix = BKE_scene_multiview_view_suffix_get(rd, view); @@ -157,7 +158,7 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int previe } else { BKE_image_path_from_imformat( - name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame, + name, rd->pic, bmain->name, (frame == INT_MIN) ? rd->cfra : frame, &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true, suffix); } } @@ -172,7 +173,7 @@ static void rna_Scene_ray_cast( Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); SnapObjectContext *sctx = ED_transform_snap_object_context_create( - G.main, scene, depsgraph, 0); + scene, depsgraph, 0); bool ret = ED_transform_snap_object_project_ray_ex( sctx, @@ -390,6 +391,7 @@ void RNA_api_scene_render(StructRNA *srna) PropertyRNA *parm; func = RNA_def_function(srna, "frame_path", "rna_SceneRender_get_frame_path"); + RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Return the absolute path to the filename to be written for a given frame"); RNA_def_int(func, "frame", INT_MIN, INT_MIN, INT_MAX, "", "Frame number to use, if unset the current frame will be used", MINAFRAME, MAXFRAME); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index e555c2ae52a..65edc619ced 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -655,12 +655,7 @@ static int rna_3DViewShading_type_get(PointerRNA *ptr) RenderEngineType *type = RE_engines_find(scene->r.engine); View3D *v3d = (View3D *)ptr->data; - if (BKE_scene_uses_blender_eevee(scene)) { - if (v3d->drawtype == OB_MATERIAL) { - return OB_RENDER; - } - } - else if (v3d->drawtype == OB_RENDER) { + if (!BKE_scene_uses_blender_eevee(scene) && v3d->drawtype == OB_RENDER) { if (!(type && type->render_to_view)) { return OB_MATERIAL; } @@ -693,6 +688,7 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf( RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_TEXTURE); if (BKE_scene_uses_blender_eevee(scene)) { + RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_MATERIAL); RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_RENDER); } else { @@ -711,7 +707,7 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf( static int rna_View3DShading_studio_light_orientation_get(PointerRNA *ptr) { View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light); + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, 0); return sl->flag & (STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_ORIENTATION_CAMERA); } static void rna_View3DShading_studio_light_orientation_set(PointerRNA *UNUSED(ptr), int UNUSED(value)) @@ -721,7 +717,9 @@ static void rna_View3DShading_studio_light_orientation_set(PointerRNA *UNUSED(pt static int rna_View3DShading_studio_light_get(PointerRNA *ptr) { View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light); + const int flag = v3d->drawtype == OB_MATERIAL? STUDIOLIGHT_ORIENTATION_WORLD: 0; + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, flag); + BLI_strncpy(v3d->shading.studio_light, sl->name, FILE_MAXFILE); return sl->index; } @@ -733,19 +731,40 @@ static void rna_View3DShading_studio_light_set(PointerRNA *ptr, int value) } static const EnumPropertyItem *rna_View3DShading_studio_light_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { + View3D *v3d = (View3D *)ptr->data; EnumPropertyItem *item = NULL; EnumPropertyItem *lastitem; int totitem = 0; + bool show_studiolight; LISTBASE_FOREACH(StudioLight *, sl, BKE_studiolight_listbase()) { - if (totitem < NUM_STUDIOLIGHT_ITEMS) { - RNA_enum_items_add_value(&item, &totitem, rna_enum_studio_light_items, totitem); + show_studiolight = false; + int icon_id = sl->irradiance_icon_id; + + if ((sl->flag & STUDIOLIGHT_EXTERNAL_FILE) == 0) { + /* always show internal lights */ + show_studiolight = true; + } else { + switch (v3d->drawtype) { + case OB_SOLID: + case OB_TEXTURE: + show_studiolight = true; + break; + case OB_MATERIAL: + show_studiolight = (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD) > 0; + icon_id = sl->radiance_icon_id; + break; + } + } + + if (show_studiolight && totitem < NUM_STUDIOLIGHT_ITEMS) { + RNA_enum_items_add_value(&item, &totitem, rna_enum_studio_light_items, sl->index); lastitem = &item[totitem - 1]; lastitem->value = sl->index; - lastitem->icon = sl->icon_id; + lastitem->icon = icon_id; lastitem->name = sl->name; } } @@ -2038,10 +2057,10 @@ static void rna_def_space_image_uv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Texture Paint UVs", "Draw overlay of texture paint uv layer"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); - prop = RNA_def_property(srna, "show_normalized_coords", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_COORDFLOATS); - RNA_def_property_ui_text(prop, "Normalized Coordinates", - "Display UV coordinates from 0.0 to 1.0 rather than in pixels"); + prop = RNA_def_property(srna, "show_pixel_coords", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_COORDFLOATS); + RNA_def_property_ui_text(prop, "Pixel Coordinates", + "Display UV coordinates in pixels rather than from 0.0 to 1.0"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); prop = RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE); @@ -2305,10 +2324,10 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Shadow", "Show Shadow"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "show_see_through", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_SEE_THROUGH); + prop = RNA_def_property(srna, "show_xray", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_XRAY); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "See Through", "Show whole scene transparent"); + RNA_def_property_ui_text(prop, "X-Ray", "Show whole scene transparent"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "object_outline_color", PROP_FLOAT, PROP_COLOR); @@ -2475,7 +2494,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "transparent_bones", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "show_transparent_bones", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.arm_flag", V3D_OVERLAY_ARM_TRANSP_BONES); RNA_def_property_ui_text(prop, "Transparent Bones", "Display bones as transparent"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 9e868cf17e9..173eaf56f0c 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -914,6 +914,16 @@ static void rna_UILayout_emboss_set(PointerRNA *ptr, int value) uiLayoutSetEmboss(ptr->data, value); } +static int rna_UILayout_property_split_get(PointerRNA *ptr) +{ + return uiLayoutGetPropSep(ptr->data); +} + +static void rna_UILayout_property_split_set(PointerRNA *ptr, int value) +{ + uiLayoutSetPropSep(ptr->data, value); +} + #else /* RNA_RUNTIME */ static void rna_def_ui_layout(BlenderRNA *brna) @@ -978,6 +988,9 @@ static void rna_def_ui_layout(BlenderRNA *brna) prop = RNA_def_property(srna, "emboss", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, emboss_items); RNA_def_property_enum_funcs(prop, "rna_UILayout_emboss_get", "rna_UILayout_emboss_set", NULL); + + prop = RNA_def_property(srna, "use_property_split", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_split_get", "rna_UILayout_property_split_set"); } static void rna_def_panel(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 741a1a87eb1..fef4cc3ed8e 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2962,6 +2962,20 @@ static void rna_def_userdef_theme_space_topbar(BlenderRNA *brna) rna_def_userdef_theme_spaces_main(srna); } +static void rna_def_userdef_theme_space_statusbar(BlenderRNA *brna) +{ + StructRNA *srna; + + /* space_statusbar */ + + srna = RNA_def_struct(brna, "ThemeStatusBar", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Theme Status Bar", "Theme settings for the Status Bar"); + + rna_def_userdef_theme_spaces_main(srna); +} + static void rna_def_userdef_themes(BlenderRNA *brna) { StructRNA *srna; @@ -2987,6 +3001,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna) {17, "CONSOLE", ICON_CONSOLE, "Python Console", ""}, {20, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", ""}, {21, "TOPBAR", ICON_NONE, "Top Bar", ""}, + {22, "STATUSBAR", ICON_NONE, "Status Bar", ""}, {0, NULL, 0, NULL, NULL} }; @@ -3114,6 +3129,12 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ttopbar"); RNA_def_property_struct_type(prop, "ThemeTopBar"); RNA_def_property_ui_text(prop, "Top Bar", ""); + + prop = RNA_def_property(srna, "statusbar", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "tstatusbar"); + RNA_def_property_struct_type(prop, "ThemeStatusBar"); + RNA_def_property_ui_text(prop, "Status Bar", ""); } static void rna_def_userdef_addon(BlenderRNA *brna) @@ -3204,6 +3225,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna) rna_def_userdef_theme_space_console(brna); rna_def_userdef_theme_space_clip(brna); rna_def_userdef_theme_space_topbar(brna); + rna_def_userdef_theme_space_statusbar(brna); rna_def_userdef_theme_colorset(brna); rna_def_userdef_themes(brna); } diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 4a67b8318bb..e74d9087427 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -390,7 +390,7 @@ static Mesh *arrayModifier_doArray( vgroup_start_cap_remap = BKE_object_defgroup_index_map_create( amd->start_cap, ctx->object, &vgroup_start_cap_remap_len); - start_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(amd->start_cap, ctx->flag); + start_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, amd->start_cap); if (start_cap_mesh) { start_cap_nverts = start_cap_mesh->totvert; start_cap_nedges = start_cap_mesh->totedge; @@ -402,7 +402,7 @@ static Mesh *arrayModifier_doArray( vgroup_end_cap_remap = BKE_object_defgroup_index_map_create( amd->end_cap, ctx->object, &vgroup_end_cap_remap_len); - end_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(amd->end_cap, ctx->flag); + end_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, amd->end_cap); if (end_cap_mesh) { end_cap_nverts = end_cap_mesh->totvert; end_cap_nedges = end_cap_mesh->totedge; diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index ebe5aacd888..73d1388d88f 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -56,6 +56,8 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DEG_depsgraph_query.h" + #include "MEM_guardedalloc.h" #include "bmesh.h" @@ -173,18 +175,19 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes if (!bmd->object) return mesh; - mesh_other = BKE_modifier_get_evaluated_mesh_from_object(bmd->object, ctx->flag); - + mesh_other = BKE_modifier_get_evaluated_mesh_from_object(ctx, bmd->object); if (mesh_other) { Mesh *result; + Object *object_eval = DEG_get_evaluated_object(ctx->depsgraph, ctx->object); + Object *other_eval = DEG_get_evaluated_object(ctx->depsgraph, bmd->object); /* when one of objects is empty (has got no faces) we could speed up * calculation a bit returning one of objects' derived meshes (or empty one) * Returning mesh is depended on modifiers operation (sergey) */ - result = get_quick_mesh(ctx->object, mesh, bmd->object, mesh_other, bmd->operation); + result = get_quick_mesh(object_eval, mesh, other_eval, mesh_other, bmd->operation); if (result == NULL) { - const bool is_flip = (is_negative_m4(ctx->object->obmat) != is_negative_m4(bmd->object->obmat)); + const bool is_flip = (is_negative_m4(object_eval->obmat) != is_negative_m4(other_eval->obmat)); BMesh *bm; const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_other); @@ -231,8 +234,8 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes float imat[4][4]; float omat[4][4]; - invert_m4_m4(imat, ctx->object->obmat); - mul_m4_m4m4(omat, imat, bmd->object->obmat); + invert_m4_m4(imat, object_eval->obmat); + mul_m4_m4m4(omat, imat, other_eval->obmat); BMVert *eve; i = 0; @@ -254,10 +257,11 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes negate_m3(nmat); } - const short ob_src_totcol = bmd->object->totcol; + const short ob_src_totcol = other_eval->totcol; short *material_remap = BLI_array_alloca(material_remap, ob_src_totcol ? ob_src_totcol : 1); - BKE_material_remap_object_calc(ctx->object, bmd->object, material_remap); + /* Using original (not evaluated) object here since we are writing to it. */ + BKE_material_remap_object_calc(ctx->object, other_eval, material_remap); BMFace *efa; i = 0; diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 94adb3d9ebc..48653856178 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -275,7 +275,7 @@ static void meshdeform_vert_task( } static void meshdeformModifier_do( - ModifierData *md, Object *ob, Mesh *mesh, + ModifierData *md, Depsgraph *depsgraph, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts) { MeshDeformModifierData *mmd = (MeshDeformModifierData *) md; @@ -307,7 +307,11 @@ static void meshdeformModifier_do( free_cagemesh = true; } else { - cagemesh = BKE_modifier_get_evaluated_mesh_from_object(ob, md->mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0); + ModifierEvalContext ctx = { + .depsgraph = depsgraph, + .flag = md->mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0, + }; + cagemesh = BKE_modifier_get_evaluated_mesh_from_object(&ctx, ob); } /* if we don't have one computed, use derivedmesh from data @@ -421,7 +425,7 @@ static void deformVerts( modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ - meshdeformModifier_do(md, ctx->object, mesh_src, vertexCos, numVerts); + meshdeformModifier_do(md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, numVerts); if (mesh_src && mesh_src != mesh) { BKE_id_free(NULL, mesh_src); @@ -437,7 +441,7 @@ static void deformVertsEM( { Mesh *mesh_src = get_mesh(ctx->object, NULL, mesh, NULL, false, false); - meshdeformModifier_do(md, ctx->object, mesh_src, vertexCos, numVerts); + meshdeformModifier_do(md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, numVerts); if (mesh_src && mesh_src != mesh) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index c2493e6d8f3..72bdcc779ea 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -42,6 +42,7 @@ #include "BKE_cdderivedmesh.h" +#include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_library.h" #include "BKE_modifier.h" @@ -55,7 +56,7 @@ static void initData(ModifierData *md) ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; psmd->psys = NULL; psmd->mesh_final = NULL; - psmd->mesh_deformed = NULL; + psmd->mesh_original = NULL; psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; } static void freeData(ModifierData *md) @@ -65,9 +66,9 @@ static void freeData(ModifierData *md) if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; @@ -88,7 +89,7 @@ static void copyData(const ModifierData *md, ModifierData *target) modifier_copyData_generic(md, target); tpsmd->mesh_final = NULL; - tpsmd->mesh_deformed = NULL; + tpsmd->mesh_original = NULL; tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0; } @@ -129,9 +130,9 @@ static void deformVerts( if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } else if (psmd->flag & eParticleSystemFlag_file_loaded) { @@ -156,20 +157,40 @@ static void deformVerts( BKE_mesh_tessface_ensure(psmd->mesh_final); if (!psmd->mesh_final->runtime.deformed_only) { - /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set. - * This is awfully weak though. :| */ - if (ctx->object->derivedDeform) { - DM_to_mesh(ctx->object->derivedDeform, psmd->mesh_deformed, ctx->object, CD_MASK_EVERYTHING, false); + /* Get the original mesh from the object, this is what the particles + * are attached to so in case of non-deform modifiers we need to remap + * them to the final mesh (typically subdivision surfaces). */ + Mesh *mesh_original = NULL; + + if (ctx->object->type == OB_MESH) { + BMEditMesh *edit_btmesh = BKE_editmesh_from_object(ctx->object); + + if (edit_btmesh) { + /* In edit mode get directly from the edit mesh. */ + psmd->mesh_original = BKE_bmesh_to_mesh_nomain(edit_btmesh->bm, &(struct BMeshToMeshParams){0}); + } + else { + /* Otherwise get regular mesh. */ + mesh_original = ctx->object->data; + } } - else { /* Can happen in some cases, e.g. when rendering from Edit mode... */ - BKE_id_copy_ex(NULL, &mesh_src->id, (ID **)&psmd->mesh_deformed, + else { + mesh_original = mesh_src; + } + + if (mesh_original) { + /* Make a persistent copy of the mesh. We don't actually need + * all this data, just some topology for remapping. Could be + * optimized once. */ + BKE_id_copy_ex(NULL, &mesh_original->id, (ID **)&psmd->mesh_original, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW, false); } - BKE_mesh_tessface_ensure(psmd->mesh_deformed); + + BKE_mesh_tessface_ensure(psmd->mesh_original); } if (mesh_src != psmd->mesh_final && mesh_src != mesh) { diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index ab0b31812b2..f03ae73e2bb 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1041,7 +1041,7 @@ static bool surfacedeformBind( return data.success == 1; } -static Mesh *surfacedeform_get_mesh(SurfaceDeformModifierData *smd, bool *r_needsfree) +static Mesh *surfacedeform_get_mesh(Depsgraph *depsgraph, SurfaceDeformModifierData *smd, bool *r_needsfree) { Mesh *mesh; @@ -1052,8 +1052,11 @@ static Mesh *surfacedeform_get_mesh(SurfaceDeformModifierData *smd, bool *r_need *r_needsfree = true; } else { - mesh = BKE_modifier_get_evaluated_mesh_from_object( - smd->target, smd->modifier.mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0); + ModifierEvalContext ctx = { + .depsgraph = depsgraph, + .flag = smd->modifier.mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0, + }; + mesh = BKE_modifier_get_evaluated_mesh_from_object(&ctx, smd->target); *r_needsfree = false; } @@ -1124,6 +1127,7 @@ static void deformVert( static void surfacedeformModifier_do( ModifierData *md, + const ModifierEvalContext *ctx, float (*vertexCos)[3], unsigned int numverts, Object *ob) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; @@ -1137,7 +1141,7 @@ static void surfacedeformModifier_do( return; } - target = surfacedeform_get_mesh(smd, &free_target); + target = surfacedeform_get_mesh(ctx->depsgraph, smd, &free_target); if (!target) { modifier_setError(md, "No valid target mesh"); return; @@ -1204,7 +1208,7 @@ static void deformVerts( Mesh *UNUSED(mesh), float (*vertexCos)[3], int numVerts) { - surfacedeformModifier_do(md, vertexCos, numVerts, ctx->object); + surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object); } static void deformVertsEM( @@ -1213,7 +1217,7 @@ static void deformVertsEM( Mesh *UNUSED(mesh), float (*vertexCos)[3], int numVerts) { - surfacedeformModifier_do(md, vertexCos, numVerts, ctx->object); + surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object); } static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 207c692071c..b491496caa4 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -55,7 +55,9 @@ #include "MEM_guardedalloc.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" static void initData(ModifierData *md) { @@ -111,7 +113,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } typedef struct Projector { - Object *ob; /* object this projector is derived from */ + Object *ob_eval; /* object this projector is derived from */ float projmat[4][4]; /* projection matrix */ float normal[3]; /* projector normal in world space */ void *uci; /* optional uv-project info (panorama projection) */ @@ -119,6 +121,7 @@ typedef struct Projector { static Mesh *uvprojectModifier_do( UVProjectModifierData *umd, + Depsgraph *depsgraph, Object *ob, Mesh *mesh) { float (*coords)[3], (*co)[3]; @@ -137,7 +140,7 @@ static Mesh *uvprojectModifier_do( for (i = 0; i < umd->num_projectors; ++i) if (umd->projectors[i]) - projectors[num_projectors++].ob = umd->projectors[i]; + projectors[num_projectors++].ob_eval = DEG_get_evaluated_object(depsgraph, umd->projectors[i]); if (num_projectors == 0) return mesh; @@ -154,15 +157,14 @@ static Mesh *uvprojectModifier_do( float offsetmat[4][4]; Camera *cam = NULL; /* calculate projection matrix */ - invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat); + invert_m4_m4(projectors[i].projmat, projectors[i].ob_eval->obmat); projectors[i].uci = NULL; - if (projectors[i].ob->type == OB_CAMERA) { - - cam = (Camera *)projectors[i].ob->data; + if (projectors[i].ob_eval->type == OB_CAMERA) { + cam = (Camera *)projectors[i].ob_eval->data; if (cam->type == CAM_PANO) { - projectors[i].uci = BLI_uvproject_camera_info(projectors[i].ob, NULL, aspx, aspy); + projectors[i].uci = BLI_uvproject_camera_info(projectors[i].ob_eval, NULL, aspx, aspy); BLI_uvproject_camera_info_scale(projectors[i].uci, scax, scay); free_uci = 1; } @@ -171,7 +173,7 @@ static Mesh *uvprojectModifier_do( /* setup parameters */ BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, projectors[i].ob); + BKE_camera_params_from_object(¶ms, projectors[i].ob_eval); /* compute matrix, viewplane, .. */ BKE_camera_params_compute_viewplane(¶ms, 1, 1, aspx, aspy); @@ -200,7 +202,7 @@ static Mesh *uvprojectModifier_do( projectors[i].normal[0] = 0; projectors[i].normal[1] = 0; projectors[i].normal[2] = 1; - mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); + mul_mat3_m4_v3(projectors[i].ob_eval->obmat, projectors[i].normal); } numPolys = mesh->totpoly; @@ -312,7 +314,7 @@ static Mesh *applyModifier( Mesh *result; UVProjectModifierData *umd = (UVProjectModifierData *) md; - result = uvprojectModifier_do(umd, ctx->object, mesh); + result = uvprojectModifier_do(umd, ctx->depsgraph, ctx->object, mesh); return result; } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 64133222c1e..9e77e0d3794 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -506,7 +506,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes const bool use_trgt_faces = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_FACES) != 0; if (use_trgt_verts || use_trgt_edges || use_trgt_faces) { - Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_object(obr, ctx->flag); + Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, obr); /* We must check that we do have a valid target_mesh! */ if (target_mesh != NULL) { diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 5acd0a9fcea..67c86180188 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -173,6 +173,7 @@ set(SRC shader/nodes/node_shader_fresnel.c shader/nodes/node_shader_geometry.c shader/nodes/node_shader_holdout.c + shader/nodes/node_shader_ies_light.c shader/nodes/node_shader_layer_weight.c shader/nodes/node_shader_light_falloff.c shader/nodes/node_shader_light_path.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 3d6a8647628..158d20a5c19 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -136,6 +136,7 @@ void register_node_type_sh_tex_musgrave(void); void register_node_type_sh_tex_noise(void); void register_node_type_sh_tex_checker(void); void register_node_type_sh_bump(void); +void register_node_type_sh_tex_ies(void); #endif diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index efb8eb66737..437093a9cb3 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -126,6 +126,7 @@ DefNode( ShaderNode, SH_NODE_COMBXYZ, 0, "CO DefNode( ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEVEL", Bevel, "Bevel", "" ) DefNode( ShaderNode, SH_NODE_DISPLACEMENT, def_sh_displacement, "DISPLACEMENT", Displacement, "Displacement", "" ) DefNode( ShaderNode, SH_NODE_VECTOR_DISPLACEMENT,def_sh_vector_displacement,"VECTOR_DISPLACEMENT",VectorDisplacement,"Vector Displacement","" ) +DefNode( ShaderNode, SH_NODE_TEX_IES, def_sh_tex_ies, "TEX_IES", TexIES, "IES Texture", "" ) DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index be23c535cba..a1beadbdc03 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -306,6 +306,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node) iuser->sfra = 1; iuser->fie_ima = 2; iuser->ok = 1; + iuser->flag |= IMA_ANIM_ALWAYS; /* setup initial outputs */ cmp_node_image_verify_outputs(ntree, node, false); diff --git a/source/blender/nodes/shader/nodes/node_shader_ies_light.c b/source/blender/nodes/shader/nodes/node_shader_ies_light.c new file mode 100644 index 00000000000..8084f445e34 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_ies_light.c @@ -0,0 +1,61 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** IES Light ******************** */ + +static bNodeSocketTemplate sh_node_tex_ies_in[] = { + { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_tex_ies_out[] = { + { SOCK_FLOAT, 0, N_("Fac")}, + { -1, 0, "" } +}; + +static void node_shader_init_tex_ies(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeShaderTexIES *tex = MEM_callocN(sizeof(NodeShaderTexIES), "NodeShaderIESLight"); + node->storage = tex; +} + +/* node type definition */ +void register_node_type_sh_tex_ies(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_TEX_IES, "IES Texture", NODE_CLASS_TEXTURE, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_tex_ies_in, sh_node_tex_ies_out); + node_type_init(&ntype, node_shader_init_tex_ies); + node_type_storage(&ntype, "NodeShaderTexIES", node_free_standard_storage, node_copy_standard_storage); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 6cd58d2fb85..f36310f4d00 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -221,6 +221,11 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode r = fabsf(a); break; } + case NODE_MATH_ATAN2: + { + r = atan2(a, b); + break; + } } if (node->custom2 & SHD_MATH_CLAMP) { CLAMP(r, 0.0f, 1.0f); @@ -235,6 +240,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED( "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin", "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max", "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs", + "math_atan2" }; switch (node->custom1) { @@ -249,6 +255,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED( case NODE_MATH_LESS: case NODE_MATH_GREATER: case NODE_MATH_MOD: + case NODE_MATH_ATAN2: GPU_stack_link(mat, node, names[node->custom1], in, out); break; case NODE_MATH_SIN: diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c index 69c8f4b7262..fd1e818b63b 100644 --- a/source/blender/nodes/texture/nodes/node_texture_image.c +++ b/source/blender/nodes/texture/nodes/node_texture_image.c @@ -95,6 +95,7 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node) iuser->sfra = 1; iuser->fie_ima = 2; iuser->ok = 1; + iuser->flag |= IMA_ANIM_ALWAYS; } void register_node_type_tex_image(void) diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c index 19bc16fb82d..d8dc2a62625 100644 --- a/source/blender/nodes/texture/nodes/node_texture_math.c +++ b/source/blender/nodes/texture/nodes/node_texture_math.c @@ -189,6 +189,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor break; } + case NODE_MATH_ATAN2: + { + *out = atan2(in0, in1); + break; + } + default: { BLI_assert(0); diff --git a/source/blender/python/intern/stubs.c b/source/blender/python/intern/stubs.c index cc186be60ea..3b3a4d6d2fe 100644 --- a/source/blender/python/intern/stubs.c +++ b/source/blender/python/intern/stubs.c @@ -32,7 +32,7 @@ #include "BPY_extern.h" -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic error "-Wmissing-prototypes" # pragma GCC diagnostic ignored "-Wunused-parameter" #endif diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 4f3f8ece1f0..c800370a85d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1958,14 +1958,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand /* remove modal handler, operator itself should have been canceled and freed */ if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { - /* set cursor back to the default for the region */ - wmWindow *win = CTX_wm_window(C); - WM_cursor_grab_disable(win, NULL); - /* Causes crash when joining areas: T55166, seems this is not even needed. */ -#if 0 - ED_region_cursor_set(win, area, region); -#endif - + WM_cursor_grab_disable(CTX_wm_window(C), NULL); BLI_remlink(handlers, handler); wm_event_free_handler(handler); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 9d26c7e92d5..f2387846fd2 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1215,9 +1215,11 @@ static wmKeyMapItem *wm_keymap_item_find_props( /* look into multiple handler lists to find the item */ if (win) { - found = wm_keymap_item_find_handlers(C, &win->modalhandlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); + found = wm_keymap_item_find_handlers( + C, &win->modalhandlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); if (found == NULL) { - found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); + found = wm_keymap_item_find_handlers( + C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1fe0799d6c1..7cf1fe3bdfa 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2248,7 +2248,7 @@ static int wm_call_panel_exec(bContext *C, wmOperator *op) const int space_type = RNA_enum_get(op->ptr, "space_type"); const int region_type = RNA_enum_get(op->ptr, "region_type"); - return UI_popover_panel_invoke(C, space_type, region_type, idname, op->reports); + return UI_popover_panel_invoke(C, space_type, region_type, idname, true, op->reports); } static void WM_OT_call_panel(wmOperatorType *ot) diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c index f5a8746f807..5634a1a3ee7 100644 --- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c +++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c @@ -509,7 +509,7 @@ void wm_manipulator_calculate_scale(wmManipulator *mpr, const bContext *C) } /* Exclude matrix_offset from scale. */ - scale *= ED_view3d_pixel_size(rv3d, matrix_world[3]) / U.pixelsize; + scale *= ED_view3d_pixel_size_no_ui_scale(rv3d, matrix_world[3]); } else { scale *= 0.02f; diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc index f6f7e17c8ca..f3a12cef26a 100644 --- a/tests/gtests/blenlib/BLI_string_test.cc +++ b/tests/gtests/blenlib/BLI_string_test.cc @@ -364,6 +364,72 @@ TEST(string, StrFormatIntGrouped) EXPECT_STREQ("-999", num_str); } +/* BLI_str_format_byte_unit */ +TEST(string, StrFormatByteUnits) +{ + char size_str[15]; + long long int size; + + /* Base 10 */ + BLI_str_format_byte_unit(size_str, size = 0, true); + EXPECT_STREQ("0 B", size_str); + BLI_str_format_byte_unit(size_str, size = -0, true); + EXPECT_STREQ("0 B", size_str); + + BLI_str_format_byte_unit(size_str, size = 1, true); + EXPECT_STREQ("1 B", size_str); + BLI_str_format_byte_unit(size_str, size = -1, true); + EXPECT_STREQ("-1 B", size_str); + + BLI_str_format_byte_unit(size_str, size = 1000, true); + EXPECT_STREQ("1 KB", size_str); + BLI_str_format_byte_unit(size_str, size = -1000, true); + EXPECT_STREQ("-1 KB", size_str); + + BLI_str_format_byte_unit(size_str, size = 1024, true); + EXPECT_STREQ("1 KB", size_str); + BLI_str_format_byte_unit(size_str, size = -1024, true); + EXPECT_STREQ("-1 KB", size_str); + + BLI_str_format_byte_unit(size_str, size = 9223372036854775807, true); /* LLONG_MAX - largest possible value */ + EXPECT_STREQ("9223.372 PB", size_str); + BLI_str_format_byte_unit(size_str, size = -9223372036854775807, true); + EXPECT_STREQ("-9223.372 PB", size_str); + + + /* Base 2 */ + BLI_str_format_byte_unit(size_str, size = 0, false); + EXPECT_STREQ("0 B", size_str); + BLI_str_format_byte_unit(size_str, size = -0, false); + EXPECT_STREQ("0 B", size_str); + + BLI_str_format_byte_unit(size_str, size = 1, false); + EXPECT_STREQ("1 B", size_str); + BLI_str_format_byte_unit(size_str, size = -1, false); + EXPECT_STREQ("-1 B", size_str); + + BLI_str_format_byte_unit(size_str, size = 1000, false); + EXPECT_STREQ("1000 B", size_str); + BLI_str_format_byte_unit(size_str, size = -1000, false); + EXPECT_STREQ("-1000 B", size_str); + + BLI_str_format_byte_unit(size_str, size = 1024, false); + EXPECT_STREQ("1 KiB", size_str); + BLI_str_format_byte_unit(size_str, size = -1024, false); + EXPECT_STREQ("-1 KiB", size_str); + + BLI_str_format_byte_unit(size_str, size = 9223372036854775807, false); /* LLONG_MAX - largest possible value */ + EXPECT_STREQ("8192.0 PiB", size_str); + BLI_str_format_byte_unit(size_str, size = -9223372036854775807, false); + EXPECT_STREQ("-8192.0 PiB", size_str); + + /* Test maximum string length. */ + BLI_str_format_byte_unit(size_str, size = -9223200000000000000, false); + EXPECT_STREQ("-8191.8472 PiB", size_str); +} + + + #define STRING_FIND_SPLIT_WORDS_EX(word_str_src, word_str_src_len, limit_words, ...) \ { \ int word_info[][2] = \ diff --git a/tests/python/eevee_render_tests.py b/tests/python/eevee_render_tests.py index 9756f7a1840..74e716dc8e6 100755 --- a/tests/python/eevee_render_tests.py +++ b/tests/python/eevee_render_tests.py @@ -15,14 +15,14 @@ def setup(): scene = bpy.context.scene eevee = scene.eevee - eevee.sss_enable = True - eevee.ssr_enable = True - eevee.ssr_refraction = True - eevee.gtao_enable = True - eevee.dof_enable = True - - eevee.volumetric_enable = True - eevee.volumetric_shadows = True + eevee.use_sss = True + eevee.use_ssr = True + eevee.use_ssr_refraction = True + eevee.use_gtao = True + eevee.use_dof = True + + eevee.use_volumetric = True + eevee.use_volumetric_shadows = True eevee.volumetric_tile_size = '2' for mat in bpy.data.materials: |