diff options
109 files changed, 2208 insertions, 1208 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 39b75d9a32b..e2dda8553d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -562,12 +562,12 @@ set(PLATFORM_LINKFLAGS_DEBUG "") if(UNIX AND NOT APPLE) macro(find_package_wrapper) string(TOUPPER ${ARGV0} _NAME_UPPER) - if(${WITH_STATIC_LIBS}) + if(WITH_STATIC_LIBS) set(_cmake_find_library_suffixes_back ${CMAKE_FIND_LIBRARY_SUFFIXES}) set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) endif() find_package(${ARGV}) - if(${WITH_STATIC_LIBS}) + if(WITH_STATIC_LIBS) set(CMAKE_FIND_LIBRARY_SUFFIXES ${_cmake_find_library_suffixes_back}) unset(_cmake_find_library_suffixes_back) endif() @@ -707,7 +707,7 @@ if(UNIX AND NOT APPLE) if(WITH_BOOST) # uses in build instructions to override include and library variables if(NOT BOOST_CUSTOM) - if(${WITH_STATIC_LIBS}) + if(WITH_STATIC_LIBS) set(Boost_USE_STATIC_LIBS ON) endif() set(Boost_USE_MULTITHREADED ON) @@ -1124,26 +1124,22 @@ elseif(WIN32) ${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader ${OPENCOLLADA}/include/opencollada/GeneratedSaxParser ) - set_lib_path(OPENCOLLADA_LIBPATH "opencollada") set(OPENCOLLADA_LIBRARIES - ${OPENCOLLADA_LIBPATH}/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/OpenCOLLADAFramework.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/OpenCOLLADABaseUtils.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/OpenCOLLADAStreamWriter.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/MathMLSolver.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/GeneratedSaxParser.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/xml.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/buffer.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/ftoa.lib - ${OPENCOLLADA_LIBPATH}/lib/opencollada/UTF.lib + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAFramework.lib + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADABaseUtils.lib + ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib + ${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib + ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib + ${OPENCOLLADA}/lib/opencollada/xml.lib + ${OPENCOLLADA}/lib/opencollada/buffer.lib + ${OPENCOLLADA}/lib/opencollada/ftoa.lib + ${OPENCOLLADA}/lib/opencollada/UTF.lib ) set(PCRE_LIBRARIES - ${OPENCOLLADA_LIBPATH}/lib/opencollada/pcre.lib + ${OPENCOLLADA}/lib/opencollada/pcre.lib ) - - unset(OPENCOLLADA_LIBPATH) - endif() if(WITH_CODEC_FFMPEG) @@ -1172,7 +1168,7 @@ elseif(WIN32) endif() if(WITH_IMAGE_OPENEXR) - set_lib_path(OPENEXR "openexr") + set(OPENEXR ${LIBDIR}/openexr) set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) set(OPENEXR_LIBPATH ${OPENEXR}/lib) @@ -1199,18 +1195,11 @@ elseif(WIN32) endif() if(WITH_PYTHON) - # normally cached but not since we include them with blender - if(MSVC10) - set(PYTHON_VERSION 3.3) # CACHE STRING) - else() - set(PYTHON_VERSION 3.3) # CACHE STRING) - endif() + set(PYTHON_VERSION 3.3) # CACHE STRING) - set_lib_path(PYTHON "python") string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) # Use shared libs for vc2008 and vc2010 until we actually have vc2010 libs set(PYTHON_LIBRARY ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) - # set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH unset(_PYTHON_VERSION_NO_DOTS) # Shared includes for both vc2008 and vc2010 @@ -1228,10 +1217,6 @@ elseif(WIN32) set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_POSTFIX "vc110-mt-s-1_53.lib") set(BOOST_DEBUG_POSTFIX "vc110-mt-sgd-1_53.lib") - elseif(MSVC10) - set(BOOST_LIBPATH ${BOOST}/vc2010/lib) - set(BOOST_POSTFIX "vc100-mt-s-1_49.lib") - set(BOOST_DEBUG_POSTFIX "vc100-mt-sgd-1_49.lib") else() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_POSTFIX "vc90-mt-s-1_49.lib") @@ -2084,13 +2069,6 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") endif() -# MSVC2010 fails to links C++ libs right -if(MSVC10) - if(WITH_OPENCOLLADA) - message(WARNING "MSVC 2010 does not support OpenCollada, disabling WITH_OPENCOLLADA. To enable support use Use MSVC 2008") - endif() -endif() - # ensure python header is found since detection can fail, this could happen # with _any_ library but since we used a fixed python version this tends to # be most problematic. diff --git a/SConstruct b/SConstruct index 94acdbbab92..0a7fa2aec9e 100644 --- a/SConstruct +++ b/SConstruct @@ -137,6 +137,8 @@ else: B.quickie=[] toolset = B.arguments.get('BF_TOOLSET', None) +vcver = B.arguments.get('MSVS_VERSION', '9.0') + if toolset: print "Using " + toolset if toolset=='mstoolkit': @@ -148,9 +150,9 @@ if toolset: btools.SetupSpawn(env) else: if bitness==64 and platform=='win32': - env = BlenderEnvironment(ENV = os.environ, MSVS_ARCH='amd64') + env = BlenderEnvironment(ENV = os.environ, MSVS_ARCH='amd64', TARGET_ARCH='x86_64', MSVC_VERSION=vcver) else: - env = BlenderEnvironment(ENV = os.environ) + env = BlenderEnvironment(ENV = os.environ, TARGET_ARCH='x86', MSVC_VERSION=vcver) if not env: print "Could not create a build environment" @@ -384,6 +386,8 @@ else: env['CPPFLAGS'].append('-DWITH_AUDASPACE') env['CPPFLAGS'].append('-DWITH_AVI') env['CPPFLAGS'].append('-DWITH_BOOL_COMPAT') +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc') and env['MSVC_VERSION'] == '11.0': + env['CPPFLAGS'].append('-D_ALLOW_KEYWORD_MACROS') if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc'): env['CPPFLAGS'].append('-DHAVE_STDBOOL_H') @@ -940,7 +944,10 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): if env['WITH_BF_OPENAL']: dllsources.append('${LCGDIR}/openal/lib/OpenAL32.dll') - dllsources.append('${LCGDIR}/openal/lib/wrap_oal.dll') + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc') and env['MSVC_VERSION'] == '11.0': + pass + else: + dllsources.append('${LCGDIR}/openal/lib/wrap_oal.dll') if env['WITH_BF_SNDFILE']: dllsources.append('${LCGDIR}/sndfile/lib/libsndfile-1.dll') diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 7e50798b33f..33879ccff17 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -143,6 +143,8 @@ else: scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe') if builder.find('mingw') != -1: scons_options.append('BF_TOOLSET=mingw') + if builder.endswith('vc2012'): + scons_options.append('MSVS_VERSION=11.0') scons_options.append('BF_NUMJOBS=1') elif builder.find('mac') != -1: @@ -156,7 +158,10 @@ else: retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) if builder.find('win') != -1: - dlls = ('msvcm90.dll', 'msvcp90.dll', 'msvcr90.dll', 'vcomp90.dll', 'Microsoft.VC90.CRT.manifest', 'Microsoft.VC90.OpenMP.manifest') + if builder.endswith('vc2012'): + dlls = ('msvcp110.dll', 'msvcr110.dll', 'vcomp110.dll') + else: + dlls = ('msvcm90.dll', 'msvcp90.dll', 'msvcr90.dll', 'vcomp90.dll', 'Microsoft.VC90.CRT.manifest', 'Microsoft.VC90.OpenMP.manifest') if builder.find('win64') == -1: dlls_path = '..\\..\\..\\redist\\x86' else: diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index 3c2569e4a69..3e8ae939dd5 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -99,6 +99,8 @@ if builder.find('scons') != -1: scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe') if builder.find('mingw') != -1: scons_options.append('BF_TOOLSET=mingw') + if builder.endswith('vc2012'): + scons_options.append('MSVS_VERSION=11.0') elif builder.find('mac') != -1: if builder.find('x86_64') != -1: diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake index 9f1d6571ef5..9ea0f6c9efd 100644 --- a/build_files/cmake/Modules/FindOpenEXR.cmake +++ b/build_files/cmake/Modules/FindOpenEXR.cmake @@ -52,11 +52,11 @@ SET(_openexr_SEARCH_DIRS FIND_PATH(OPENEXR_INCLUDE_DIR NAMES - ImfXdr.h + OpenEXR/ImfXdr.h HINTS ${_openexr_SEARCH_DIRS} PATH_SUFFIXES - include/OpenEXR + include ) SET(_openexr_LIBRARIES) @@ -82,7 +82,8 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenEXR DEFAULT_MSG IF(OPENEXR_FOUND) SET(OPENEXR_LIBRARIES ${_openexr_LIBRARIES}) - SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR}) + # Both include paths are needed because of dummy OSL headers mixing #include <OpenEXR/foo.h> and #include <foo.h> :( + SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}/OpenEXR) ENDIF() MARK_AS_ADVANCED(OPENEXR_INCLUDE_DIR) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 2b5cfbc31cc..b1dd76fbd14 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -751,17 +751,6 @@ function(delayed_do_install endif() endfunction() -macro(set_lib_path - lvar - lproj) - - if(MSVC10) - set(${lvar} ${LIBDIR}/${lproj}/vc2010) - else() - set(${lvar} ${LIBDIR}/${lproj}) - endif() -endmacro() - macro(data_to_c file_from file_to diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index e43bb5336b8..bceab628b47 100644 --- a/build_files/scons/config/win32-vc-config.py +++ b/build_files/scons/config/win32-vc-config.py @@ -1,12 +1,28 @@ -LCGDIR = '#../lib/windows' +import subprocess + +CL_OUT = subprocess.Popen(["cl.exe"],stdout=subprocess.PIPE,stderr=subprocess.PIPE) +CL_STDOUT, CL_STDERR = CL_OUT.communicate() + +if CL_STDERR.find("Version 15.00.") == -1: + VC_VERSION = '11.0' + LCGDIR = '#../lib/windows_vc11' + +else: + VC_VERSION = '9.0' + LCGDIR = '#../lib/windows' + LIBDIR = '${LCGDIR}' WITH_BF_FFMPEG = True BF_FFMPEG = LIBDIR +'/ffmpeg' BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' -BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib swscale-2.lib' -BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll' +if VC_VERSION == '11.0': + BF_FFMPEG_LIB = 'avformat-54.lib avcodec-54.lib avdevice-54.lib avutil-52.lib avfilter-3.lib swscale-2.lib swresample-0.lib' + BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-54.dll ${BF_FFMPEG_LIBPATH}/avcodec-54.dll ${BF_FFMPEG_LIBPATH}/avdevice-54.dll ${BF_FFMPEG_LIBPATH}/avutil-52.dll ${BF_FFMPEG_LIBPATH}/avfilter-3.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll ${BF_FFMPEG_LIBPATH}/swresample-0.dll' +else: + BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib swscale-2.lib' + BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll' BF_PYTHON = LIBDIR + '/python' BF_PYTHON_VERSION = '3.3' @@ -19,7 +35,10 @@ BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = True BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include ' -BF_OPENAL_LIB = 'wrap_oal' +if VC_VERSION == '11.0': + BF_OPENAL_LIB = 'OpenAL32' +else: + BF_OPENAL_LIB = 'wrap_oal' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' WITH_BF_ICONV = True @@ -43,7 +62,10 @@ BF_SNDFILE_LIBPATH = '${BF_SNDFILE}/lib' WITH_BF_SDL = True BF_SDL = LIBDIR + '/sdl' BF_SDL_INC = '${BF_SDL}/include' -BF_SDL_LIB = 'SDL.lib' +if VC_VERSION == '11.0': + BF_SDL_LIB = 'SDL.lib dxguid.lib' +else: + BF_SDL_LIB = 'SDL.lib' BF_SDL_LIBPATH = '${BF_SDL}/lib' BF_PTHREADS = LIBDIR + '/pthreads' @@ -182,8 +204,12 @@ WITH_BF_STATICOCIO = True WITH_BF_BOOST = True BF_BOOST = '${LIBDIR}/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49' -BF_BOOST_LIB_INTERNATIONAL = 'libboost_locale-vc90-mt-s-1_49' +if VC_VERSION == '11.0': + BF_BOOST_LIB = 'libboost_date_time-vc110-mt-s-1_53 libboost_filesystem-vc110-mt-s-1_53 libboost_regex-vc110-mt-s-1_53 libboost_system-vc110-mt-s-1_53 libboost_thread-vc110-mt-s-1_53 libboost_wave-vc110-mt-s-1_53' + BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc110-mt-s-1_53' +else: + BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49' + BF_BOOST_LIB_INTERNATIONAL = 'libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA @@ -209,16 +235,16 @@ BF_OPENGL_LIB_STATIC = [ '${BF_OPENGL}/lib/libGL.a', '${BF_OPENGL}/lib/libGLU.a' CC = 'cl.exe' CXX = 'cl.exe' -CCFLAGS = ['/nologo', '/Ob1', '/J', '/W1', '/Gd', '/wd4018', '/wd4244', '/wd4305', '/wd4800', '/wd4065', '/wd4267', '/we4013'] +CCFLAGS = ['/nologo', '/J', '/W1', '/Gd', '/wd4018', '/wd4244', '/wd4305', '/wd4800', '/wd4065', '/wd4267', '/we4013'] CXXFLAGS = ['/EHsc'] -BGE_CXXFLAGS = ['/O2', '/EHsc', '/GR', '/fp:fast', '/arch:SSE'] +BGE_CXXFLAGS = ['/O2', '/Ob2', '/EHsc', '/GR', '/fp:fast', '/arch:SSE'] -BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr'] +BF_DEBUG_CCFLAGS = ['/Zi', '/Ob0', '/Od', '/FR${TARGET}.sbr'] CPPFLAGS = ['-DWIN32','-D_CONSOLE', '-D_LIB', '-D_CRT_SECURE_NO_DEPRECATE', '-DOPJ_STATIC'] REL_CFLAGS = [] REL_CXXFLAGS = [] -REL_CCFLAGS = ['-O2', '-DNDEBUG'] +REL_CCFLAGS = ['-O2', '/Ob2', '-DNDEBUG'] C_WARN = [] CC_WARN = [] @@ -235,5 +261,9 @@ PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/STACK:2097152','/IN BF_BSC=False -BF_BUILDDIR = '..\\build\\win32-vc' -BF_INSTALLDIR='..\\install\\win32-vc' +if VC_VERSION == '11.0': + BF_BUILDDIR = '..\\build\\win32-vc11' + BF_INSTALLDIR='..\\install\\win32-vc11' +else: + BF_BUILDDIR = '..\\build\\win32-vc' + BF_INSTALLDIR='..\\install\\win32-vc' diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index eb3533cdb8b..c7bf2fa0bd2 100644 --- a/build_files/scons/config/win64-vc-config.py +++ b/build_files/scons/config/win64-vc-config.py @@ -1,12 +1,29 @@ -LCGDIR = '#../lib/win64' +import subprocess + +CL_OUT = subprocess.Popen(["cl.exe"],stdout=subprocess.PIPE,stderr=subprocess.PIPE) +CL_STDOUT, CL_STDERR = CL_OUT.communicate() + +if CL_STDERR.find("Version 15.00.") == -1: + VC_VERSION = '11.0' + LCGDIR = '#../lib/win64_vc11' + +else: + VC_VERSION = '9.0' + LCGDIR = '#../lib/win64' + LIBDIR = '${LCGDIR}' WITH_BF_FFMPEG = True BF_FFMPEG = LIBDIR +'/ffmpeg' BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc ' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' -BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib swscale-2.lib' -BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll' +if VC_VERSION == '11.0': + BF_FFMPEG_LIB = 'avformat-54.lib avcodec-54.lib avdevice-54.lib avutil-52.lib avfilter-3.lib swscale-2.lib swresample-0.lib' + BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-54.dll ${BF_FFMPEG_LIBPATH}/avcodec-54.dll ${BF_FFMPEG_LIBPATH}/avdevice-54.dll ${BF_FFMPEG_LIBPATH}/avutil-52.dll ${BF_FFMPEG_LIBPATH}/avfilter-3.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll ${BF_FFMPEG_LIBPATH}/swresample-0.dll' +else: + BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib swscale-2.lib' + BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll' + BF_PYTHON = LIBDIR + '/python' BF_PYTHON_VERSION = '3.3' @@ -19,7 +36,10 @@ BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = True BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include ' -BF_OPENAL_LIB = 'wrap_oal' +if VC_VERSION == '11.0': + BF_OPENAL_LIB = 'OpenAL32' +else: + BF_OPENAL_LIB = 'wrap_oal' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' WITH_BF_SNDFILE = True @@ -37,7 +57,10 @@ BF_ICONV_LIBPATH = '${BF_ICONV}/lib' WITH_BF_SDL = True BF_SDL = LIBDIR + '/sdl' BF_SDL_INC = '${BF_SDL}/include' -BF_SDL_LIB = 'SDL.lib' +if VC_VERSION == '11.0': + BF_SDL_LIB = 'SDL.lib dxguid.lib' +else: + BF_SDL_LIB = 'SDL.lib' BF_SDL_LIBPATH = '${BF_SDL}/lib' WITH_BF_JACK = False @@ -178,8 +201,12 @@ WITH_BF_STATICOCIO = True WITH_BF_BOOST = True BF_BOOST = '${LIBDIR}/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49' -BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc90-mt-s-1_49' +if VC_VERSION == '11.0': + BF_BOOST_LIB = 'libboost_date_time-vc110-mt-s-1_53 libboost_filesystem-vc110-mt-s-1_53 libboost_regex-vc110-mt-s-1_53 libboost_system-vc110-mt-s-1_53 libboost_thread-vc110-mt-s-1_53 libboost_wave-vc110-mt-s-1_53' + BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc110-mt-s-1_53' +else: + BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49' + BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA @@ -206,16 +233,16 @@ CC = 'cl.exe' CXX = 'cl.exe' CFLAGS = [] -CCFLAGS = ['/nologo', '/Ob1', '/J', '/W1', '/Gd', '/we4013', '/wd4018', '/wd4244', '/wd4305', '/wd4800', '/wd4065', '/wd4267'] +CCFLAGS = ['/nologo', '/J', '/W1', '/Gd', '/we4013', '/wd4018', '/wd4244', '/wd4305', '/wd4800', '/wd4065', '/wd4267'] CXXFLAGS = ['/EHsc'] -BGE_CXXFLAGS = ['/O2', '/EHsc', '/GR', '/fp:fast'] +BGE_CXXFLAGS = ['/O2', '/Ob2', '/EHsc', '/GR', '/fp:fast'] -BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr', '/Od'] +BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr', '/Od', '/Ob0'] CPPFLAGS = ['-DWIN32', '-D_CONSOLE', '-D_LIB', '-D_CRT_SECURE_NO_DEPRECATE', '-DOPJ_STATIC'] REL_CFLAGS = [] REL_CXXFLAGS = [] -REL_CCFLAGS = ['-O2', '-DNDEBUG'] +REL_CCFLAGS = ['-O2', '/Ob2', '-DNDEBUG'] C_WARN = [] CC_WARN = [] @@ -224,7 +251,9 @@ CXX_WARN = [] LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi'] PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:X64','/STACK:2097152','/OPT:NOREF','/INCREMENTAL:NO', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib'] - -BF_BUILDDIR = '..\\build\\win64-vc' -BF_INSTALLDIR='..\\install\\win64-vc' - +if VC_VERSION == '11.0': + BF_BUILDDIR = '..\\build\\win64-vc11' + BF_INSTALLDIR='..\\install\\win64-vc11' +else: + BF_BUILDDIR = '..\\build\\win64-vc' + BF_INSTALLDIR='..\\install\\win64-vc' diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index f98e9a28c44..90674113f47 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -190,7 +190,7 @@ def validate_arguments(args, bc): 'BF_BSC', 'BF_CONFIG', 'BF_PRIORITYLIST', 'BF_BUILDINFO','CC', 'CXX', 'BF_QUICKDEBUG', 'BF_LISTDEBUG', 'LCGDIR', 'BF_X264_CONFIG', 'BF_XVIDCORE_CONFIG', - 'BF_UNIT_TEST', 'BF_BITNESS'] + 'BF_UNIT_TEST', 'BF_BITNESS', 'MSVS_VERSION'] okdict = {} @@ -233,8 +233,6 @@ class OurSpawn: stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env=env) data, err = proc.communicate() rv = proc.wait() - if data: - print(data) if err: print(err) return rv @@ -689,6 +687,9 @@ def buildslave(target=None, source=None, env=None): if platform == 'darwin': platform = 'OSX-' + env['MACOSX_DEPLOYMENT_TARGET'] + '-' + env['MACOSX_ARCHITECTURE'] + if env['MSVC_VERSION'] == '11.0': + platform = env['OURPLATFORM'] + '11' + branch = env['BUILDBOT_BRANCH'] outdir = os.path.abspath(env['BF_INSTALLDIR']) diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 226218ae512..cc132a2c3b2 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -13,12 +13,17 @@ if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD) endif() if(WIN32 AND MSVC) - set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc") - set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /EHsc") + # there is no /arch:SSE3, but intrinsics are available anyway + set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-") + set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} /Ox") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_RELEASE} /Ox") elseif(CMAKE_COMPILER_IS_GNUCC) set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse") - set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mfpmath=sse") + set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") endif() diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index a7a4bc22dea..d1f1b287e00 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -79,14 +79,15 @@ if env['WITH_BF_RAYOPTIMIZATION']: sse3_cxxflags = Split(env['CXXFLAGS']) if env['OURPLATFORM'] == 'win32-vc': - sse2_cxxflags.append('/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) - sse3_cxxflags.append('/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) + # there is no /arch:SSE3, but intrinsics are available anyway + sse2_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split()) + sse3_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split()) elif env['OURPLATFORM'] == 'win64-vc': - sse2_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) - sse3_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) + sse2_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split()) + sse3_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split()) else: sse2_cxxflags.append('-ffast-math -msse -msse2 -mfpmath=sse'.split()) - sse3_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mfpmath=sse'.split()) + sse3_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse'.split()) defs.append('WITH_OPTIMIZED_KERNEL') optim_defs = defs[:] diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index e1015fa3cee..b451b8ef3bf 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -21,7 +21,7 @@ bl_info = { "name": "Cycles Render Engine", "author": "", - "blender": (2, 66, 0), + "blender": (2, 67, 0), "location": "Info header, render engine menu", "description": "Cycles Render Engine integration", "warning": "", diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 0c6cf9f513a..ca49ffccd2a 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -504,6 +504,12 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup): "objects that emit little light compared to other light sources", default=True, ) + cls.use_transparent_shadow = BoolProperty( + name="Transparent Shadows", + description="Use transparent shadows for this material if it contains a Transparent BSDF, " + "disabling will render faster but not give accurate shadows", + default=True, + ) cls.homogeneous_volume = BoolProperty( name="Homogeneous Volume", description="When using volume rendering, assume volume has the same density everywhere, " diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index c8d41250754..f90881b9338 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -912,10 +912,13 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel): col = split.column() col.prop(mat, "diffuse_color", text="Viewport Color") - col = split.column() + col = split.column(align=True) + col.label() col.prop(mat, "pass_index") - - layout.prop(cmat, "sample_as_light") + + col = layout.column() + col.prop(cmat, "sample_as_light") + col.prop(cmat, "use_transparent_shadow") class CyclesTexture_PT_context(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index f2671185301..ee6a0887d45 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -863,7 +863,8 @@ void BlenderSync::sync_materials(bool update_all) /* settings */ PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles"); - shader->sample_as_light = get_boolean(cmat, "sample_as_light"); + shader->use_mis = get_boolean(cmat, "sample_as_light"); + shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow"); shader->homogeneous_volume = get_boolean(cmat, "homogeneous_volume"); shader->set_graph(graph); diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 82a444bda76..dd647fec2d3 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -552,9 +552,9 @@ void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int { int4 data[BVH_NODE_SIZE] = { - make_int4(__float_as_int(b0.min.x), __float_as_int(b0.max.x), __float_as_int(b0.min.y), __float_as_int(b0.max.y)), - make_int4(__float_as_int(b1.min.x), __float_as_int(b1.max.x), __float_as_int(b1.min.y), __float_as_int(b1.max.y)), - make_int4(__float_as_int(b0.min.z), __float_as_int(b0.max.z), __float_as_int(b1.min.z), __float_as_int(b1.max.z)), + make_int4(__float_as_int(b0.min.x), __float_as_int(b1.min.x), __float_as_int(b0.max.x), __float_as_int(b1.max.x)), + make_int4(__float_as_int(b0.min.y), __float_as_int(b1.min.y), __float_as_int(b0.max.y), __float_as_int(b1.max.y)), + make_int4(__float_as_int(b0.min.z), __float_as_int(b1.min.z), __float_as_int(b0.max.z), __float_as_int(b1.max.z)), make_int4(c0, c1, visibility0, visibility1) }; @@ -579,6 +579,7 @@ void RegularBVH::pack_nodes(const array<int>& prims, const BVHNode *root) int nextNodeIdx = 0; vector<BVHStackEntry> stack; + stack.reserve(BVHParams::MAX_DEPTH*2); stack.push_back(BVHStackEntry(root, nextNodeIdx++)); while(stack.size()) { @@ -776,6 +777,7 @@ void QBVH::pack_nodes(const array<int>& prims, const BVHNode *root) int nextNodeIdx = 0; vector<BVHStackEntry> stack; + stack.reserve(BVHParams::MAX_DEPTH*2); stack.push_back(BVHStackEntry(root, nextNodeIdx++)); while(stack.size()) { diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index f32c6dde639..1f96ed0ae83 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -271,11 +271,53 @@ public: return ""; } + int cuda_version = cuCompilerVersion(); + + if(cuda_version == 0) { + cuda_error_message("CUDA nvcc compiler version could not be parsed."); + return ""; + } + + if(cuda_version != 50) + printf("CUDA version %d.%d detected, build may succeed but only CUDA 5.0 is officially supported.\n", cuda_version/10, cuda_version%10); + /* compile */ string kernel = path_join(kernel_path, "kernel.cu"); string include = kernel_path; const int machine = system_cpu_bits(); - const int maxreg = 24; + string arch_flags; + + /* build flags depending on CUDA version and arch */ + if(cuda_version < 50) { + /* CUDA 4.x */ + if(major == 1) { + /* sm_1x */ + arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0"; + } + else if(major == 2) { + /* sm_2x */ + arch_flags = "--maxrregcount=24"; + } + else { + /* sm_3x */ + arch_flags = "--maxrregcount=32"; + } + } + else { + /* CUDA 4.x */ + if(major == 1) { + /* sm_1x */ + arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0 --use_fast_math"; + } + else if(major == 2) { + /* sm_2x */ + arch_flags = "--maxrregcount=32 --use_fast_math"; + } + else { + /* sm_3x */ + arch_flags = "--maxrregcount=32 --use_fast_math"; + } + } double starttime = time_dt(); printf("Compiling CUDA kernel ...\n"); @@ -283,8 +325,10 @@ public: path_create_directories(cubin); string command = string_printf("\"%s\" -arch=sm_%d%d -m%d --cubin \"%s\" " - "-o \"%s\" --ptxas-options=\"-v\" --maxrregcount=%d --opencc-options -OPT:Olimit=0 -I\"%s\" -DNVCC", - nvcc.c_str(), major, minor, machine, kernel.c_str(), cubin.c_str(), maxreg, include.c_str()); + "-o \"%s\" --ptxas-options=\"-v\" %s -I\"%s\" -DNVCC -D__KERNEL_CUDA_VERSION__=%d", + nvcc.c_str(), major, minor, machine, kernel.c_str(), cubin.c_str(), arch_flags.c_str(), include.c_str(), cuda_version); + + printf("%s\n", command.c_str()); if(system(command.c_str()) == -1) { cuda_error_message("Failed to execute compilation command, see console for details."); diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 0fb5c7abafb..2ee4ffaca17 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -85,7 +85,7 @@ static string opencl_kernel_build_options(const string& platform, const string * string build_options = " -cl-fast-relaxed-math "; if(platform == "NVIDIA CUDA") - build_options += "-D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=24 -cl-nv-verbose "; + build_options += "-D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=32 -cl-nv-verbose "; else if(platform == "Apple") build_options += "-D__KERNEL_OPENCL_APPLE__ -Wno-missing-prototypes "; diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 1dcf63f9e47..753d32f5182 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -118,32 +118,68 @@ set(SRC_UTIL_HEADERS # CUDA module if(WITH_CYCLES_CUDA_BINARIES) + # 32 bit or 64 bit if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(CUDA_BITS 64) else() set(CUDA_BITS 32) endif() + # CUDA version + execute_process (COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT) + string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR ${NVCC_OUT}) + string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR ${NVCC_OUT}) + set(CUDA_VERSION "${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}") + + # build for each arch set(cuda_sources kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_UTIL_HEADERS}) set(cuda_cubins) foreach(arch ${CYCLES_CUDA_BINARIES_ARCH}) set(cuda_cubin kernel_${arch}.cubin) - if(${arch} MATCHES "sm_1[0-9]") - # sm_1x - set(cuda_arch_flags "--maxrregcount=24 --opencc-options -OPT:Olimit=0") - elseif(${arch} MATCHES "sm_2[0-9]") - # sm_2x - set(cuda_arch_flags "--maxrregcount=24") + set(cuda_version_flags "-D__KERNEL_CUDA_VERSION__=${CUDA_VERSION}") + + # warn for other versions + if(CUDA_VERSION MATCHES "50") + else() + message(STATUS "CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, build may succeed but only CUDA 5.0 is officially supported") + endif() + + # build flags depending on CUDA version and arch + if(CUDA_VERSION LESS 50) + # CUDA 4.x + if(${arch} MATCHES "sm_1[0-9]") + # sm_1x + set(cuda_arch_flags "--maxrregcount=24 --opencc-options -OPT:Olimit=0") + elseif(${arch} MATCHES "sm_2[0-9]") + # sm_2x + set(cuda_arch_flags "--maxrregcount=24") + else() + # sm_3x + set(cuda_arch_flags "--maxrregcount=32") + endif() + + set(cuda_math_flags "") else() - # sm_3x - set(cuda_arch_flags "--maxrregcount=32") + # CUDA 5.x + if(${arch} MATCHES "sm_1[0-9]") + # sm_1x + set(cuda_arch_flags "--maxrregcount=24 --opencc-options -OPT:Olimit=0") + elseif(${arch} MATCHES "sm_2[0-9]") + # sm_2x + set(cuda_arch_flags "--maxrregcount=32") + else() + # sm_3x + set(cuda_arch_flags "--maxrregcount=32") + endif() + + set(cuda_math_flags "--use_fast_math") endif() add_custom_command( OUTPUT ${cuda_cubin} - COMMAND ${CUDA_NVCC_EXECUTABLE} -arch=${arch} -m${CUDA_BITS} --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cu -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin} --ptxas-options="-v" ${cuda_arch_flags} -I${CMAKE_CURRENT_SOURCE_DIR}/../util -I${CMAKE_CURRENT_SOURCE_DIR}/svm -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -DNVCC + COMMAND ${CUDA_NVCC_EXECUTABLE} -arch=${arch} -m${CUDA_BITS} --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cu -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin} --ptxas-options="-v" ${cuda_arch_flags} ${cuda_version_flags} ${cuda_math_flags} -I${CMAKE_CURRENT_SOURCE_DIR}/../util -I${CMAKE_CURRENT_SOURCE_DIR}/svm -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -DNVCC DEPENDS ${cuda_sources}) delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib) diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript index 3a46d10dee1..353ec1ce9d8 100644 --- a/intern/cycles/kernel/SConscript +++ b/intern/cycles/kernel/SConscript @@ -25,6 +25,8 @@ # # ***** END GPL LICENSE BLOCK ***** +import re +import subprocess import sys import os import Blender as B @@ -60,10 +62,19 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: svm_dir = os.path.join(source_dir, "../svm") closure_dir = os.path.join(source_dir, "../closure") + # get CUDA version + nvcc_pipe = subprocess.Popen([nvcc, "--version"],stdout=subprocess.PIPE,stderr=subprocess.PIPE) + output, erroroutput = nvcc_pipe.communicate() + cuda_major_minor = re.findall(r'release (\d+).(\d+)', output)[0] + cuda_version = int(cuda_major_minor[0])*10 + int(cuda_major_minor[1]) + + if cuda_version != 50: + print("CUDA version %d.%d detected, build may succeed but only CUDA 5.0 is officially supported." % (cuda_version/10, cuda_version%10)) + # nvcc flags nvcc_flags = "-m%s" % (bits) - nvcc_flags += " --cubin --ptxas-options=\"-v\" --maxrregcount=24" - nvcc_flags += " --opencc-options -OPT:Olimit=0" + nvcc_flags += " --cubin --ptxas-options=\"-v\"" + nvcc_flags += " -D__KERNEL_CUDA_VERSION__=%d" % (cuda_version) nvcc_flags += " -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -DNVCC" nvcc_flags += " -I \"%s\" -I \"%s\" -I \"%s\"" % (util_dir, svm_dir, closure_dir) @@ -75,7 +86,31 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: for arch in cuda_archs: cubin_file = os.path.join(build_dir, "kernel_%s.cubin" % arch) - command = "\"%s\" -arch=%s %s \"%s\" -o \"%s\"" % (nvcc, arch, nvcc_flags, kernel_file, cubin_file) + # build flags depending on CUDA version and arch + if cuda_version < 50: + # CUDA 4.x + if arch.startswith("sm_1"): + # sm_1x + cuda_arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0" + elif arch.startswith("sm_2"): + # sm_2x + cuda_arch_flags = "--maxrregcount=24" + else: + # sm_3x + cuda_arch_flags = "--maxrregcount=32" + else: + # CUDA 5.x + if arch.startswith("sm_1"): + # sm_1x + cuda_arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0 --use_fast_math" + elif arch.startswith("sm_2"): + # sm_2x + cuda_arch_flags = "--maxrregcount=32 --use_fast_math" + else: + # sm_3x + cuda_arch_flags = "--maxrregcount=32 --use_fast_math" + + command = "\"%s\" -arch=%s %s %s \"%s\" -o \"%s\"" % (nvcc, arch, nvcc_flags, cuda_arch_flags, kernel_file, cubin_file) kernel.Command(cubin_file, 'kernel.cu', command) kernel.Depends(cubin_file, dependencies) diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index ae9677ed5cb..9f6d79e13fb 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -112,80 +112,8 @@ __device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, cons } #endif -/* intersect two bounding boxes */ -#ifdef __HAIR__ -__device_inline void bvh_node_intersect(KernelGlobals *kg, - bool *traverseChild0, bool *traverseChild1, - bool *closestChild1, int *nodeAddr0, int *nodeAddr1, - float3 P, float3 idir, float t, uint visibility, int nodeAddr, float difl, float extmax) -{ -#else -__device_inline void bvh_node_intersect(KernelGlobals *kg, - bool *traverseChild0, bool *traverseChild1, - bool *closestChild1, int *nodeAddr0, int *nodeAddr1, - float3 P, float3 idir, float t, uint visibility, int nodeAddr) -{ -#endif - - /* fetch node data */ - float4 n0xy = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0); - float4 n1xy = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1); - float4 nz = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2); - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3); - - /* intersect ray against child nodes */ - float3 ood = P * idir; - NO_EXTENDED_PRECISION float c0lox = n0xy.x * idir.x - ood.x; - NO_EXTENDED_PRECISION float c0hix = n0xy.y * idir.x - ood.x; - NO_EXTENDED_PRECISION float c0loy = n0xy.z * idir.y - ood.y; - NO_EXTENDED_PRECISION float c0hiy = n0xy.w * idir.y - ood.y; - NO_EXTENDED_PRECISION float c0loz = nz.x * idir.z - ood.z; - NO_EXTENDED_PRECISION float c0hiz = nz.y * idir.z - ood.z; - NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f); - NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t); - - NO_EXTENDED_PRECISION float c1loz = nz.z * idir.z - ood.z; - NO_EXTENDED_PRECISION float c1hiz = nz.w * idir.z - ood.z; - NO_EXTENDED_PRECISION float c1lox = n1xy.x * idir.x - ood.x; - NO_EXTENDED_PRECISION float c1hix = n1xy.y * idir.x - ood.x; - NO_EXTENDED_PRECISION float c1loy = n1xy.z * idir.y - ood.y; - NO_EXTENDED_PRECISION float c1hiy = n1xy.w * idir.y - ood.y; - NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f); - NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t); - -#ifdef __HAIR__ - if(difl != 0.0f) { - float hdiff = 1.0f + difl; - float ldiff = 1.0f - difl; - if(__float_as_int(cnodes.z) & PATH_RAY_CURVE) { - c0min = max(ldiff * c0min, c0min - extmax); - c0max = min(hdiff * c0max, c0max + extmax); - } - if(__float_as_int(cnodes.w) & PATH_RAY_CURVE) { - c1min = max(ldiff * c1min, c1min - extmax); - c1max = min(hdiff * c1max, c1max + extmax); - } - } -#endif - - /* decide which nodes to traverse next */ -#ifdef __VISIBILITY_FLAG__ - /* this visibility test gives a 5% performance hit, how to solve? */ - *traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility); - *traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility); -#else - *traverseChild0 = (c0max >= c0min); - *traverseChild1 = (c1max >= c1min); -#endif - - *nodeAddr0 = __float_as_int(cnodes.x); - *nodeAddr1 = __float_as_int(cnodes.y); - - *closestChild1 = (c1min < c0min); -} - /* Sven Woop's algorithm */ -__device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *isect, +__device_inline bool bvh_triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, uint visibility, int object, int triAddr) { /* compute and check intersection t-value */ @@ -223,10 +151,13 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise isect->u = u; isect->v = v; isect->t = t; + return true; } } } } + + return false; } #ifdef __HAIR__ @@ -280,7 +211,7 @@ __device_inline void curvebounds(float *lower, float *upper, float *extremta, fl } } -__device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect, +__device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment, uint *lcg_state, float difl, float extmax) { float epsilon = 0.0f; @@ -346,7 +277,7 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio float zextrem[4]; curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z); if(lower - r_curr > isect->t || upper + r_curr < epsilon) - return; + return false; /*minimum width extension*/ float mw_extension = min(difl * fabsf(upper), extmax); @@ -355,17 +286,18 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio float xextrem[4]; curvebounds(&lower, &upper, &xextrem[0], &xextrem[1], &xextrem[2], &xextrem[3], curve_coef[0].x, curve_coef[1].x, curve_coef[2].x, curve_coef[3].x); if(lower > r_ext || upper < -r_ext) - return; + return false; float yextrem[4]; curvebounds(&lower, &upper, &yextrem[0], &yextrem[1], &yextrem[2], &yextrem[3], curve_coef[0].y, curve_coef[1].y, curve_coef[2].y, curve_coef[3].y); if(lower > r_ext || upper < -r_ext) - return; + return false; /*setup recurrent loop*/ int level = 1 << depth; int tree = 0; float resol = 1.0f / (float)level; + bool hit = false; /*begin loop*/ while(!(tree >> (depth))) { @@ -557,7 +489,7 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio /*stochastic fade from minimum width*/ if(lcg_state && coverage != 1.0f) { if(lcg_step(lcg_state) > coverage) - return; + return hit; } #ifdef __VISIBILITY_FLAG__ @@ -574,6 +506,7 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio isect->v = 0.0f; /*isect->v = 1.0f - coverage; */ isect->t = t; + hit = true; } tree++; @@ -584,9 +517,11 @@ __device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersectio level = level >> 1; } } + + return hit; } -__device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, +__device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment, uint *lcg_state, float difl, float extmax) { /* curve Intersection check */ @@ -630,7 +565,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, sphere_b = dot(dir,sphere_dif); float sdisc = sphere_b * sphere_b - len_squared(sphere_dif) + sp_r * sp_r; if(sdisc < 0.0f) - return; + return false; /* obtain parameters and test midpoint distance for suitable modes*/ float3 tg = (p2 - p1) / l; @@ -645,9 +580,9 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, float zcentre = difz + (dirz * tcentre); if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE)) - return; + return false; if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION)) - return; + return false; /* test minimum separation*/ float3 cprod = cross(tg, dir); @@ -662,7 +597,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, distscaled = (distscaled*distscaled)/cprodsq; if(distscaled > mr*mr) - return; + return false; /* calculate true intersection*/ float3 tdif = P - p1 + tcentre * dir; @@ -672,7 +607,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, float td = tb*tb - 4*a*tc; if (td < 0.0f) - return; + return false; float rootd = 0.0f; float correction = 0.0f; @@ -706,7 +641,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, adjradius = adjradius / (r1 + z * gd); if(lcg_state && adjradius != 1.0f) { if(lcg_step(lcg_state) > adjradius) - return; + return false; } /* --- */ @@ -719,7 +654,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio)); float c2 = dot(dif,dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio; if(a2*c2 < 0.0f) - return; + return false; } } @@ -740,9 +675,13 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, if(backface) isect->u = -isect->u; + + return true; } } } + + return false; } #endif @@ -751,7 +690,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, * only want to intersect with primitives in the same object, and if case of * multiple hits we pick a single random primitive as the intersection point. */ -__device_inline void bvh_triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect, +__device_inline bool bvh_triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, int object, int triAddr, float tmax, int *num_hits, float subsurface_random) { /* compute and check intersection t-value */ @@ -786,10 +725,13 @@ __device_inline void bvh_triangle_intersect_subsurface(KernelGlobals *kg, Inters isect->u = u; isect->v = v; isect->t = t; + return true; } } } } + + return false; } #endif diff --git a/intern/cycles/kernel/kernel_bvh_traversal.h b/intern/cycles/kernel/kernel_bvh_traversal.h index 2d75af32abd..8d423b7e7ce 100644 --- a/intern/cycles/kernel/kernel_bvh_traversal.h +++ b/intern/cycles/kernel/kernel_bvh_traversal.h @@ -1,6 +1,8 @@ /* - * Adapted from code Copyright 2009-2010 NVIDIA Corporation - * Modifications Copyright 2011, Blender Foundation. + * Adapted from code Copyright 2009-2010 NVIDIA Corporation, + * and code copyright 2009-2012 Intel Corporation + * + * Modifications 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. @@ -41,6 +43,14 @@ __device bool BVH_FUNCTION_NAME #endif ) { + /* todo: + * - test if pushing distance on the stack helps (for non shadow rays) + * - separate version for shadow rays + * - likely and unlikely for if() statements + * - SSE for hair + * - test restrict attribute for pointers + */ + /* traversal stack in CUDA thread-local memory */ int traversalStack[BVH_STACK_SIZE]; traversalStack[0] = ENTRYPOINT_SENTINEL; @@ -70,6 +80,28 @@ __device bool BVH_FUNCTION_NAME isect->u = 0.0f; isect->v = 0.0f; +#if defined(__KERNEL_SSE2__) && !FEATURE(BVH_HAIR_MINIMUM_WIDTH) + const shuffle_swap_t shuf_identity = shuffle_swap_identity(); + const shuffle_swap_t shuf_swap = shuffle_swap_swap(); + + const __m128i pn = _mm_set_epi32(0x80000000, 0x80000000, 0x00000000, 0x00000000); + __m128 Psplat[3], idirsplat[3]; + + Psplat[0] = _mm_set_ps1(P.x); + Psplat[1] = _mm_set_ps1(P.y); + Psplat[2] = _mm_set_ps1(P.z); + + idirsplat[0] = _mm_xor_ps(_mm_set_ps1(idir.x), _mm_castsi128_ps(pn)); + idirsplat[1] = _mm_xor_ps(_mm_set_ps1(idir.y), _mm_castsi128_ps(pn)); + idirsplat[2] = _mm_xor_ps(_mm_set_ps1(idir.z), _mm_castsi128_ps(pn)); + + __m128 tsplat = _mm_set_ps(-isect->t, -isect->t, 0.0f, 0.0f); + + shuffle_swap_t shufflex = (idir.x >= 0)? shuf_identity: shuf_swap; + shuffle_swap_t shuffley = (idir.y >= 0)? shuf_identity: shuf_swap; + shuffle_swap_t shufflez = (idir.z >= 0)? shuf_identity: shuf_swap; +#endif + /* traversal loop */ do { do @@ -77,46 +109,121 @@ __device bool BVH_FUNCTION_NAME /* traverse internal nodes */ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { - bool traverseChild0, traverseChild1, closestChild1; + bool traverseChild0, traverseChild1; int nodeAddrChild1; +#if !defined(__KERNEL_SSE2__) || FEATURE(BVH_HAIR_MINIMUM_WIDTH) + /* Intersect two child bounding boxes, non-SSE version */ + float t = isect->t; + + /* fetch node data */ + float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0); + float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1); + float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3); + + /* intersect ray against child nodes */ + NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f); + NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t); + + NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f); + NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t); + #if FEATURE(BVH_HAIR_MINIMUM_WIDTH) && !FEATURE(BVH_SUBSURFACE) - bvh_node_intersect(kg, &traverseChild0, &traverseChild1, - &closestChild1, &nodeAddr, &nodeAddrChild1, - P, idir, isect->t, visibility, nodeAddr, difl, extmax); + if(difl != 0.0f) { + float hdiff = 1.0f + difl; + float ldiff = 1.0f - difl; + if(__float_as_int(cnodes.z) & PATH_RAY_CURVE) { + c0min = max(ldiff * c0min, c0min - extmax); + c0max = min(hdiff * c0max, c0max + extmax); + } + if(__float_as_int(cnodes.w) & PATH_RAY_CURVE) { + c1min = max(ldiff * c1min, c1min - extmax); + c1max = min(hdiff * c1max, c1max + extmax); + } + } +#endif + + /* decide which nodes to traverse next */ +#ifdef __VISIBILITY_FLAG__ + /* this visibility test gives a 5% performance hit, how to solve? */ + traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility); + traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility); #else - bvh_node_intersect(kg, &traverseChild0, &traverseChild1, - &closestChild1, &nodeAddr, &nodeAddrChild1, -#ifdef __HAIR__ - P, idir, isect->t, visibility, nodeAddr, 0.0f, 0.0f); + traverseChild0 = (c0max >= c0min); + traverseChild1 = (c1max >= c1min); +#endif + +#else // __KERNEL_SSE2__ + /* Intersect two child bounding boxes, SSE3 version adapted from Embree */ + + /* fetch node data */ + __m128 *bvh_nodes = (__m128*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE; + float4 cnodes = ((float4*)bvh_nodes)[3]; + + /* intersect ray against child nodes */ + const __m128 tminmaxx = _mm_mul_ps(_mm_sub_ps(shuffle_swap(bvh_nodes[0], shufflex), Psplat[0]), idirsplat[0]); + const __m128 tminmaxy = _mm_mul_ps(_mm_sub_ps(shuffle_swap(bvh_nodes[1], shuffley), Psplat[1]), idirsplat[1]); + const __m128 tminmaxz = _mm_mul_ps(_mm_sub_ps(shuffle_swap(bvh_nodes[2], shufflez), Psplat[2]), idirsplat[2]); + + const __m128 tminmax = _mm_xor_ps(_mm_max_ps(_mm_max_ps(tminmaxx, tminmaxy), _mm_max_ps(tminmaxz, tsplat)), _mm_castsi128_ps(pn)); + const __m128 lrhit = _mm_cmple_ps(tminmax, shuffle_swap(tminmax, shuf_swap)); + + /* decide which nodes to traverse next */ +#ifdef __VISIBILITY_FLAG__ + /* this visibility test gives a 5% performance hit, how to solve? */ + traverseChild0 = (_mm_movemask_ps(lrhit) & 1) && (__float_as_uint(cnodes.z) & visibility); + traverseChild1 = (_mm_movemask_ps(lrhit) & 2) && (__float_as_uint(cnodes.w) & visibility); #else - P, idir, isect->t, visibility, nodeAddr); + traverseChild0 = (_mm_movemask_ps(lrhit) & 1); + traverseChild1 = (_mm_movemask_ps(lrhit) & 2); #endif +#endif // __KERNEL_SSE2__ + + nodeAddr = __float_as_int(cnodes.x); + nodeAddrChild1 = __float_as_int(cnodes.y); + + if(traverseChild0 && traverseChild1) { + /* both children were intersected, push the farther one */ +#if !defined(__KERNEL_SSE2__) || FEATURE(BVH_HAIR_MINIMUM_WIDTH) + bool closestChild1 = (c1min < c0min); +#else + union { __m128 m128; float v[4]; } uminmax; + uminmax.m128 = tminmax; + bool closestChild1 = uminmax.v[1] < uminmax.v[0]; #endif - if(traverseChild0 != traverseChild1) { - /* one child was intersected */ - if(traverseChild1) { + if(closestChild1) { + int tmp = nodeAddr; nodeAddr = nodeAddrChild1; + nodeAddrChild1 = tmp; } + + ++stackPtr; + traversalStack[stackPtr] = nodeAddrChild1; } else { - if(!traverseChild0) { + /* one child was intersected */ + if(traverseChild1) { + nodeAddr = nodeAddrChild1; + } + else if(!traverseChild0) { /* neither child was intersected */ nodeAddr = traversalStack[stackPtr]; --stackPtr; } - else { - /* both children were intersected, push the farther one */ - if(closestChild1) { - int tmp = nodeAddr; - nodeAddr = nodeAddrChild1; - nodeAddrChild1 = tmp; - } - - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild1; - } } } @@ -136,6 +243,8 @@ __device bool BVH_FUNCTION_NAME /* primitive intersection */ while(primAddr < primAddr2) { + bool hit; + #if FEATURE(BVH_SUBSURFACE) /* only primitives from the same object */ uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object; @@ -148,15 +257,16 @@ __device bool BVH_FUNCTION_NAME uint segment = kernel_tex_fetch(__prim_segment, primAddr); #if !FEATURE(BVH_SUBSURFACE) if(segment != ~0) { + if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_INTERPOLATE) #if FEATURE(BVH_HAIR_MINIMUM_WIDTH) - bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment, lcg_state, difl, extmax); + hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment, lcg_state, difl, extmax); else - bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment, lcg_state, difl, extmax); + hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment, lcg_state, difl, extmax); #else - bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); else - bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); #endif } else @@ -166,17 +276,30 @@ __device bool BVH_FUNCTION_NAME #if FEATURE(BVH_HAIR) if(segment == ~0) #endif - bvh_triangle_intersect_subsurface(kg, isect, P, idir, object, primAddr, tmax, &num_hits, subsurface_random); + { + hit = bvh_triangle_intersect_subsurface(kg, isect, P, idir, object, primAddr, tmax, &num_hits, subsurface_random); + (void)hit; + } } #else - bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); + hit = bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); /* shadow ray early termination */ - if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0) +#if defined(__KERNEL_SSE2__) && !FEATURE(BVH_HAIR_MINIMUM_WIDTH) + if(hit) { + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + + tsplat = _mm_set_ps(-isect->t, -isect->t, 0.0f, 0.0f); + } +#else + if(hit && visibility == PATH_RAY_SHADOW_OPAQUE) return true; #endif +#endif + primAddr++; } } @@ -196,6 +319,22 @@ __device bool BVH_FUNCTION_NAME bvh_instance_push(kg, object, ray, &P, &idir, &isect->t, tmax); #endif +#if defined(__KERNEL_SSE2__) && !FEATURE(BVH_HAIR_MINIMUM_WIDTH) + Psplat[0] = _mm_set_ps1(P.x); + Psplat[1] = _mm_set_ps1(P.y); + Psplat[2] = _mm_set_ps1(P.z); + + idirsplat[0] = _mm_xor_ps(_mm_set_ps1(idir.x), _mm_castsi128_ps(pn)); + idirsplat[1] = _mm_xor_ps(_mm_set_ps1(idir.y), _mm_castsi128_ps(pn)); + idirsplat[2] = _mm_xor_ps(_mm_set_ps1(idir.z), _mm_castsi128_ps(pn)); + + tsplat = _mm_set_ps(-isect->t, -isect->t, 0.0f, 0.0f); + + shufflex = (idir.x >= 0)? shuf_identity: shuf_swap; + shuffley = (idir.y >= 0)? shuf_identity: shuf_swap; + shufflez = (idir.z >= 0)? shuf_identity: shuf_swap; +#endif + ++stackPtr; traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; @@ -223,6 +362,23 @@ __device bool BVH_FUNCTION_NAME #else bvh_instance_pop(kg, object, ray, &P, &idir, &isect->t, tmax); #endif + +#if defined(__KERNEL_SSE2__) && !FEATURE(BVH_HAIR_MINIMUM_WIDTH) + Psplat[0] = _mm_set_ps1(P.x); + Psplat[1] = _mm_set_ps1(P.y); + Psplat[2] = _mm_set_ps1(P.z); + + idirsplat[0] = _mm_xor_ps(_mm_set_ps1(idir.x), _mm_castsi128_ps(pn)); + idirsplat[1] = _mm_xor_ps(_mm_set_ps1(idir.y), _mm_castsi128_ps(pn)); + idirsplat[2] = _mm_xor_ps(_mm_set_ps1(idir.z), _mm_castsi128_ps(pn)); + + tsplat = _mm_set_ps(-isect->t, -isect->t, 0.0f, 0.0f); + + shufflex = (idir.x >= 0)? shuf_identity: shuf_swap; + shuffley = (idir.y >= 0)? shuf_identity: shuf_swap; + shufflez = (idir.z >= 0)? shuf_identity: shuf_swap; +#endif + object = ~0; nodeAddr = traversalStack[stackPtr]; --stackPtr; diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index c430a40d814..77dc59d2691 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -168,9 +168,9 @@ __device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderDa float3 L = shader_emissive_eval(kg, sd); #ifdef __HAIR__ - if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->segment == ~0)) { + if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->segment == ~0)) { #else - if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) { + if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS)) { #endif /* multiple importance sampling, get triangle light pdf, * and compute weight with respect to BSDF pdf */ diff --git a/intern/cycles/kernel/kernel_jitter.h b/intern/cycles/kernel/kernel_jitter.h index 15d2151228f..3e1a18ab469 100644 --- a/intern/cycles/kernel/kernel_jitter.h +++ b/intern/cycles/kernel/kernel_jitter.h @@ -37,7 +37,7 @@ __device_inline int cmj_fast_mod_pow2(int a, int b) /* a must be > 0 and b must be > 1 */ __device_inline int cmj_fast_div_pow2(int a, int b) { -#ifdef __KERNEL_SSE2__ +#if defined(__KERNEL_SSE2__) && !defined(_MSC_VER) return a >> __builtin_ctz(b); #else return a/b; @@ -46,7 +46,7 @@ __device_inline int cmj_fast_div_pow2(int a, int b) __device_inline uint cmj_w_mask(uint w) { -#ifdef __KERNEL_SSE2__ +#if defined(__KERNEL_SSE2__) && !defined(_MSC_VER) return ((1 << (32 - __builtin_clz(w))) - 1); #else w |= w >> 1; @@ -137,7 +137,7 @@ __device_inline float cmj_randfloat(uint i, uint p) } #ifdef __CMJ__ -__device_noinline float cmj_sample_1D(int s, int N, int p) +__device float cmj_sample_1D(int s, int N, int p) { uint x = cmj_permute(s, N, p * 0x68bc21eb); float jx = cmj_randfloat(s, p * 0x967a889b); @@ -146,7 +146,7 @@ __device_noinline float cmj_sample_1D(int s, int N, int p) return (x + jx)*invN; } -__device_noinline void cmj_sample_2D(int s, int N, int p, float *fx, float *fy) +__device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy) { int m = float_to_int(sqrtf(N)); int n = (N + m - 1)/m; diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index f0ac8e7bbc9..ca4d878daa0 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -38,7 +38,12 @@ CCL_NAMESPACE_BEGIN /* ShaderData setup from incoming ray */ #ifdef __OBJECT_MOTION__ -__device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time) +#if defined(__KERNEL_CUDA_VERSION__) && __KERNEL_CUDA_VERSION__ <= 42 +__device_noinline +#else +__device +#endif +void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time) { /* note that this is a separate non-inlined function to work around crash * on CUDA sm 2.0, otherwise kernel execution crashes (compiler bug?) */ @@ -53,7 +58,12 @@ __device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderD } #endif -__device_noinline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, +#if defined(__KERNEL_CUDA_VERSION__) && __KERNEL_CUDA_VERSION__ <= 42 +__device_noinline +#else +__device +#endif +void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { #ifdef __INSTANCING__ @@ -260,7 +270,12 @@ __device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderData /* ShaderData setup from position sampled on mesh */ -__device_noinline void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, +#if defined(__KERNEL_CUDA_VERSION__) && __KERNEL_CUDA_VERSION__ <= 42 +__device_noinline +#else +__device +#endif +void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, const float3 P, const float3 Ng, const float3 I, int shader, int object, int prim, float u, float v, float t, float time, int segment) { @@ -891,7 +906,7 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect) #endif int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2); - return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0; + return (flag & SD_HAS_TRANSPARENT_SHADOW) != 0; } #endif diff --git a/intern/cycles/kernel/kernel_sse3.cpp b/intern/cycles/kernel/kernel_sse3.cpp index 6982570c59b..ff6bb412d5b 100644 --- a/intern/cycles/kernel/kernel_sse3.cpp +++ b/intern/cycles/kernel/kernel_sse3.cpp @@ -16,12 +16,15 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* Optimized CPU kernel entry points. This file is compiled with SSE3 +/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3 * optimization flags and nearly all functions inlined, while kernel.cpp * is compiled without for other CPU's. */ #ifdef WITH_OPTIMIZED_KERNEL +#define __KERNEL_SSE3__ +#define __KERNEL_SSSE3__ + #include "kernel.h" #include "kernel_compat_cpu.h" #include "kernel_math.h" diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 70a3e82896b..c6b1e29ba26 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -499,8 +499,8 @@ enum ShaderDataFlag { SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|SD_BSSRDF|SD_HOLDOUT|SD_VOLUME|SD_AO), /* shader flags */ - SD_SAMPLE_AS_LIGHT = 512, /* direct light sample */ - SD_HAS_SURFACE_TRANSPARENT = 1024, /* has surface transparency */ + SD_USE_MIS = 512, /* direct light sample */ + SD_HAS_TRANSPARENT_SHADOW = 1024, /* has transparent shadow */ SD_HAS_VOLUME = 2048, /* has volume shader */ SD_HOMOGENEOUS_VOLUME = 4096, /* has homogeneous volume */ diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 1d48ae8f87d..2f92b957929 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -164,7 +164,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; - if(shader->sample_as_light && shader->has_surface_emission) { + if(shader->use_mis && shader->has_surface_emission) { have_emission = true; break; } @@ -175,7 +175,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen for(size_t i = 0; i < mesh->triangles.size(); i++) { Shader *shader = scene->shaders[mesh->shader[i]]; - if(shader->sample_as_light && shader->has_surface_emission) + if(shader->use_mis && shader->has_surface_emission) num_triangles++; } @@ -184,7 +184,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen foreach(Mesh::Curve& curve, mesh->curves) { Shader *shader = scene->shaders[curve.shader]; - if(shader->sample_as_light && shader->has_surface_emission) + if(shader->use_mis && shader->has_surface_emission) num_curve_segments += curve.num_segments(); #endif } @@ -215,7 +215,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; - if(shader->sample_as_light && shader->has_surface_emission) { + if(shader->use_mis && shader->has_surface_emission) { have_emission = true; break; } @@ -247,7 +247,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen for(size_t i = 0; i < mesh->triangles.size(); i++) { Shader *shader = scene->shaders[mesh->shader[i]]; - if(shader->sample_as_light && shader->has_surface_emission) { + if(shader->use_mis && shader->has_surface_emission) { distribution[offset].x = totarea; distribution[offset].y = __int_as_float(i + mesh->tri_offset); distribution[offset].z = __int_as_float(shader_id); @@ -277,7 +277,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Shader *shader = scene->shaders[curve.shader]; int first_key = curve.first_key; - if(shader->sample_as_light && shader->has_surface_emission) { + if(shader->use_mis && shader->has_surface_emission) { for(int j = 0; j < curve.num_segments(); j++) { distribution[offset].x = totarea; distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 1a2780995e3..7931a51b99d 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -127,7 +127,7 @@ void Object::tag_update(Scene *scene) foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; - if(shader->sample_as_light && shader->has_surface_emission) + if(shader->use_mis && shader->has_surface_emission) scene->light_manager->need_update = true; } } diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 8efc6b553e0..52e4c697ba8 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -100,7 +100,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene compiler.background = (shader == scene->shaders[scene->default_background]); compiler.compile(og, shader); - if(shader->sample_as_light && shader->has_surface_emission) + if(shader->use_mis && shader->has_surface_emission) scene->light_manager->need_update = true; } diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 46c174b773d..76b5b2baaa6 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -43,7 +43,8 @@ Shader::Shader() graph = NULL; graph_bump = NULL; - sample_as_light = true; + use_mis = true; + use_transparent_shadow = true; homogeneous_volume = false; has_surface = false; @@ -90,7 +91,7 @@ void Shader::tag_update(Scene *scene) /* if the shader previously was emissive, update light distribution, * if the new shader is emissive, a light manager update tag will be * done in the shader manager device update. */ - if(sample_as_light && has_surface_emission) + if(use_mis && has_surface_emission) scene->light_manager->need_update = true; /* get requested attributes. this could be optimized by pruning unused @@ -224,10 +225,10 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc foreach(Shader *shader, scene->shaders) { uint flag = 0; - if(shader->sample_as_light) - flag |= SD_SAMPLE_AS_LIGHT; - if(shader->has_surface_transparent) - flag |= SD_HAS_SURFACE_TRANSPARENT; + if(shader->use_mis) + flag |= SD_USE_MIS; + if(shader->has_surface_transparent && shader->use_transparent_shadow) + flag |= SD_HAS_TRANSPARENT_SHADOW; if(shader->has_volume) flag |= SD_HAS_VOLUME; if(shader->homogeneous_volume) diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 0b7b4b3ab42..d7eac603fa6 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -62,7 +62,8 @@ public: ShaderGraph *graph_bump; /* sampling */ - bool sample_as_light; + bool use_mis; + bool use_transparent_shadow; bool homogeneous_volume; /* synchronization */ diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 8b662cbf7c1..30105af2910 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -74,7 +74,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene assert(shader->graph); - if(shader->sample_as_light && shader->has_surface_emission) + if(shader->use_mis && shader->has_surface_emission) scene->light_manager->need_update = true; SVMCompiler compiler(scene->shader_manager, scene->image_manager, diff --git a/intern/cycles/util/util_cuda.cpp b/intern/cycles/util/util_cuda.cpp index 6c9ee7c548f..42ffb04a793 100644 --- a/intern/cycles/util/util_cuda.cpp +++ b/intern/cycles/util/util_cuda.cpp @@ -16,6 +16,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <iostream> + #include <stdlib.h> #include <stdio.h> @@ -25,6 +27,11 @@ #include "util_path.h" #include "util_string.h" +#ifdef _WIN32 +#define popen _popen +#define pclose _pclose +#endif + /* function defininitions */ tcuInit *cuInit; @@ -399,7 +406,15 @@ string cuCompilerPath() const char *defaultpaths[] = {"C:/CUDA/bin", NULL}; const char *executable = "nvcc.exe"; #else - const char *defaultpaths[] = {"/Developer/NVIDIA/CUDA-4.2/bin", "/usr/local/cuda-4.2/bin", "/usr/local/cuda/bin", NULL}; + const char *defaultpaths[] = { + "/Developer/NVIDIA/CUDA-5.0/bin", + "/usr/local/cuda-5.0/bin", + "/usr/local/cuda/bin", + "/Developer/NVIDIA/CUDA-4.2/bin", + "/usr/local/cuda-4.2/bin", + "/Developer/NVIDIA/CUDA-5.5/bin", + "/usr/local/cuda-5.5/bin", + NULL}; const char *executable = "nvcc"; #endif @@ -437,5 +452,46 @@ string cuCompilerPath() return ""; } +int cuCompilerVersion() +{ + string path = cuCompilerPath(); + if(path == "") + return 0; + + /* get --version output */ + FILE *pipe = popen((path + " --version").c_str(), "r"); + if(!pipe) { + fprintf(stderr, "CUDA: failed to run compiler to retrieve version"); + return 0; + } + + char buf[128]; + string output = ""; + + while(!feof(pipe)) + if(fgets(buf, 128, pipe) != NULL) + output += buf; + + pclose(pipe); + + /* parse version number */ + string marker = "Cuda compilation tools, release "; + size_t offset = output.find(marker); + if(offset == string::npos) { + fprintf(stderr, "CUDA: failed to find version number in:\n\n%s\n", output.c_str()); + return 0; + } + + string versionstr = output.substr(offset + marker.size(), string::npos); + int major, minor; + + if(sscanf(versionstr.c_str(), "%d.%d", &major, &minor) < 2) { + fprintf(stderr, "CUDA: failed to parse version number from:\n\n%s\n", output.c_str()); + return 0; + } + + return 10*major + minor; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_cuda.h b/intern/cycles/util/util_cuda.h index 55feb3f84cb..ba4df0de90a 100644 --- a/intern/cycles/util/util_cuda.h +++ b/intern/cycles/util/util_cuda.h @@ -32,6 +32,7 @@ CCL_NAMESPACE_BEGIN bool cuLibraryInit(); bool cuHavePrecompiledKernels(); string cuCompilerPath(); +int cuCompilerVersion(); CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 68668d88d44..05ed8a2d3f6 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -165,7 +165,7 @@ __device_inline float clamp(float a, float mn, float mx) __device_inline int float_to_int(float f) { -#ifdef __KERNEL_SSE2__ +#if defined(__KERNEL_SSE2__) && !defined(_MSC_VER) return _mm_cvtt_ss2si(_mm_load_ss(&f)); #else return (int)f; diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp index c3ecc303a34..7ba749f4287 100644 --- a/intern/cycles/util/util_system.cpp +++ b/intern/cycles/util/util_system.cpp @@ -194,7 +194,7 @@ bool system_cpu_support_sse2() bool system_cpu_support_sse3() { CPUCapabilities& caps = system_cpu_capabilities(); - return caps.sse && caps.sse2 && caps.sse3; + return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3; } #else diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index 472a707d8fd..4fd1e9d8807 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -69,16 +69,28 @@ #include <xmmintrin.h> /* SSE 1 */ #include <emmintrin.h> /* SSE 2 */ #include <pmmintrin.h> /* SSE 3 */ -#include <tmmintrin.h> /* SSE 3 */ +#include <tmmintrin.h> /* SSSE 3 */ #include <smmintrin.h> /* SSE 4 */ +#ifndef __KERNEL_SSE2__ #define __KERNEL_SSE2__ +#endif + +#ifndef __KERNEL_SSE3__ #define __KERNEL_SSE3__ +#endif + +#ifndef __KERNEL_SSSE3__ +#define __KERNEL_SSSE3__ +#endif + +#ifndef __KERNEL_SSE4__ #define __KERNEL_SSE4__ +#endif #else -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__KERNEL_SSSE3__) /* MinGW64 has conflicting declarations for these SSE headers in <windows.h>. * Since we can't avoid including <windows.h>, better only include that */ @@ -87,18 +99,26 @@ #else #include <xmmintrin.h> /* SSE 1 */ #include <emmintrin.h> /* SSE 2 */ + +#ifdef __KERNEL_SSE3__ +#include <pmmintrin.h> /* SSE 3 */ +#endif +#ifdef __KERNEL_SSSE3__ +#include <tmmintrin.h> /* SSSE 3 */ +#endif #endif +#ifndef __KERNEL_SSE2__ #define __KERNEL_SSE2__ +#endif #endif #endif +/* int8_t, uint16_t, and friends */ #ifndef _WIN32 - #include <stdint.h> - #endif #endif @@ -471,6 +491,67 @@ __device_inline int4 make_int4(const float3& f) #endif +#ifdef __KERNEL_SSE2__ + +/* SSE shuffle utility functions */ + +#ifdef __KERNEL_SSSE3__ + +/* faster version for SSSE3 */ +typedef __m128i shuffle_swap_t; + +__device_inline const shuffle_swap_t shuffle_swap_identity(void) +{ + return _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); +} + +__device_inline const shuffle_swap_t shuffle_swap_swap(void) +{ + return _mm_set_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8); +} + +__device_inline const __m128 shuffle_swap(const __m128& a, const shuffle_swap_t& shuf) +{ + return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf)); +} + +#else + +/* somewhat slower version for SSE3 */ +typedef int shuffle_swap_t; + +__device_inline const shuffle_swap_t shuffle_swap_identity(void) +{ + return 0; +} + +__device_inline const shuffle_swap_t shuffle_swap_swap(void) +{ + return 1; +} + +__device_inline const __m128 shuffle_swap(const __m128& a, shuffle_swap_t shuf) +{ + /* shuffle value must be a constant, so we need to branch */ + if(shuf) + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2)); + else + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 2, 1, 0)); +} + +#endif + +template<size_t i0, size_t i1, size_t i2, size_t i3> __device_inline const __m128 shuffle(const __m128& a, const __m128& b) +{ + return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0)); +} + +template<size_t i0, size_t i1, size_t i2, size_t i3> __device_inline const __m128 shuffle(const __m128& b) +{ + return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(i3, i2, i1, i0))); +} +#endif + CCL_NAMESPACE_END #endif /* __UTIL_TYPES_H__ */ diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 7e7612e56d8..a197c20fdab 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -239,7 +239,7 @@ def _addon_remove(module_name): addons.remove(addon) -def enable(module_name, default_set=True, persistent=False): +def enable(module_name, default_set=True, persistent=False, handle_error=None): """ Enables an addon by name. @@ -253,9 +253,10 @@ def enable(module_name, default_set=True, persistent=False): import sys from bpy_restrict_state import RestrictBlend - def handle_error(): - import traceback - traceback.print_exc() + if handle_error is None: + def handle_error(): + import traceback + traceback.print_exc() # reload if the mtime changes mod = sys.modules.get(module_name) @@ -322,7 +323,7 @@ def enable(module_name, default_set=True, persistent=False): return mod -def disable(module_name, default_set=True): +def disable(module_name, default_set=True, handle_error=None): """ Disables an addon by name. @@ -330,6 +331,12 @@ def disable(module_name, default_set=True): :type module_name: string """ import sys + + if handle_error is None: + def handle_error(): + import traceback + traceback.print_exc() + mod = sys.modules.get(module_name) # possible this addon is from a previous session and didn't load a @@ -344,8 +351,7 @@ def disable(module_name, default_set=True): except: print("Exception in module unregister(): %r" % getattr(mod, "__file__", module_name)) - import traceback - traceback.print_exc() + handle_error() else: print("addon_utils.disable: %s not %s." % (module_name, "disabled" if mod is None else "loaded")) diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index 4ca4c18cc7b..001f044f1c4 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -101,7 +101,7 @@ IMPORT_MIN_LEVEL = 0.0 # Languages in /branches we do not want to import in /trunk currently... IMPORT_LANGUAGES_SKIP = { - 'am_ET', 'bg_BG', 'fi_FI', 'el_GR', 'et_EE', 'ne_NP', 'nl_NL', 'pl_PL', 'ro_RO', 'uz_UZ', 'uz_UZ@cyrillic', + 'am_ET', 'bg_BG', 'fi_FI', 'el_GR', 'et_EE', 'ne_NP', 'pl_PL', 'ro_RO', 'uz_UZ', 'uz_UZ@cyrillic', } # Languages that need RTL pre-processing. diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index 99f311bad11..8c237840d96 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -58,6 +58,7 @@ class SpellChecker(): "arcsine", "arccosine", "arctangent", "autoclip", "autocomplete", + "autoexec", "autoname", "autosave", "autoscale", @@ -437,6 +438,7 @@ class SpellChecker(): "oren", "prewitt", "runge", + "sobol", "verlet", "worley", diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index 7412d34940f..7d8caf449ca 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -25,7 +25,7 @@ __all__ = ( "object_add_grid_scale", "object_add_grid_scale_apply_operator", "object_image_guess", - "world_to_camera", + "world_to_camera_view", ) @@ -268,12 +268,14 @@ def object_image_guess(obj, bm=None): return None -def world_to_camera(scene, obj, coord): +def world_to_camera_view(scene, obj, coord): """ - Returns the 2d camera space coords for a 3d point. + Returns the camera space coords for a 3d point. + (also known as: normalized device coordinates - NDC). Where (0, 0) is the bottom left and (1, 1) is the top right of the camera frame. values outside 0-1 are also supported. + A negative 'z' value means the point is behind the camera. Takes shift-x/y, lens angle and sensor size into account as well as perspective/ortho projections. @@ -284,7 +286,7 @@ def world_to_camera(scene, obj, coord): :type obj: :class:`bpy.types.Object` :arg coord: World space location. :type coord: :class:`mathutils.Vector` - :return: normalized 2d vector. + :return: a vector where X and Y map to the view plane and Z is the depth on the view axis. :rtype: :class:`mathutils.Vector` """ from mathutils import Vector diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index fd1f538efd3..fba7672e846 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1574,8 +1574,15 @@ class WM_OT_addon_enable(Operator): def execute(self, context): import addon_utils + + err_str = "" + def err_cb(): + import traceback + nonlocal err_str + err_str = traceback.format_exc() + print(err_str) - mod = addon_utils.enable(self.module) + mod = addon_utils.enable(self.module, handle_error=err_cb) if mod: info = addon_utils.module_bl_info(mod) @@ -1590,6 +1597,10 @@ class WM_OT_addon_enable(Operator): info_ver) return {'FINISHED'} else: + + if err_str: + self.report({'ERROR'}, err_str) + return {'CANCELLED'} @@ -1606,7 +1617,18 @@ class WM_OT_addon_disable(Operator): def execute(self, context): import addon_utils - addon_utils.disable(self.module) + err_str = "" + def err_cb(): + import traceback + nonlocal err_str + err_str = traceback.format_exc() + print(err_str) + + addon_utils.disable(self.module, handle_error=err_cb) + + if err_str: + self.report({'ERROR'}, err_str) + return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 868fa2a311c..594f724c6e3 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -68,6 +68,7 @@ _modules = [ "space_nla", "space_node", "space_outliner", + "space_properties", "space_sequencer", "space_text", "space_time", diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 65ab1246c19..b3335f32231 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -134,8 +134,8 @@ def brush_mask_texture_settings(layout, brush): layout.operator("brush.stencil_reset_transform").mask = True if brush.mask_texture: - layout.label(text="Mask Mapping:") col = layout.column() + col.label(text="Angle:") col.active = brush.brush_capabilities.has_texture_angle col.prop(mask_tex_slot, "angle", text="") diff --git a/release/scripts/startup/bl_ui/space_properties.py b/release/scripts/startup/bl_ui/space_properties.py new file mode 100644 index 00000000000..758713b5cc4 --- /dev/null +++ b/release/scripts/startup/bl_ui/space_properties.py @@ -0,0 +1,46 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> +import bpy +from bpy.types import Header + + +class PROPERTIES_HT_header(Header): + bl_space_type = 'PROPERTIES' + + def draw(self, context): + layout = self.layout + + view = context.space_data + + row = layout.row() + row.template_header(menus=False) + row.prop(view, "context", expand=True, icon_only=True) + + +def register(): + bpy.utils.register_module(__name__) + + +def unregister(): + bpy.utils.unregister_module(__name__) + + +if __name__ == "__main__": + register() diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index ef4e5468194..a497ecfb927 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -867,8 +867,21 @@ class USERPREF_PT_file(Panel): colsplit = col.split(percentage=0.95) sub = colsplit.column() - sub.label(text="Author:") - sub.prop(system, "author", text="") + + row = sub.split(percentage=0.3) + row.label(text="Auto Execution:") + row.prop(system, "use_scripts_auto_execute") + + if system.use_scripts_auto_execute: + box = sub.box() + row = box.row() + row.label(text="Excluded Paths:") + row.operator("wm.userpref_autoexec_path_add", text="", icon='ZOOMIN', emboss=False) + for i, path_cmp in enumerate(userpref.autoexec_paths): + row = box.row() + row.prop(path_cmp, "path", text="") + row.prop(path_cmp, "use_glob", text="", icon='FILTER') + row.operator("wm.userpref_autoexec_path_remove", text="", icon='X', emboss=False).index = i col = split.column() col.label(text="Save & Load:") @@ -896,10 +909,12 @@ class USERPREF_PT_file(Panel): col.separator() - col.label(text="Scripts:") - col.prop(system, "use_scripts_auto_execute") + col.label(text="Text Editor:") col.prop(system, "use_tabs_as_spaces") + col.label(text="Author:") + col.prop(system, "author", text="") + from bl_ui.space_userpref_keymap import InputKeyMapPanel diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b8cbd058063..e0449931fc9 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -966,26 +966,30 @@ class VIEW3D_MT_object_specials(Menu): if scene.render.use_shading_nodes: try: value = lamp.node_tree.nodes["Emission"].inputs["Strength"].default_value + except AttributeError: + value = None + if value is not None: props = layout.operator("wm.context_modal_mouse", text="Strength") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.node_tree.nodes[\"Emission\"].inputs[\"Strength\"].default_value" props.header_text = "Lamp Strength: %.3f" props.input_scale = 0.1 - except AttributeError: - pass + del value - if lamp.type == 'AREA' and lamp.shape == 'RECTANGLE': + if lamp.type == 'AREA': props = layout.operator("wm.context_modal_mouse", text="Size X") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.size" props.header_text = "Lamp Size X: %.3f" - props = layout.operator("wm.context_modal_mouse", text="Size Y") - props.data_path_iter = "selected_editable_objects" - props.data_path_item = "data.size" - props.header_text = "Lamp Size Y: %.3f" - elif lamp.type in {'SPOT', 'AREA', 'POINT', 'SUN'}: + if lamp.shape == 'RECTANGLE': + props = layout.operator("wm.context_modal_mouse", text="Size Y") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.size_y" + props.header_text = "Lamp Size Y: %.3f" + + elif lamp.type in {'SPOT', 'POINT', 'SUN'}: props = layout.operator("wm.context_modal_mouse", text="Size") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.shadow_soft_size" diff --git a/source/blender/blenkernel/BKE_autoexec.h b/source/blender/blenkernel/BKE_autoexec.h new file mode 100644 index 00000000000..7dc1e76ed5c --- /dev/null +++ b/source/blender/blenkernel/BKE_autoexec.h @@ -0,0 +1,31 @@ +/* + * ***** 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. + * + * Contributor(s): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_AUTOEXEC_H__ +#define __BKE_AUTOEXEC_H__ + +/** \file BKE_autoexec.h + * \ingroup bke + */ + +bool BKE_autoexec_match(const char *path); + +#endif /* __BKE_AUTOEXEC_H__ */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 6b9392a4169..3f3a5739d55 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -391,5 +391,30 @@ void modifier_mdef_compact_influences(struct ModifierData *md); void modifier_path_init(char *path, int path_maxlen, const char *name); const char *modifier_path_relbase(struct Object *ob); + +/* wrappers for modifier callbacks */ + +struct DerivedMesh *modwrap_applyModifier( + ModifierData *md, struct Object *ob, + struct DerivedMesh *dm, + ModifierApplyFlag flag); + +struct DerivedMesh *modwrap_applyModifierEM( + ModifierData *md, struct Object *ob, + struct BMEditMesh *em, + struct DerivedMesh *dm, + ModifierApplyFlag flag); + +void modwrap_deformVerts( + ModifierData *md, struct Object *ob, + struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts, + ModifierApplyFlag flag); + +void modwrap_deformVertsEM( + ModifierData *md, struct Object *ob, + struct BMEditMesh *em, struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts); + #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 3864fe3b350..7e1355b5421 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -63,6 +63,7 @@ set(SRC intern/anim.c intern/anim_sys.c intern/armature.c + intern/autoexec.c intern/blender.c intern/bmfont.c intern/boids.c @@ -163,6 +164,7 @@ set(SRC BKE_anim.h BKE_animsys.h BKE_armature.h + BKE_autoexec.h BKE_blender.h BKE_bmesh.h BKE_bmfont.h diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 6a21f33ac15..96ccc5be8e0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -845,69 +845,6 @@ DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) return dm; } -/***/ - -/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */ - -static DerivedMesh *modwrap_applyModifier( - ModifierData *md, Object *ob, - DerivedMesh *dm, - ModifierApplyFlag flag) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - return mti->applyModifier(md, ob, dm, flag); -} - -static DerivedMesh *modwrap_applyModifierEM( - ModifierData *md, Object *ob, - BMEditMesh *em, - DerivedMesh *dm, - ModifierApplyFlag flag) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - return mti->applyModifierEM(md, ob, em, dm, flag); -} - -static void modwrap_deformVerts( - ModifierData *md, Object *ob, - DerivedMesh *dm, - float (*vertexCos)[3], int numVerts, - ModifierApplyFlag flag) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag); -} - -static void modwrap_deformVertsEM( - ModifierData *md, Object *ob, - BMEditMesh *em, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts); -} -/* end modifier callback wrappers */ - DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md, int build_shapekey_layers) { @@ -2148,7 +2085,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D if (mti->applyModifierEM) ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE); else - ndm = mti->applyModifier(md, ob, dm, MOD_APPLY_USECACHE); + ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE); if (ndm) { if (dm && dm != ndm) diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c new file mode 100644 index 00000000000..c27343bf80a --- /dev/null +++ b/source/blender/blenkernel/intern/autoexec.c @@ -0,0 +1,70 @@ +/* + * ***** 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. + * + * Contributor(s): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/armature.c + * \ingroup bke + * + * Currently just checks if a blend file can be trusted to autoexec, + * may add signing here later. + */ + +#include <stdlib.h> +#include <string.h> + +#include "DNA_userdef_types.h" + +#include "BLI_utildefines.h" +#include "BLI_fnmatch.h" +#include "BLI_string.h" +#include "BLI_path_util.h" + +#include "BKE_autoexec.h" /* own include */ + +/** + * \param path The path to check against. + * \return Success + */ +bool BKE_autoexec_match(const char *path) +{ + bPathCompare *path_cmp; + +#ifdef WIN32 + const int fnmatch_flags = FNM_CASEFOLD; +#else + const int fnmatch_flags = 0; +#endif + + BLI_assert((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0); + + for (path_cmp = U.autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) { + if ((path_cmp->flag & USER_PATHCMP_GLOB)) { + if (fnmatch(path_cmp->path, path, fnmatch_flags) == 0) { + return true; + } + } + else if (BLI_path_ncmp(path_cmp->path, path, strlen(path_cmp->path)) == 0) { + return true; + } + } + + return false; +} diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 87a8def52bf..1e7aba6d25b 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -416,6 +416,8 @@ void BKE_userdef_free(void) MEM_freeN(addon); } + BLI_freelistN(&U.autoexec_paths); + BLI_freelistN(&U.uistyles); BLI_freelistN(&U.uifonts); BLI_freelistN(&U.themes); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index f3de4001dea..e1ecf00104a 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -976,7 +976,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba dm = tdm; CDDM_apply_vert_coords(dm, vertCos); - CDDM_calc_normals_mapping(dm); } } else { @@ -989,8 +988,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba } dm = CDDM_from_curve_displist(ob, dispbase); - - CDDM_calc_normals_mapping(dm); } if (vertCos) { @@ -1001,7 +998,8 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba if (useCache) appf |= MOD_APPLY_USECACHE; - ndm = mti->applyModifier(md, ob, dm, appf); + + ndm = modwrap_applyModifier(md, ob, dm, appf); if (ndm) { /* Modifier returned a new derived mesh */ @@ -1031,8 +1029,19 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba } if (derivedFinal) { - if (dm) - DM_ensure_tessface(dm); /* needed for drawing */ + if (dm) { + /* see: mesh_calc_modifiers */ + if (dm->getNumTessFaces(dm) == 0) { + dm->recalcTessellation(dm); + } + /* Even if tessellation is not needed, some modifiers might have modified CD layers + * (like mloopcol or mloopuv), hence we have to update those. */ + else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) { + DM_update_tessface_data(dm); + } + + CDDM_calc_normals_mapping_ex(dm, (dm->dirty & DM_DIRTY_NORMALS) ? false : true); + } (*derivedFinal) = dm; } @@ -1169,7 +1178,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina if (!orcodm) orcodm = create_orco_dm(scene, ob); - ndm = mti->applyModifier(md, ob, orcodm, app_flag); + ndm = modwrap_applyModifier(md, ob, orcodm, app_flag); if (ndm) { /* if the modifier returned a new dm, release the old one */ diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index 979a38f0346..160972889fd 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -382,7 +382,7 @@ static void bmbvh_find_vert_closest_cb(void *userdata, int index, const float *U bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage); for (i = 0; i < 3; i++) { - dist = len_v3v3(hit->co, tri_cos[i]); + dist = len_squared_v3v3(hit->co, tri_cos[i]); if (dist < hit->dist && dist < maxdist) { copy_v3_v3(hit->co, tri_cos[i]); /* XXX, normal ignores cage */ @@ -398,17 +398,17 @@ BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *bmtree, const float co[3], const { BVHTreeNearest hit; struct VertSearchUserData bmcb_data; + const float maxdist_sq = maxdist * maxdist; if (bmtree->cos_cage) BLI_assert(!(bmtree->em->bm->elem_index_dirty & BM_VERT)); copy_v3_v3(hit.co, co); - /* XXX, why x5, scampbell */ - hit.dist = maxdist * 5; + hit.dist = maxdist_sq; hit.index = -1; bmcb_data.looptris = (const BMLoop *(*)[3])bmtree->em->looptris; bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage; - bmcb_data.maxdist = maxdist; + bmcb_data.maxdist = maxdist_sq; BLI_bvhtree_find_nearest(bmtree->tree, co, &hit, bmbvh_find_vert_closest_cb, &bmcb_data); if (hit.dist != FLT_MAX && hit.index != -1) { diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 43819e1e80e..0546c85db67 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -112,19 +112,6 @@ typedef struct intlists { /* list of list of integers */ struct intlists *next; /* remaining elements */ } INTLISTS; -typedef struct process { /* parameters, function, storage */ - /* what happens here? floats, I think. */ - /* float (*function)(void); */ /* implicit surface function */ - float (*function)(float, float, float); - float size, delta; /* cube size, normal delta */ - int bounds; /* cube range within lattice */ - CUBES *cubes; /* active cubes */ - VERTICES vertices; /* surface vertices */ - CENTERLIST **centers; /* cube center hash table */ - CORNER **corners; /* corner value hash table */ - EDGELIST **edges; /* edge and vertex id hash table */ -} PROCESS; - /* dividing scene using octal tree makes polygonisation faster */ typedef struct ml_pointer { struct ml_pointer *next, *prev; @@ -153,20 +140,41 @@ struct pgn_elements { char *data; }; -/* Forward declarations */ -static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb); -static int setcenter(CENTERLIST *table[], const int i, const int j, const int k); -static CORNER *setcorner(PROCESS *p, int i, int j, int k); -static void converge(const float p1[3], const float p2[3], float v1, float v2, - float (*function)(float, float, float), float p[3], MetaBall *mb, int f); - -/* Global variables */ -static struct { +typedef struct process { /* parameters, function, storage */ + /* ** old G_mb contents ** */ float thresh; int totelem; MetaElem **mainb; octal_tree *metaball_tree; -} G_mb = {0}; + + /* ** old process contents ** */ + + /* what happens here? floats, I think. */ + /* float (*function)(void); */ /* implicit surface function */ + float (*function)(struct process*, float, float, float); + float size, delta; /* cube size, normal delta */ + int bounds; /* cube range within lattice */ + CUBES *cubes; /* active cubes */ + VERTICES vertices; /* surface vertices */ + CENTERLIST **centers; /* cube center hash table */ + CORNER **corners; /* corner value hash table */ + EDGELIST **edges; /* edge and vertex id hash table */ + + /* Runtime things */ + int *indices; + int totindex, curindex; + + int pgn_offset; + struct pgn_elements *pgn_current; + ListBase pgn_list; +} PROCESS; + +/* Forward declarations */ +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb); +static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k); +static CORNER *setcorner(PROCESS *process, int i, int j, int k); +static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, + float p[3], MetaBall *mb, int f); /* Functions */ @@ -519,43 +527,23 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) Scene *sce_iter = scene; Base *base; Object *ob, *bob = basis; - MetaElem *ml = NULL; int basisnr, obnr; char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - G_mb.totelem = 0; /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL)) return NULL; - + while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &ob)) { - if (ob->type == OB_MBALL) { - if (ob == bob) { - MetaBall *mb = ob->data; - - /* if bob object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - } - else { + if (ob != bob) { BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); /* object ob has to be in same "group" ... it means, that it has to have * same base of its name */ if (strcmp(obname, basisname) == 0) { - MetaBall *mb = ob->data; - - /* if object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - if (obnr < basisnr) { if (!(ob->flag & OB_FROMDUPLI)) { basis = ob; @@ -564,12 +552,6 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) } } } - - for ( ; ml; ml = ml->next) { - if (!(ml->flag & MB_HIDE)) { - G_mb.totelem++; - } - } } } @@ -768,60 +750,57 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, return node; } -static float metaball(float x, float y, float z) +static float metaball(PROCESS *process, float x, float y, float z) /* float x, y, z; */ { + octal_tree *metaball_tree = process->metaball_tree; struct octal_node *node; struct ml_pointer *ml_p; float dens = 0; int a; - if (G_mb.totelem > 1) { - node = find_metaball_octal_node(G_mb.metaball_tree->first, x, y, z, G_mb.metaball_tree->depth); + if (process->totelem > 1) { + node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); if (node) { for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) { dens += densfunc(ml_p->ml, x, y, z); } - dens += -0.5f * (G_mb.metaball_tree->pos - node->pos); - dens += 0.5f * (G_mb.metaball_tree->neg - node->neg); + dens += -0.5f * (metaball_tree->pos - node->pos); + dens += 0.5f * (metaball_tree->neg - node->neg); } else { - for (a = 0; a < G_mb.totelem; a++) { - dens += densfunc(G_mb.mainb[a], x, y, z); + for (a = 0; a < process->totelem; a++) { + dens += densfunc(process->mainb[a], x, y, z); } } } else { - dens += densfunc(G_mb.mainb[0], x, y, z); + dens += densfunc(process->mainb[0], x, y, z); } - return G_mb.thresh - dens; + return process->thresh - dens; } /* ******************************************** */ -static int *indices = NULL; -static int totindex, curindex; - - -static void accum_mballfaces(int i1, int i2, int i3, int i4) +static void accum_mballfaces(PROCESS *process, int i1, int i2, int i3, int i4) { int *newi, *cur; /* static int i = 0; I would like to delete altogether, but I don't dare to, yet */ - if (totindex == curindex) { - totindex += 256; - newi = MEM_mallocN(4 * sizeof(int) * totindex, "vertindex"); + if (process->totindex == process->curindex) { + process->totindex += 256; + newi = MEM_mallocN(4 * sizeof(int) * process->totindex, "vertindex"); - if (indices) { - memcpy(newi, indices, 4 * sizeof(int) * (totindex - 256)); - MEM_freeN(indices); + if (process->indices) { + memcpy(newi, process->indices, 4 * sizeof(int) * (process->totindex - 256)); + MEM_freeN(process->indices); } - indices = newi; + process->indices = newi; } - cur = indices + 4 * curindex; + cur = process->indices + 4 * process->curindex; /* displists now support array drawing, we treat tri's as fake quad */ @@ -833,63 +812,62 @@ static void accum_mballfaces(int i1, int i2, int i3, int i4) else cur[3] = i4; - curindex++; + process->curindex++; } /* ******************* MEMORY MANAGEMENT *********************** */ -static void *new_pgn_element(int size) +static void *new_pgn_element(PROCESS *process, int size) { /* during polygonize 1000s of elements are allocated * and never freed in between. Freeing only done at the end. */ int blocksize = 16384; - static int offs = 0; /* the current free address */ - static struct pgn_elements *cur = NULL; - static ListBase lb = {NULL, NULL}; void *adr; if (size > 10000 || size == 0) { printf("incorrect use of new_pgn_element\n"); } else if (size == -1) { - cur = lb.first; + struct pgn_elements *cur = process->pgn_list.first; while (cur) { MEM_freeN(cur->data); cur = cur->next; } - BLI_freelistN(&lb); + BLI_freelistN(&process->pgn_list); return NULL; } size = 4 * ( (size + 3) / 4); - if (cur) { - if (size + offs < blocksize) { - adr = (void *) (cur->data + offs); - offs += size; + if (process->pgn_current) { + if (size + process->pgn_offset < blocksize) { + adr = (void *) (process->pgn_current->data + process->pgn_offset); + process->pgn_offset += size; return adr; } } - cur = MEM_callocN(sizeof(struct pgn_elements), "newpgn"); - cur->data = MEM_callocN(blocksize, "newpgn"); - BLI_addtail(&lb, cur); + process->pgn_current = MEM_callocN(sizeof(struct pgn_elements), "newpgn"); + process->pgn_current->data = MEM_callocN(blocksize, "newpgn"); + BLI_addtail(&process->pgn_list, process->pgn_current); - offs = size; - return cur->data; + process->pgn_offset = size; + return process->pgn_current->data; } -static void freepolygonize(PROCESS *p) +static void freepolygonize(PROCESS *process) { - MEM_freeN(p->corners); - MEM_freeN(p->edges); - MEM_freeN(p->centers); + MEM_freeN(process->corners); + MEM_freeN(process->edges); + MEM_freeN(process->centers); - new_pgn_element(-1); - - if (p->vertices.ptr) MEM_freeN(p->vertices.ptr); + new_pgn_element(process, -1); + + if (process->vertices.ptr) { + MEM_freeN(process->vertices.ptr); + } } /**** Cubical Polygonization (optional) ****/ @@ -928,7 +906,7 @@ static int rightface[12] = { /* docube: triangulate the cube directly, without decomposition */ -static void docube(CUBE *cube, PROCESS *p, MetaBall *mb) +static void docube(PROCESS *process, CUBE *cube, MetaBall *mb) { INTLISTS *polys; CORNER *c1, *c2; @@ -945,45 +923,45 @@ static void docube(CUBE *cube, PROCESS *p, MetaBall *mb) c1 = cube->corners[corner1[edges->i]]; c2 = cube->corners[corner2[edges->i]]; - indexar[count] = vertid(c1, c2, p, mb); + indexar[count] = vertid(process, c1, c2, mb); count++; } if (count > 2) { switch (count) { case 3: - accum_mballfaces(indexar[2], indexar[1], indexar[0], 0); + accum_mballfaces(process, indexar[2], indexar[1], indexar[0], 0); break; case 4: - if (indexar[0] == 0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); break; case 5: - if (indexar[0] == 0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(indexar[4], indexar[3], indexar[0], 0); + accum_mballfaces(process, indexar[4], indexar[3], indexar[0], 0); break; case 6: if (indexar[0] == 0) { - accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); + accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); } else { - accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); + accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); } break; case 7: if (indexar[0] == 0) { - accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); + accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); } else { - accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); + accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); } - accum_mballfaces(indexar[6], indexar[5], indexar[0], 0); + accum_mballfaces(process, indexar[6], indexar[5], indexar[0], 0); break; } @@ -996,10 +974,10 @@ static void docube(CUBE *cube, PROCESS *p, MetaBall *mb) * if surface crosses face, compute other four corners of adjacent cube * and add new cube to cube stack */ -static void testface(int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4, PROCESS *p) +static void testface(PROCESS *process, int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4) { CUBE newc; - CUBES *oldcubes = p->cubes; + CUBES *oldcubes = process->cubes; CORNER *corn1, *corn2, *corn3, *corn4; int n, pos; @@ -1015,12 +993,13 @@ static void testface(int i, int j, int k, CUBE *old, int bit, int c1, int c2, in /* test if cube out of bounds */ /*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/ /* test if already visited (always as last) */ - if (setcenter(p->centers, i, j, k)) return; - + if (setcenter(process, process->centers, i, j, k)) { + return; + } /* create new cube and add cube to top of stack: */ - p->cubes = (CUBES *) new_pgn_element(sizeof(CUBES)); - p->cubes->next = oldcubes; + process->cubes = (CUBES *) new_pgn_element(process, sizeof(CUBES)); + process->cubes->next = oldcubes; newc.i = i; newc.j = j; @@ -1032,22 +1011,22 @@ static void testface(int i, int j, int k, CUBE *old, int bit, int c1, int c2, in newc.corners[FLIP(c3, bit)] = corn3; newc.corners[FLIP(c4, bit)] = corn4; - if (newc.corners[0] == NULL) newc.corners[0] = setcorner(p, i, j, k); - if (newc.corners[1] == NULL) newc.corners[1] = setcorner(p, i, j, k + 1); - if (newc.corners[2] == NULL) newc.corners[2] = setcorner(p, i, j + 1, k); - if (newc.corners[3] == NULL) newc.corners[3] = setcorner(p, i, j + 1, k + 1); - if (newc.corners[4] == NULL) newc.corners[4] = setcorner(p, i + 1, j, k); - if (newc.corners[5] == NULL) newc.corners[5] = setcorner(p, i + 1, j, k + 1); - if (newc.corners[6] == NULL) newc.corners[6] = setcorner(p, i + 1, j + 1, k); - if (newc.corners[7] == NULL) newc.corners[7] = setcorner(p, i + 1, j + 1, k + 1); + if (newc.corners[0] == NULL) newc.corners[0] = setcorner(process, i, j, k); + if (newc.corners[1] == NULL) newc.corners[1] = setcorner(process, i, j, k + 1); + if (newc.corners[2] == NULL) newc.corners[2] = setcorner(process, i, j + 1, k); + if (newc.corners[3] == NULL) newc.corners[3] = setcorner(process, i, j + 1, k + 1); + if (newc.corners[4] == NULL) newc.corners[4] = setcorner(process, i + 1, j, k); + if (newc.corners[5] == NULL) newc.corners[5] = setcorner(process, i + 1, j, k + 1); + if (newc.corners[6] == NULL) newc.corners[6] = setcorner(process, i + 1, j + 1, k); + if (newc.corners[7] == NULL) newc.corners[7] = setcorner(process, i + 1, j + 1, k + 1); - p->cubes->cube = newc; + process->cubes->cube = newc; } /* setcorner: return corner with the given lattice location * set (and cache) its function value */ -static CORNER *setcorner(PROCESS *p, int i, int j, int k) +static CORNER *setcorner(PROCESS *process, int i, int j, int k) { /* for speed, do corner value caching here */ CORNER *c; @@ -1055,7 +1034,7 @@ static CORNER *setcorner(PROCESS *p, int i, int j, int k) /* does corner exist? */ index = HASH(i, j, k); - c = p->corners[index]; + c = process->corners[index]; for (; c != NULL; c = c->next) { if (c->i == i && c->j == j && c->k == k) { @@ -1063,18 +1042,18 @@ static CORNER *setcorner(PROCESS *p, int i, int j, int k) } } - c = (CORNER *) new_pgn_element(sizeof(CORNER)); + c = (CORNER *) new_pgn_element(process, sizeof(CORNER)); c->i = i; - c->co[0] = ((float)i - 0.5f) * p->size; + c->co[0] = ((float)i - 0.5f) * process->size; c->j = j; - c->co[1] = ((float)j - 0.5f) * p->size; + c->co[1] = ((float)j - 0.5f) * process->size; c->k = k; - c->co[2] = ((float)k - 0.5f) * p->size; - c->value = p->function(c->co[0], c->co[1], c->co[2]); + c->co[2] = ((float)k - 0.5f) * process->size; + c->value = process->function(process, c->co[0], c->co[1], c->co[2]); - c->next = p->corners[index]; - p->corners[index] = c; + c->next = process->corners[index]; + process->corners[index] = c; return c; } @@ -1196,7 +1175,7 @@ void BKE_mball_cubeTable_free(void) /* setcenter: set (i, j, k) entry of table[] * return 1 if already set; otherwise, set and return 0 */ -static int setcenter(CENTERLIST *table[], const int i, const int j, const int k) +static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k) { int index; CENTERLIST *newc, *l, *q; @@ -1208,7 +1187,7 @@ static int setcenter(CENTERLIST *table[], const int i, const int j, const int k) if (l->i == i && l->j == j && l->k == k) return 1; } - newc = (CENTERLIST *) new_pgn_element(sizeof(CENTERLIST)); + newc = (CENTERLIST *) new_pgn_element(process, sizeof(CENTERLIST)); newc->i = i; newc->j = j; newc->k = k; @@ -1221,7 +1200,8 @@ static int setcenter(CENTERLIST *table[], const int i, const int j, const int k) /* setedge: set vertex id for edge */ -static void setedge(EDGELIST *table[], +static void setedge(PROCESS *process, + EDGELIST *table[], int i1, int j1, int k1, int i2, int j2, int k2, @@ -1242,7 +1222,7 @@ static void setedge(EDGELIST *table[], k2 = t; } index = HASH(i1, j1, k1) + HASH(i2, j2, k2); - newe = (EDGELIST *) new_pgn_element(sizeof(EDGELIST)); + newe = (EDGELIST *) new_pgn_element(process, sizeof(EDGELIST)); newe->i1 = i1; newe->j1 = j1; newe->k1 = k1; @@ -1316,14 +1296,14 @@ static void addtovertices(VERTICES *vertices, VERTEX v) /* vnormal: compute unit length surface normal at point */ -static void vnormal(const float point[3], PROCESS *p, float r_no[3]) +static void vnormal(PROCESS *process, const float point[3], float r_no[3]) { - const float delta = 0.2f * p->delta; - const float f = p->function(point[0], point[1], point[2]); + const float delta = 0.2f * process->delta; + const float f = process->function(process, point[0], point[1], point[2]); - r_no[0] = p->function(point[0] + delta, point[1], point[2]) - f; - r_no[1] = p->function(point[0], point[1] + delta, point[2]) - f; - r_no[2] = p->function(point[0], point[1], point[2] + delta) - f; + r_no[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; + r_no[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; + r_no[2] = process->function(process, point[0], point[1], point[2] + delta) - f; #if 1 normalize_v3(r_no); @@ -1335,11 +1315,11 @@ static void vnormal(const float point[3], PROCESS *p, float r_no[3]) delta *= 2.0f; - f = p->function(point[0], point[1], point[2]); + f = process->function(process, point[0], point[1], point[2]); - tvec[0] = p->function(point[0] + delta, point[1], point[2]) - f; - tvec[1] = p->function(point[0], point[1] + delta, point[2]) - f; - tvec[2] = p->function(point[0], point[1], point[2] + delta) - f; + tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; + tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; + tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f; if (normalize_v3(tvec) != 0.0f) { add_v3_v3(r_no, tvec); @@ -1350,32 +1330,30 @@ static void vnormal(const float point[3], PROCESS *p, float r_no[3]) } -static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb) +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb) { VERTEX v; - int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); + int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); if (vid != -1) { return vid; /* previously computed */ } - converge(c1->co, c2->co, c1->value, c2->value, p->function, v.co, mb, 1); /* position */ - vnormal(v.co, p, v.no); + converge(process, c1->co, c2->co, c1->value, c2->value, v.co, mb, 1); /* position */ + vnormal(process, v.co, v.no); - addtovertices(&p->vertices, v); /* save vertex */ - vid = p->vertices.count - 1; - setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); + addtovertices(&process->vertices, v); /* save vertex */ + vid = process->vertices.count - 1; + setedge(process, process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); return vid; } - - /* converge: from two points of differing sign, converge to zero crossing */ /* watch it: p1 and p2 are used to calculate */ -static void converge(const float p1[3], const float p2[3], float v1, float v2, - float (*function)(float, float, float), float p[3], MetaBall *mb, int f) +static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, + float p[3], MetaBall *mb, int f) { int i = 0; float pos[3], neg[3]; @@ -1426,8 +1404,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[0] = 0.5f * (pos[0] + neg[0]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; - else neg[0] = p[0]; + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; + else neg[0] = p[0]; } } @@ -1437,8 +1415,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[1] = 0.5f * (pos[1] + neg[1]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; - else neg[1] = p[1]; + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; + else neg[1] = p[1]; } } @@ -1448,8 +1426,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[2] = 0.5f * (pos[2] + neg[2]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; - else neg[2] = p[2]; + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; + else neg[2] = p[2]; } } @@ -1461,7 +1439,7 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, return; } - if ((function(p[0], p[1], p[2])) > 0.0f) { + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) { copy_v3_v3(pos, &p[0]); } else { @@ -1471,7 +1449,7 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, } /* ************************************** */ -static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) +static void add_cube(PROCESS *process, int i, int j, int k, int count) { CUBES *ncube; int n; @@ -1483,11 +1461,11 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) for (b = j - 1; b < j + count; b++) for (c = k - 1; c < k + count; c++) { /* test if cube has been found before */ - if (setcenter(mbproc->centers, a, b, c) == 0) { + if (setcenter(process, process->centers, a, b, c) == 0) { /* push cube on stack: */ - ncube = (CUBES *) new_pgn_element(sizeof(CUBES)); - ncube->next = mbproc->cubes; - mbproc->cubes = ncube; + ncube = (CUBES *) new_pgn_element(process, sizeof(CUBES)); + ncube->next = process->cubes; + process->cubes = ncube; ncube->cube.i = a; ncube->cube.j = b; @@ -1495,18 +1473,18 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) /* set corners of initial cube: */ for (n = 0; n < 8; n++) - ncube->cube.corners[n] = setcorner(mbproc, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0)); + ncube->cube.corners[n] = setcorner(process, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0)); } } } -static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) +static void find_first_points(PROCESS *process, MetaBall *mb, int a) { MetaElem *ml; float f; - ml = G_mb.mainb[a]; + ml = process->mainb[a]; f = 1.0f - (mb->thresh / ml->s); /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be @@ -1521,7 +1499,7 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) float tmp_v, workp_v, max_len, nx, ny, nz, max_dim; calc_mballco(ml, in); - in_v = mbproc->function(in[0], in[1], in[2]); + in_v = process->function(process, in[0], in[1], in[2]); for (i = 0; i < 3; i++) { switch (ml->type) { @@ -1566,16 +1544,16 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) calc_mballco(ml, out); - /*out_v = mbproc->function(out[0], out[1], out[2]);*/ /*UNUSED*/ + /*out_v = process->function(out[0], out[1], out[2]);*/ /*UNUSED*/ /* find "first points" on Implicit Surface of MetaElemnt ml */ copy_v3_v3(workp, in); workp_v = in_v; max_len = len_v3v3(out, in); - nx = abs((out[0] - in[0]) / mbproc->size); - ny = abs((out[1] - in[1]) / mbproc->size); - nz = abs((out[2] - in[2]) / mbproc->size); + nx = abs((out[0] - in[0]) / process->size); + ny = abs((out[1] - in[1]) / process->size); + nz = abs((out[2] - in[2]) / process->size); max_dim = max_fff(nx, ny, nz); if (max_dim != 0.0f) { @@ -1589,22 +1567,22 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) add_v3_v3(workp, dvec); /* compute value of implicite function */ - tmp_v = mbproc->function(workp[0], workp[1], workp[2]); + tmp_v = process->function(process, workp[0], workp[1], workp[2]); /* add cube to the stack, when value of implicite function crosses zero value */ if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) { /* indexes of CUBE, which includes "first point" */ - c_i = (int)floor(workp[0] / mbproc->size); - c_j = (int)floor(workp[1] / mbproc->size); - c_k = (int)floor(workp[2] / mbproc->size); + c_i = (int)floor(workp[0] / process->size); + c_j = (int)floor(workp[1] / process->size); + c_k = (int)floor(workp[2] / process->size); /* add CUBE (with indexes c_i, c_j, c_k) to the stack, * this cube includes found point of Implicit Surface */ if ((ml->flag & MB_NEGATIVE) == 0) { - add_cube(mbproc, c_i, c_j, c_k, 1); + add_cube(process, c_i, c_j, c_k, 1); } else { - add_cube(mbproc, c_i, c_j, c_k, 2); + add_cube(process, c_i, c_j, c_k, 2); } } len = len_v3v3(workp, in); @@ -1618,43 +1596,43 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) } } -static void polygonize(PROCESS *mbproc, MetaBall *mb) +static void polygonize(PROCESS *process, MetaBall *mb) { CUBE c; int a; - mbproc->vertices.count = mbproc->vertices.max = 0; - mbproc->vertices.ptr = NULL; + process->vertices.count = process->vertices.max = 0; + process->vertices.ptr = NULL; /* allocate hash tables and build cube polygon table: */ - mbproc->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); - mbproc->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); - mbproc->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); + process->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); + process->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); + process->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); makecubetable(); - for (a = 0; a < G_mb.totelem; a++) { + for (a = 0; a < process->totelem; a++) { /* try to find 8 points on the surface for each MetaElem */ - find_first_points(mbproc, mb, a); + find_first_points(process, mb, a); } /* polygonize all MetaElems of current MetaBall */ - while (mbproc->cubes != NULL) { /* process active cubes till none left */ - c = mbproc->cubes->cube; + while (process->cubes != NULL) { /* process active cubes till none left */ + c = process->cubes->cube; /* polygonize the cube directly: */ - docube(&c, mbproc, mb); + docube(process, &c, mb); /* pop current cube from stack */ - mbproc->cubes = mbproc->cubes->next; + process->cubes = process->cubes->next; /* test six face directions, maybe add to stack: */ - testface(c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF, mbproc); - testface(c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF, mbproc); - testface(c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF, mbproc); - testface(c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF, mbproc); - testface(c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN, mbproc); - testface(c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF, mbproc); + testface(process, c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF); + testface(process, c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF); + testface(process, c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF); + testface(process, c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF); + testface(process, c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN); + testface(process, c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF); } } @@ -1666,7 +1644,7 @@ BLI_INLINE void copy_v3_fl3(float v[3], float x, float y, float z) v[2] = z; } -static float init_meta(Scene *scene, Object *ob) /* return totsize */ +static float init_meta(PROCESS *process, Scene *scene, Object *ob) /* return totsize */ { Scene *sce_iter = scene; Base *base; @@ -1733,7 +1711,7 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ ml_count++; ml = ml->next; } - G_mb.totelem -= ml_count; + process->totelem -= ml_count; } else { while (ml) { @@ -1763,12 +1741,12 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ mul_m4_m4m4(temp1, temp2, temp3); /* make a copy because of duplicates */ - G_mb.mainb[a] = new_pgn_element(sizeof(MetaElem)); - *(G_mb.mainb[a]) = *ml; - G_mb.mainb[a]->bb = new_pgn_element(sizeof(BoundBox)); + process->mainb[a] = new_pgn_element(process, sizeof(MetaElem)); + *(process->mainb[a]) = *ml; + process->mainb[a]->bb = new_pgn_element(process, sizeof(BoundBox)); - mat = new_pgn_element(4 * 4 * sizeof(float)); - imat = new_pgn_element(4 * 4 * sizeof(float)); + mat = new_pgn_element(process, 4 * 4 * sizeof(float)); + imat = new_pgn_element(process, 4 * 4 * sizeof(float)); /* mat is the matrix to transform from mball into the basis-mball */ invert_m4_m4(obinv, obmat); @@ -1778,10 +1756,10 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ invert_m4_m4(imat, mat); - G_mb.mainb[a]->rad2 = ml->rad * ml->rad; + process->mainb[a]->rad2 = ml->rad * ml->rad; - G_mb.mainb[a]->mat = (float *) mat; - G_mb.mainb[a]->imat = (float *) imat; + process->mainb[a]->mat = (float *) mat; + process->mainb[a]->imat = (float *) imat; if (!MB_TYPE_SIZE_SQUARED(ml->type)) { expx = ml->expx; @@ -1796,40 +1774,40 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ /* untransformed Bounding Box of MetaElem */ /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */ + copy_v3_fl3(process->mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */ + copy_v3_fl3(process->mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */ + copy_v3_fl3(process->mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */ + copy_v3_fl3(process->mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */ + copy_v3_fl3(process->mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */ + copy_v3_fl3(process->mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */ + copy_v3_fl3(process->mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */ + copy_v3_fl3(process->mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */ /* transformation of Metalem bb */ for (i = 0; i < 8; i++) - mul_m4_v3((float (*)[4])mat, G_mb.mainb[a]->bb->vec[i]); + mul_m4_v3((float (*)[4])mat, process->mainb[a]->bb->vec[i]); /* find max and min of transformed bb */ for (i = 0; i < 8; i++) { /* find maximums */ - if (G_mb.mainb[a]->bb->vec[i][0] > max_x) max_x = G_mb.mainb[a]->bb->vec[i][0]; - if (G_mb.mainb[a]->bb->vec[i][1] > max_y) max_y = G_mb.mainb[a]->bb->vec[i][1]; - if (G_mb.mainb[a]->bb->vec[i][2] > max_z) max_z = G_mb.mainb[a]->bb->vec[i][2]; + if (process->mainb[a]->bb->vec[i][0] > max_x) max_x = process->mainb[a]->bb->vec[i][0]; + if (process->mainb[a]->bb->vec[i][1] > max_y) max_y = process->mainb[a]->bb->vec[i][1]; + if (process->mainb[a]->bb->vec[i][2] > max_z) max_z = process->mainb[a]->bb->vec[i][2]; /* find minimums */ - if (G_mb.mainb[a]->bb->vec[i][0] < min_x) min_x = G_mb.mainb[a]->bb->vec[i][0]; - if (G_mb.mainb[a]->bb->vec[i][1] < min_y) min_y = G_mb.mainb[a]->bb->vec[i][1]; - if (G_mb.mainb[a]->bb->vec[i][2] < min_z) min_z = G_mb.mainb[a]->bb->vec[i][2]; + if (process->mainb[a]->bb->vec[i][0] < min_x) min_x = process->mainb[a]->bb->vec[i][0]; + if (process->mainb[a]->bb->vec[i][1] < min_y) min_y = process->mainb[a]->bb->vec[i][1]; + if (process->mainb[a]->bb->vec[i][2] < min_z) min_z = process->mainb[a]->bb->vec[i][2]; } /* create "new" bb, only point 0 and 6, which are * necessary for octal tree filling */ - G_mb.mainb[a]->bb->vec[0][0] = min_x - ml->rad; - G_mb.mainb[a]->bb->vec[0][1] = min_y - ml->rad; - G_mb.mainb[a]->bb->vec[0][2] = min_z - ml->rad; + process->mainb[a]->bb->vec[0][0] = min_x - ml->rad; + process->mainb[a]->bb->vec[0][1] = min_y - ml->rad; + process->mainb[a]->bb->vec[0][2] = min_z - ml->rad; - G_mb.mainb[a]->bb->vec[6][0] = max_x + ml->rad; - G_mb.mainb[a]->bb->vec[6][1] = max_y + ml->rad; - G_mb.mainb[a]->bb->vec[6][2] = max_z + ml->rad; + process->mainb[a]->bb->vec[6][0] = max_x + ml->rad; + process->mainb[a]->bb->vec[6][1] = max_y + ml->rad; + process->mainb[a]->bb->vec[6][2] = max_z + ml->rad; a++; } @@ -1842,13 +1820,13 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ /* totsize (= 'manhattan' radius) */ totsize = 0.0; - for (a = 0; a < G_mb.totelem; a++) { + for (a = 0; a < process->totelem; a++) { - vec[0] = G_mb.mainb[a]->x + G_mb.mainb[a]->rad + G_mb.mainb[a]->expx; - vec[1] = G_mb.mainb[a]->y + G_mb.mainb[a]->rad + G_mb.mainb[a]->expy; - vec[2] = G_mb.mainb[a]->z + G_mb.mainb[a]->rad + G_mb.mainb[a]->expz; + vec[0] = process->mainb[a]->x + process->mainb[a]->rad + process->mainb[a]->expx; + vec[1] = process->mainb[a]->y + process->mainb[a]->rad + process->mainb[a]->expy; + vec[2] = process->mainb[a]->z + process->mainb[a]->rad + process->mainb[a]->expz; - calc_mballco(G_mb.mainb[a], vec); + calc_mballco(process->mainb[a], vec); size = fabsf(vec[0]); if (size > totsize) totsize = size; @@ -1857,11 +1835,11 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ size = fabsf(vec[2]); if (size > totsize) totsize = size; - vec[0] = G_mb.mainb[a]->x - G_mb.mainb[a]->rad; - vec[1] = G_mb.mainb[a]->y - G_mb.mainb[a]->rad; - vec[2] = G_mb.mainb[a]->z - G_mb.mainb[a]->rad; + vec[0] = process->mainb[a]->x - process->mainb[a]->rad; + vec[1] = process->mainb[a]->y - process->mainb[a]->rad; + vec[2] = process->mainb[a]->z - process->mainb[a]->rad; - calc_mballco(G_mb.mainb[a], vec); + calc_mballco(process->mainb[a], vec); size = fabsf(vec[0]); if (size > totsize) totsize = size; @@ -1871,8 +1849,8 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ if (size > totsize) totsize = size; } - for (a = 0; a < G_mb.totelem; a++) { - G_mb.thresh += densfunc(G_mb.mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); + for (a = 0; a < process->totelem; a++) { + process->thresh += densfunc(process->mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); } return totsize; @@ -2181,20 +2159,20 @@ static void free_metaball_octal_node(octal_node *node) } /* If scene include more than one MetaElem, then octree is used */ -static void init_metaball_octal_tree(int depth) +static void init_metaball_octal_tree(PROCESS *process, int depth) { struct octal_node *node; ml_pointer *ml_p; float size[3]; int a; - G_mb.metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); - G_mb.metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); + process->metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); + process->metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); /* maximal depth of octree */ - G_mb.metaball_tree->depth = depth; + process->metaball_tree->depth = depth; - G_mb.metaball_tree->neg = node->neg = 0; - G_mb.metaball_tree->pos = node->pos = 0; + process->metaball_tree->neg = node->neg = 0; + process->metaball_tree->pos = node->pos = 0; node->elems.first = NULL; node->elems.last = NULL; @@ -2207,26 +2185,26 @@ static void init_metaball_octal_tree(int depth) node->x_max = node->y_max = node->z_max = -FLT_MAX; /* size of octal tree scene */ - for (a = 0; a < G_mb.totelem; a++) { - if (G_mb.mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = G_mb.mainb[a]->bb->vec[0][0]; - if (G_mb.mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = G_mb.mainb[a]->bb->vec[0][1]; - if (G_mb.mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = G_mb.mainb[a]->bb->vec[0][2]; + for (a = 0; a < process->totelem; a++) { + if (process->mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = process->mainb[a]->bb->vec[0][0]; + if (process->mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = process->mainb[a]->bb->vec[0][1]; + if (process->mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = process->mainb[a]->bb->vec[0][2]; - if (G_mb.mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = G_mb.mainb[a]->bb->vec[6][0]; - if (G_mb.mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = G_mb.mainb[a]->bb->vec[6][1]; - if (G_mb.mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = G_mb.mainb[a]->bb->vec[6][2]; + if (process->mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = process->mainb[a]->bb->vec[6][0]; + if (process->mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = process->mainb[a]->bb->vec[6][1]; + if (process->mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = process->mainb[a]->bb->vec[6][2]; ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); - ml_p->ml = G_mb.mainb[a]; + ml_p->ml = process->mainb[a]; BLI_addtail(&node->elems, ml_p); - if ((G_mb.mainb[a]->flag & MB_NEGATIVE) == 0) { + if ((process->mainb[a]->flag & MB_NEGATIVE) == 0) { /* number of positive MetaElem in scene */ - G_mb.metaball_tree->pos++; + process->metaball_tree->pos++; } else { /* number of negative MetaElem in scene */ - G_mb.metaball_tree->neg++; + process->metaball_tree->neg++; } } @@ -2236,61 +2214,106 @@ static void init_metaball_octal_tree(int depth) size[2] = node->z_max - node->z_min; /* first node is subdivided recursively */ - subdivide_metaball_octal_node(node, size[0], size[1], size[2], G_mb.metaball_tree->depth); + subdivide_metaball_octal_node(node, size[0], size[1], size[2], process->metaball_tree->depth); +} + +static void mball_count(PROCESS *process, Scene *scene, Object *basis) +{ + Scene *sce_iter = scene; + Base *base; + Object *ob, *bob = basis; + MetaElem *ml = NULL; + int basisnr, obnr; + char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; + + BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); + process->totelem = 0; + + /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ + if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL)) + return; + + while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &ob)) { + if (ob->type == OB_MBALL) { + if (ob == bob) { + MetaBall *mb = ob->data; + + /* if bob object is in edit mode, then dynamic list of all MetaElems + * is stored in editelems */ + if (mb->editelems) ml = mb->editelems->first; + /* if bob object is in object mode */ + else ml = mb->elems.first; + } + else { + BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); + + /* object ob has to be in same "group" ... it means, that it has to have + * same base of its name */ + if (strcmp(obname, basisname) == 0) { + MetaBall *mb = ob->data; + + /* if object is in edit mode, then dynamic list of all MetaElems + * is stored in editelems */ + if (mb->editelems) ml = mb->editelems->first; + /* if bob object is in object mode */ + else ml = mb->elems.first; + } + } + + for ( ; ml; ml = ml->next) { + if (!(ml->flag & MB_HIDE)) { + process->totelem++; + } + } + } + } } void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) { - PROCESS mbproc; MetaBall *mb; DispList *dl; int a, nr_cubes; float *co, *no, totsize, width; + PROCESS process = {0}; mb = ob->data; - if (G_mb.totelem == 0) return; + mball_count(&process, scene, ob); + + if (process.totelem == 0) return; if ((G.is_rendering == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return; if (G.moving && mb->flag == MB_UPDATE_FAST) return; - curindex = totindex = 0; - indices = NULL; - G_mb.thresh = mb->thresh; + process.thresh = mb->thresh; /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ - G_mb.mainb = MEM_mallocN(sizeof(void *) * G_mb.totelem, "mainb"); + process.mainb = MEM_mallocN(sizeof(void *) * process.totelem, "mainb"); /* initialize all mainb (MetaElems) */ - totsize = init_meta(scene, ob); - - if (G_mb.metaball_tree) { - free_metaball_octal_node(G_mb.metaball_tree->first); - MEM_freeN(G_mb.metaball_tree); - G_mb.metaball_tree = NULL; - } + totsize = init_meta(&process, scene, ob); /* if scene includes more than one MetaElem, then octal tree optimization is used */ - if ((G_mb.totelem > 1) && (G_mb.totelem <= 64)) init_metaball_octal_tree(1); - if ((G_mb.totelem > 64) && (G_mb.totelem <= 128)) init_metaball_octal_tree(2); - if ((G_mb.totelem > 128) && (G_mb.totelem <= 512)) init_metaball_octal_tree(3); - if ((G_mb.totelem > 512) && (G_mb.totelem <= 1024)) init_metaball_octal_tree(4); - if (G_mb.totelem > 1024) init_metaball_octal_tree(5); + if ((process.totelem > 1) && (process.totelem <= 64)) init_metaball_octal_tree(&process, 1); + if ((process.totelem > 64) && (process.totelem <= 128)) init_metaball_octal_tree(&process, 2); + if ((process.totelem > 128) && (process.totelem <= 512)) init_metaball_octal_tree(&process, 3); + if ((process.totelem > 512) && (process.totelem <= 1024)) init_metaball_octal_tree(&process, 4); + if (process.totelem > 1024) init_metaball_octal_tree(&process, 5); /* don't polygonize metaballs with too high resolution (base mball to small) * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ - if (G_mb.metaball_tree) { - if (ob->size[0] <= 0.00001f * (G_mb.metaball_tree->first->x_max - G_mb.metaball_tree->first->x_min) || - ob->size[1] <= 0.00001f * (G_mb.metaball_tree->first->y_max - G_mb.metaball_tree->first->y_min) || - ob->size[2] <= 0.00001f * (G_mb.metaball_tree->first->z_max - G_mb.metaball_tree->first->z_min)) + if (process.metaball_tree) { + if (ob->size[0] <= 0.00001f * (process.metaball_tree->first->x_max - process.metaball_tree->first->x_min) || + ob->size[1] <= 0.00001f * (process.metaball_tree->first->y_max - process.metaball_tree->first->y_min) || + ob->size[2] <= 0.00001f * (process.metaball_tree->first->z_max - process.metaball_tree->first->z_min)) { - new_pgn_element(-1); /* free values created by init_meta */ + new_pgn_element(&process, -1); /* free values created by init_meta */ - MEM_freeN(G_mb.mainb); + MEM_freeN(process.mainb); /* free tree */ - free_metaball_octal_node(G_mb.metaball_tree->first); - MEM_freeN(G_mb.metaball_tree); - G_mb.metaball_tree = NULL; + free_metaball_octal_node(process.metaball_tree->first); + MEM_freeN(process.metaball_tree); return; } @@ -2308,46 +2331,46 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) nr_cubes = (int)(0.5f + totsize / width); /* init process */ - mbproc.function = metaball; - mbproc.size = width; - mbproc.bounds = nr_cubes; - mbproc.cubes = NULL; - mbproc.delta = width / (float)(RES * RES); + process.function = metaball; + process.size = width; + process.bounds = nr_cubes; + process.cubes = NULL; + process.delta = width / (float)(RES * RES); - polygonize(&mbproc, mb); + polygonize(&process, mb); - MEM_freeN(G_mb.mainb); + MEM_freeN(process.mainb); /* free octal tree */ - if (G_mb.totelem > 1) { - free_metaball_octal_node(G_mb.metaball_tree->first); - MEM_freeN(G_mb.metaball_tree); - G_mb.metaball_tree = NULL; + if (process.totelem > 1) { + free_metaball_octal_node(process.metaball_tree->first); + MEM_freeN(process.metaball_tree); + process.metaball_tree = NULL; } - if (curindex) { - VERTEX *ptr = mbproc.vertices.ptr; + if (process.curindex) { + VERTEX *ptr = process.vertices.ptr; dl = MEM_callocN(sizeof(DispList), "mbaldisp"); BLI_addtail(dispbase, dl); dl->type = DL_INDEX4; - dl->nr = mbproc.vertices.count; - dl->parts = curindex; + dl->nr = process.vertices.count; + dl->parts = process.curindex; - dl->index = indices; - indices = NULL; + dl->index = process.indices; + process.indices = NULL; - a = mbproc.vertices.count; + a = process.vertices.count; dl->verts = co = MEM_mallocN(sizeof(float) * 3 * a, "mballverts"); dl->nors = no = MEM_mallocN(sizeof(float) * 3 * a, "mballnors"); - for (a = 0; a < mbproc.vertices.count; ptr++, a++, no += 3, co += 3) { + for (a = 0; a < process.vertices.count; ptr++, a++, no += 3, co += 3) { copy_v3_v3(co, ptr->co); copy_v3_v3(no, ptr->no); } } - freepolygonize(&mbproc); + freepolygonize(&process); } /* basic vertex data functions */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index c17830639e4..a0fa3317297 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -36,7 +36,7 @@ * \ingroup bke */ - +#include <stdlib.h> #include <stddef.h> #include <string.h> #include <stdarg.h> @@ -60,6 +60,7 @@ #include "BKE_cloth.h" #include "BKE_key.h" #include "BKE_multires.h" +#include "BKE_DerivedMesh.h" /* may move these, only for modifier_path_relbase */ #include "BKE_global.h" /* ugh, G.main->name only */ @@ -693,3 +694,65 @@ void modifier_path_init(char *path, int path_maxlen, const char *name) G.relbase_valid ? "//" : BLI_temporary_dir(), name); } + + +/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */ + +struct DerivedMesh *modwrap_applyModifier( + ModifierData *md, Object *ob, + struct DerivedMesh *dm, + ModifierApplyFlag flag) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + return mti->applyModifier(md, ob, dm, flag); +} + +struct DerivedMesh *modwrap_applyModifierEM( + ModifierData *md, Object *ob, + struct BMEditMesh *em, + DerivedMesh *dm, + ModifierApplyFlag flag) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + return mti->applyModifierEM(md, ob, em, dm, flag); +} + +void modwrap_deformVerts( + ModifierData *md, Object *ob, + DerivedMesh *dm, + float (*vertexCos)[3], int numVerts, + ModifierApplyFlag flag) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag); +} + +void modwrap_deformVertsEM( + ModifierData *md, Object *ob, + struct BMEditMesh *em, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts); +} +/* end modifier callback wrappers */ diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index a36627bd903..e0a34e35acc 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -162,7 +162,7 @@ void BLI_path_rel(char *file, const char *relfile); bool BLI_path_is_rel(const char *path); /* path string comparisons: case-insensitive for Windows, case-sensitive otherwise */ -#ifdef WIN32 +#if defined(WIN32) # define BLI_path_cmp BLI_strcasecmp # define BLI_path_ncmp BLI_strncasecmp #else diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 224d02163cb..4d80080ed86 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -263,9 +263,21 @@ #define STACK_PUSH(stack, val) (void)((stack)[(_##stack##_index)++] = val) #define STACK_PUSH_RET(stack) ((void)stack, ((stack)[(_##stack##_index)++])) #define STACK_PUSH_RET_PTR(stack) ((void)stack, &((stack)[(_##stack##_index)++])) -#define STACK_POP(stack) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : NULL) -#define STACK_POP_ELSE(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : r) +#define STACK_POP(stack) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : NULL) +#define STACK_POP_PTR(stack) ((_##stack##_index) ? &((stack)[--(_##stack##_index)]) : NULL) +#define STACK_POP_ELSE(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : r) #define STACK_FREE(stack) ((void)stack) +#ifdef __GNUC__ +#define STACK_SWAP(stack_a, stack_b) { \ + SWAP(typeof(stack_a), stack_a, stack_b); \ + SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \ + } (void)0 +#else +#define STACK_SWAP(stack_a, stack_b) { \ + SWAP(void *, stack_a, stack_b); \ + SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \ + } (void)0 +#endif /* array helpers */ #define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot) \ diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index a8fdcd56abb..2da36377e55 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -30,6 +30,7 @@ * \ingroup bli */ +#include <stdlib.h> #include <string.h> #include "MEM_guardedalloc.h" @@ -207,6 +208,8 @@ void *BLI_heap_popmin(Heap *heap) { void *ptr = heap->tree[0]->ptr; + BLI_assert(heap->size == 0); + heap->tree[0]->ptr = heap->freenodes; heap->freenodes = heap->tree[0]; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d44e3fd4948..07ed2f18111 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9605,6 +9605,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) link_list(fd, &user->themes); link_list(fd, &user->user_keymaps); link_list(fd, &user->addons); + link_list(fd, &user->autoexec_paths); for (keymap=user->user_keymaps.first; keymap; keymap=keymap->next) { keymap->modal_items= NULL; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d8bf1a5e4c4..9b6699f3f21 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -860,6 +860,7 @@ static void write_userdef(WriteData *wd) wmKeyMapItem *kmi; wmKeyMapDiffItem *kmdi; bAddon *bext; + bPathCompare *path_cmp; uiStyle *style; writestruct(wd, USER, "UserDef", 1, &U); @@ -888,6 +889,10 @@ static void write_userdef(WriteData *wd) IDP_WriteProperty(bext->prop, wd); } } + + for (path_cmp = U.autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) { + writestruct(wd, DATA, "bPathCompare", 1, path_cmp); + } for (style= U.uistyles.first; style; style= style->next) { writestruct(wd, DATA, "uiStyle", 1, style); diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 8d95ab85df8..c92b049eafb 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -290,6 +290,6 @@ extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self); * but should not error on valid cases */ #define BM_LOOP_RADIAL_MAX 10000 #define BM_NGON_MAX 100000 -#define BM_OMP_LIMIT 10000 /* setting zero so we can catch bugs in OpenMP/BMesh */ +#define BM_OMP_LIMIT 0 /* 10000 */ /* setting zero so we can catch bugs in OpenMP/BMesh */ #endif /* __BMESH_CLASS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 2608a79d455..313d76721fa 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -498,6 +498,8 @@ static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag, BMIter iter; int tot = 0; + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + if (htype & BM_VERT) { for (ele = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); ele; ele = BM_iter_step(&iter)) { if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) continue; @@ -803,6 +805,8 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl int i; + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + if (hflag & BM_ELEM_SELECT) { BM_select_history_clear(bm); } @@ -872,6 +876,8 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla BMElem *ele; int i; + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + if (hflag & BM_ELEM_SELECT) { BM_select_history_clear(bm); } diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 79dacaad2fa..4027d4b2c19 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -628,6 +628,8 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu */ int BM_mesh_elem_count(BMesh *bm, const char htype) { + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + switch (htype) { case BM_VERT: return bm->totvert; case BM_EDGE: return bm->totedge; diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c index eda252f18f5..9fc1996e51a 100644 --- a/source/blender/bmesh/tools/bmesh_path.c +++ b/source/blender/bmesh/tools/bmesh_path.c @@ -144,7 +144,8 @@ LinkNode *BM_mesh_calc_path_vert( BLI_heap_insert(heap, 0.0f, v_src); cost[BM_elem_index_get(v_src)] = 0.0f; - while ((v = BLI_heap_popmin(heap))) { + while (!BLI_heap_is_empty(heap)) { + v = BLI_heap_popmin(heap); if (v == v_dst) break; @@ -261,7 +262,8 @@ LinkNode *BM_mesh_calc_path_edge( BLI_heap_insert(heap, 0.0f, e_src); cost[BM_elem_index_get(e_src)] = 0.0f; - while ((e = BLI_heap_popmin(heap))) { + while (!BLI_heap_is_empty(heap)) { + e = BLI_heap_popmin(heap); if (e == e_dst) break; @@ -386,7 +388,8 @@ LinkNode *BM_mesh_calc_path_face( BLI_heap_insert(heap, 0.0f, f_src); cost[BM_elem_index_get(f_src)] = 0.0f; - while ((f = BLI_heap_popmin(heap))) { + while (!BLI_heap_is_empty(heap)) { + f = BLI_heap_popmin(heap); if (f == f_dst) break; diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 097ea477501..f35edb70251 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -76,6 +76,8 @@ struct MeshStatVis; /* editmesh_utils.c */ +void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const bool use_self, const bool use_select, + const bool is_topo, float maxdist, int *r_index); void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const bool use_self, const bool use_select); void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to); struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index cb2f3e3286e..86e51b201d9 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -304,7 +304,7 @@ typedef struct uiSearchItems uiSearchItems; typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2); typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origstr); typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2); -typedef void (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); +typedef bool (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items); typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); @@ -644,7 +644,7 @@ typedef struct AutoComplete AutoComplete; AutoComplete *autocomplete_begin(const char *startname, size_t maxlen); void autocomplete_do_name(AutoComplete *autocpl, const char *name); -void autocomplete_end(AutoComplete *autocpl, char *autoname); +bool autocomplete_end(AutoComplete *autocpl, char *autoname); /* Panels * diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5a1ba8f31f0..19eb978a01e 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -443,17 +443,24 @@ void uiExplicitBoundsBlock(uiBlock *block, int minx, int miny, int maxx, int max static int ui_but_float_precision(uiBut *but, double value) { int prec; + const double pow10_neg[PRECISION_FLOAT_MAX + 1] = {1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001}; /* first check if prec is 0 and fallback to a simple default */ if ((prec = (int)but->a2) == -1) { prec = (but->hardmax < 10.001f) ? 3 : 2; } + BLI_assert(prec <= PRECISION_FLOAT_MAX); + BLI_assert(pow10_neg[prec] == pow(10, -prec)); + /* check on the number of decimal places need to display * the number, this is so 0.00001 is not displayed as 0.00, * _but_, this is only for small values si 10.0001 will not get * the same treatment */ - if (value != 0.0 && (value = ABS(value)) < 0.1) { + value = ABS(value); + if ((value < pow10_neg[prec]) && + (value > (1.0 / PRECISION_FLOAT_MAX_POW))) + { int value_i = (int)((value * PRECISION_FLOAT_MAX_POW) + 0.5); if (value_i != 0) { const int prec_span = 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */ @@ -3086,16 +3093,21 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name) } } -void autocomplete_end(AutoComplete *autocpl, char *autoname) +bool autocomplete_end(AutoComplete *autocpl, char *autoname) { - if (autocpl->truncate[0]) + bool change = false; + if (autocpl->truncate[0]) { BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen); + change = true; + } else { - if (autoname != autocpl->startname) /* don't copy a string over its self */ + if (autoname != autocpl->startname) { /* don't copy a string over its self */ BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen); + } } MEM_freeN(autocpl->truncate); MEM_freeN(autocpl); + return change; } static void ui_check_but_and_iconize(uiBut *but, int icon) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a9378d11cc3..7aee228ddaa 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1828,20 +1828,19 @@ static bool ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directi static bool ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData *data) { char *str; - /* TODO, should return false if it cant autocomp. */ - bool changed = true; + bool change = true; str = data->str; if (data->searchbox) - ui_searchbox_autocomplete(C, data->searchbox, but, data->str); + change = ui_searchbox_autocomplete(C, data->searchbox, but, data->str); else - but->autocomplete_func(C, str, but->autofunc_arg); + change = but->autocomplete_func(C, str, but->autofunc_arg); but->pos = strlen(str); but->selsta = but->selend = but->pos; - return changed; + return change; } /* mode for ui_textedit_copypaste() */ @@ -6581,7 +6580,8 @@ static void ui_mouse_motion_towards_reinit(uiPopupBlockHandle *menu, const int x ui_mouse_motion_towards_init_ex(menu, xy, true); } -static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2]) +static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2], + const bool use_wiggle_room) { float p1[2], p2[2], p3[2], p4[2]; float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]}; @@ -6615,8 +6615,8 @@ static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *me p4[1] = rect_px.ymax + margin; /* allow for some wiggle room, if the user moves a few pixels away, - * don't immediately quit */ - { + * don't immediately quit (only for top level menus) */ + if (use_wiggle_room) { const float cent[2] = { BLI_rctf_cent_x(&rect_px), BLI_rctf_cent_y(&rect_px)}; @@ -6789,7 +6789,8 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock return retval; } -static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, int level) +static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, + int level, const bool is_parent_inside) { ARegion *ar; uiBlock *block; @@ -7130,7 +7131,7 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK; } else { - ui_mouse_motion_towards_check(block, menu, &event->x); + ui_mouse_motion_towards_check(block, menu, &event->x, is_parent_inside == false); /* check mouse moving outside of the menu */ if (inside == 0 && (block->flag & UI_BLOCK_MOVEMOUSE_QUIT)) { @@ -7233,7 +7234,8 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo return WM_UI_HANDLER_BREAK; } -static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, int level) +static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, + int level, const bool is_parent_inside) { uiBut *but; uiHandleButtonData *data; @@ -7246,8 +7248,21 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB data = (but) ? but->active : NULL; submenu = (data) ? data->menu : NULL; - if (submenu) - retval = ui_handle_menus_recursive(C, event, submenu, level + 1); + if (submenu) { + bool inside = false; + + if (is_parent_inside == false) { + int mx, my; + uiBlock *block = menu->region->uiblocks.first; + + mx = event->x; + my = event->y; + ui_window_to_block(menu->region, block, &mx, &my); + inside = BLI_rctf_isect_pt(&block->rect, mx, my); + } + + retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside); + } /* now handle events for our own menu */ if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) { @@ -7275,7 +7290,7 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB } } else { - retval = ui_handle_menu_event(C, event, menu, level); + retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside); } } @@ -7371,7 +7386,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE /* handle events for menus and their buttons recursively, * this will handle events from the top to the bottom menu */ if (data->menu) - retval = ui_handle_menus_recursive(C, event, data->menu, 0); + retval = ui_handle_menus_recursive(C, event, data->menu, 0, false); /* handle events for the activated button */ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) || @@ -7417,7 +7432,7 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata) retval = WM_UI_HANDLER_CONTINUE; } - ui_handle_menus_recursive(C, event, menu, 0); + ui_handle_menus_recursive(C, event, menu, 0, false); /* free if done, does not free handle itself */ if (menu->menuretval) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 9de608f2730..a6076b8df78 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -471,7 +471,7 @@ ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBu bool ui_searchbox_inside(struct ARegion *ar, int x, int y); int ui_searchbox_find_index(struct ARegion *ar, const char *name); void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, const bool reset); -void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str); +bool ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str); void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, const struct wmEvent *event); bool ui_searchbox_apply(uiBut *but, struct ARegion *ar); void ui_searchbox_free(struct bContext *C, struct ARegion *ar); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index b6575f4eca0..ef839f1d143 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -525,7 +525,7 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt name = (!uiname || uiname[0]) ? item->name : ""; icon = item->icon; value = item->value; - itemw = ui_text_icon_width(block->curlayout, name, icon, 0); + itemw = ui_text_icon_width(block->curlayout, icon_only ? "" : name, icon, 0); if (icon && name[0] && !icon_only) but = uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index b764c70b111..1ff46004bdf 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1039,18 +1039,20 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset) ED_region_tag_redraw(ar); } -void ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str) +bool ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str) { uiSearchboxData *data = ar->regiondata; + bool changed = false; if (str[0]) { data->items.autocpl = autocomplete_begin(str, ui_get_but_string_max_length(but)); but->search_func(C, but->search_arg, but->editstr, &data->items); - autocomplete_end(data->items.autocpl, str); + changed = autocomplete_end(data->items.autocpl, str); data->items.autocpl = NULL; } + return changed; } static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 00eabad729e..d8efb972ce9 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2286,8 +2286,7 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol) } /* ************ button callbacks, draw ***************** */ - -static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) +static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss) { uiWidgetBase wtb; const float rad = 0.5f * BLI_rcti_size_y(rect); @@ -2298,9 +2297,10 @@ static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int round widget_init(&wtb); - /* fully rounded */ - round_box_edges(&wtb, roundboxalign, rect, rad); - + if (!emboss) { + round_box_edges(&wtb, roundboxalign, rect, rad); + } + /* decoration */ if (!(state & UI_TEXTINPUT)) { widget_num_tria(&wtb.tria1, rect, 0.6f, 'l'); @@ -2314,6 +2314,19 @@ static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int round rect->xmax -= textofs; } +static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) +{ + widget_numbut_draw(wcol, rect, state, roundboxalign, false); +} + +/* + * Draw number buttons still with triangles when field is not embossed +*/ +static void widget_numbut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) +{ + widget_numbut_draw(wcol, rect, state, roundboxalign, true); +} + int ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol) { float dist, vec[4][2]; @@ -2671,7 +2684,7 @@ static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUS ui_draw_but_NORMAL(but, wcol, rect); } -static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) +static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) { if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) { uiWidgetBase wtb; @@ -2685,6 +2698,11 @@ static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti round_box_edges(&wtb, UI_CNR_ALL, rect, rad); widgetbase_draw(&wtb, wcol); } + else if (but->type == NUM) { + /* Draw number buttons still with left/right + * triangles when field is not embossed */ + widget_numbut_embossn(but, wcol, rect, state, roundboxalign); + } } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index fa857edb6fc..963b9cf134b 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -507,17 +507,20 @@ bool EDBM_index_arrays_check(BMEditMesh *em) BMVert *EDBM_vert_at_index(BMEditMesh *em, int index) { - return em->vert_index && index < em->bm->totvert ? em->vert_index[index] : NULL; + BLI_assert((index >= 0) && (index < em->bm->totvert)); + return em->vert_index[index]; } BMEdge *EDBM_edge_at_index(BMEditMesh *em, int index) { - return em->edge_index && index < em->bm->totedge ? em->edge_index[index] : NULL; + BLI_assert((index >= 0) && (index < em->bm->totedge)); + return em->edge_index[index]; } BMFace *EDBM_face_at_index(BMEditMesh *em, int index) { - return (em->face_index && index < em->bm->totface && index >= 0) ? em->face_index[index] : NULL; + BLI_assert((index >= 0) && (index < em->bm->totface)); + return em->face_index[index]; } void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode) @@ -1144,46 +1147,58 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index) * preference */ #define BM_SEARCH_MAXDIST_MIRR 0.00002f #define BM_CD_LAYER_ID "__mirror_index" -void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bool use_select) +/** + * \param em Editmesh. + * \param use_self Allow a vertex to point to its self (middle verts). + * \param use_select Restrict to selected verts. + * \param is_topo Use topology mirror. + * \param maxdist Distance for close point test. + * \param r_index Optional array to write into, as an alternative to a customdata layer (length of total verts). + */ +void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const bool use_self, const bool use_select, + /* extra args */ + const bool is_topo, float maxdist, int *r_index) { Mesh *me = (Mesh *)em->ob->data; BMesh *bm = em->bm; BMIter iter; BMVert *v; - bool topo = false; int cd_vmirr_offset; + int i; /* one or the other is used depending if topo is enabled */ struct BMBVHTree *tree = NULL; MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1}; - if (me && (me->editflag & ME_EDIT_MIRROR_TOPO)) { - topo = 1; - } - EDBM_index_arrays_ensure(em, BM_VERT); - em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID); - if (em->mirror_cdlayer == -1) { - BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID); - em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID); - } + if (r_index == NULL) { + const char *layer_id = BM_CD_LAYER_ID; + em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id); + if (em->mirror_cdlayer == -1) { + BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, layer_id); + em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id); + } - cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT, - em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT)); + cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT, + em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT)); - bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY; + bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY; + } BM_mesh_elem_index_ensure(bm, BM_VERT); - if (topo) { + if (is_topo) { ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true); } else { tree = BKE_bmbvh_new(em, 0, NULL, false); } - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { +#define VERT_INTPTR(_v, _i) r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset); + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + BLI_assert(BM_elem_index_get(v) == i); /* temporary for testing, check for selection */ if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) { @@ -1191,20 +1206,21 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bo } else { BMVert *v_mirr; - int *idx = BM_ELEM_CD_GET_VOID_P(v, cd_vmirr_offset); + int *idx = VERT_INTPTR(v, i); - if (topo) { - v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, BM_elem_index_get(v)); + if (is_topo) { + v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i); } else { float co[3] = {-v->co[0], v->co[1], v->co[2]}; - v_mirr = BKE_bmbvh_find_vert_closest(tree, co, BM_SEARCH_MAXDIST_MIRR); + v_mirr = BKE_bmbvh_find_vert_closest(tree, co, maxdist); } if (v_mirr && (use_self || (v_mirr != v))) { - *idx = BM_elem_index_get(v_mirr); - idx = BM_ELEM_CD_GET_VOID_P(v_mirr, cd_vmirr_offset); - *idx = BM_elem_index_get(v); + const int i_mirr = BM_elem_index_get(v_mirr); + *idx = i_mirr; + idx = VERT_INTPTR(v_mirr, i_mirr); + *idx = i; } else { *idx = -1; @@ -1213,8 +1229,9 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bo } +#undef VERT_INTPTR - if (topo) { + if (is_topo) { ED_mesh_mirrtopo_free(&mesh_topo_store); } else { @@ -1222,6 +1239,18 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bo } } +void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bool use_select) +{ + Mesh *me = (Mesh *)em->ob->data; + bool is_topo; + + is_topo = (me && (me->editflag & ME_EDIT_MIRROR_TOPO)); + + EDBM_verts_mirror_cache_begin_ex(em, use_self, use_select, + /* extra args */ + is_topo, BM_SEARCH_MAXDIST_MIRR, NULL); +} + BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v) { int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 74f1515fe74..8da953c4f84 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2905,9 +2905,9 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ - prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all Groups"); + prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All verts", "Clear Active Group"); + prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Verts", "Clear the active group"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 20edd3d32e7..527715cdbd3 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -220,7 +220,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( return OPERATOR_CANCELLED; } -static int screenshot_check(bContext *UNUSED(C), wmOperator *op) +static bool screenshot_check(bContext *UNUSED(C), wmOperator *op) { ScreenshotData *scd = op->customdata; return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 1ff7df3b041..181b32d58fc 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2145,7 +2145,7 @@ struct WPaintData { }; /* ensure we have data on wpaint start, add if needed */ -static int wpaint_ensure_data(bContext *C, wmOperator *op) +static bool wpaint_ensure_data(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); @@ -3390,6 +3390,10 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) vert_cache = gesture->userdata; } else { + if (wpaint_ensure_data(C, op) == FALSE) { + return OPERATOR_CANCELLED; + } + data.is_init = true; vert_cache = MEM_mallocN(sizeof(DMGradient_vertStore) * me->totvert, __func__); } diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 0cb0a3d6e5c..a2189f6237c 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -391,7 +391,7 @@ static const char *snd_ext_sound[] = { NULL }; -static int sound_mixdown_check(bContext *UNUSED(C), wmOperator *op) +static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op) { AUD_Container container = RNA_enum_get(op->ptr, "container"); diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index b20301cfc3b..9e045a39a0c 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -35,7 +35,6 @@ set(INC_SYS set(SRC buttons_context.c - buttons_header.c buttons_ops.c buttons_texture.c space_buttons.c diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c deleted file mode 100644 index f9742121e99..00000000000 --- a/source/blender/editors/space_buttons/buttons_header.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - * - * - * Contributor(s): Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/space_buttons/buttons_header.c - * \ingroup spbuttons - */ - - -#include <string.h> -#include <stdio.h> - -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" - -#include "BLF_translation.h" - -#include "BKE_context.h" -#include "BKE_modifier.h" -#include "BKE_paint.h" -#include "BKE_scene.h" - -#include "ED_buttons.h" -#include "ED_screen.h" -#include "ED_types.h" - -#include "DNA_brush_types.h" -#include "DNA_object_force.h" -#include "DNA_object_types.h" - -#include "UI_interface.h" -#include "UI_resources.h" -#include "UI_view2d.h" - -#include "buttons_intern.h" - - -#define B_CONTEXT_SWITCH 101 - -static void set_texture_context(const bContext *C, SpaceButs *sbuts) -{ - Scene *scene = CTX_data_scene(C); - - if (BKE_scene_use_new_shading_nodes(scene)) { - return; /* No texture context in new shading mode */ - } - - if ((sbuts->mainb == BCONTEXT_WORLD) && ED_texture_context_check_world(C)) { - sbuts->texture_context = SB_TEXC_WORLD; - } - else if ((sbuts->mainb == BCONTEXT_MATERIAL) && ED_texture_context_check_material(C)) { - sbuts->texture_context = SB_TEXC_MATERIAL; - } - else if ((sbuts->mainb == BCONTEXT_DATA) && ED_texture_context_check_lamp(C)) { - sbuts->texture_context = SB_TEXC_LAMP; - } - else if ((sbuts->mainb == BCONTEXT_PARTICLE) && ED_texture_context_check_particles(C)) { - sbuts->texture_context = SB_TEXC_PARTICLES; - } - else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && ED_texture_context_check_others(C)) { - sbuts->texture_context = SB_TEXC_OTHER; - } - /* Second pass: sbuts->mainbuser still contains the previous button context. - * Useful e.g. when we switch to material, no material present, add a material, switch to texture. - * See #35741. */ - else if ((sbuts->mainbuser == BCONTEXT_WORLD) && ED_texture_context_check_world(C)) { - sbuts->texture_context = SB_TEXC_WORLD; - } - else if ((sbuts->mainbuser == BCONTEXT_MATERIAL) && ED_texture_context_check_material(C)) { - sbuts->texture_context = SB_TEXC_MATERIAL; - } - else if ((sbuts->mainbuser == BCONTEXT_DATA) && ED_texture_context_check_lamp(C)) { - sbuts->texture_context = SB_TEXC_LAMP; - } - else if ((sbuts->mainbuser == BCONTEXT_PARTICLE) && ED_texture_context_check_particles(C)) { - sbuts->texture_context = SB_TEXC_PARTICLES; - } - else if ((ELEM(sbuts->mainbuser, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && ED_texture_context_check_others(C)) { - sbuts->texture_context = SB_TEXC_OTHER; - } - /* Else, just be sure that current context is valid! */ - else { - buttons_check_texture_context(C, sbuts); - } -} - -static void do_buttons_buttons(bContext *C, void *UNUSED(arg), int event) -{ - SpaceButs *sbuts = CTX_wm_space_buts(C); - - if (!sbuts) /* editor type switch */ - return; - - switch (event) { - case B_CONTEXT_SWITCH: - ED_area_tag_redraw(CTX_wm_area(C)); - - set_texture_context(C, sbuts); - - sbuts->preview = 1; - break; - } - - sbuts->mainbuser = sbuts->mainb; -} - -#define BUT_UNIT_X (UI_UNIT_X + 2 * U.pixelsize) - -void buttons_header_buttons(const bContext *C, ARegion *ar) -{ - SpaceButs *sbuts = CTX_wm_space_buts(C); - uiBlock *block; - uiBut *but; - int headery = ED_area_headersize(); - int xco, yco = 0.5f * (headery - UI_UNIT_Y); - - buttons_context_compute(C, sbuts); - - block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); - uiBlockSetHandleFunc(block, do_buttons_buttons, NULL); - - xco = ED_area_header_switchbutton(C, block, yco); - - uiBlockSetEmboss(block, UI_EMBOSS); - - xco -= UI_UNIT_X; - - /* Default panels */ - - uiBlockBeginAlign(block); - -#define BUTTON_HEADER_CTX(_ctx, _icon, _tip) \ - if (sbuts->pathflag & (1 << _ctx)) { \ - but = uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, _icon, xco += BUT_UNIT_X, yco, BUT_UNIT_X, UI_UNIT_Y, \ - &(sbuts->mainb), 0.0, (float)_ctx, 0, 0, TIP_(_tip)); \ - uiButClearFlag(but, UI_BUT_UNDO); \ - } (void)0 - - BUTTON_HEADER_CTX(BCONTEXT_RENDER, ICON_SCENE, N_("Render")); - BUTTON_HEADER_CTX(BCONTEXT_RENDER_LAYER, ICON_RENDERLAYERS, N_("Render Layers")); - BUTTON_HEADER_CTX(BCONTEXT_SCENE, ICON_SCENE_DATA, N_("Scene")); - BUTTON_HEADER_CTX(BCONTEXT_WORLD, ICON_WORLD, N_("World")); - BUTTON_HEADER_CTX(BCONTEXT_OBJECT, ICON_OBJECT_DATA, N_("Object")); - BUTTON_HEADER_CTX(BCONTEXT_CONSTRAINT, ICON_CONSTRAINT, N_("Object Constraints")); - BUTTON_HEADER_CTX(BCONTEXT_MODIFIER, ICON_MODIFIER, N_("Object Modifiers")); - BUTTON_HEADER_CTX(BCONTEXT_DATA, sbuts->dataicon, N_("Object Data")); - BUTTON_HEADER_CTX(BCONTEXT_BONE, ICON_BONE_DATA, N_("Bone")); - BUTTON_HEADER_CTX(BCONTEXT_BONE_CONSTRAINT, ICON_CONSTRAINT_BONE, N_("Bone Constraints")); - BUTTON_HEADER_CTX(BCONTEXT_MATERIAL, ICON_MATERIAL, N_("Material")); - BUTTON_HEADER_CTX(BCONTEXT_TEXTURE, ICON_TEXTURE, N_("Textures")); - BUTTON_HEADER_CTX(BCONTEXT_PARTICLE, ICON_PARTICLES, N_("Particles")); - BUTTON_HEADER_CTX(BCONTEXT_PHYSICS, ICON_PHYSICS, N_("Physics")); - -#undef BUTTON_HEADER_CTX - - xco += BUT_UNIT_X; - - uiBlockEndAlign(block); - - /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco + (UI_UNIT_X / 2), BLI_rctf_size_y(&ar->v2d.tot)); - - uiEndBlock(C, block); - uiDrawBlock(C, block); -} - - diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 55c9bf0dffd..f294729ae97 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -97,9 +97,6 @@ typedef struct ButsContextTexture { /* internal exports only */ -/* buttons_header.c */ -void buttons_header_buttons(const struct bContext *C, struct ARegion *ar); - /* buttons_context.c */ void buttons_context_compute(const struct bContext *C, struct SpaceButs *sbuts); int buttons_context(const struct bContext *C, const char *member, struct bContextDataResult *result); @@ -111,7 +108,6 @@ extern const char *buttons_context_dir[]; /* doc access */ /* buttons_texture.c */ void buttons_texture_context_compute(const struct bContext *C, struct SpaceButs *sbuts); -void buttons_check_texture_context(const struct bContext *C, struct SpaceButs *sbuts); /* buttons_ops.c */ void BUTTONS_OT_file_browse(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 0b1f244a1b5..51e740e539f 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -135,8 +135,7 @@ bool ED_texture_context_check_others(const bContext *C) return false; } -/* Only change texture context if current one is invalid! */ -void buttons_check_texture_context(const bContext *C, SpaceButs *sbuts) +static void set_texture_context(const bContext *C, SpaceButs *sbuts) { Scene *scene = CTX_data_scene(C); @@ -151,11 +150,27 @@ void buttons_check_texture_context(const bContext *C, SpaceButs *sbuts) bool valid_particles = ED_texture_context_check_particles(C); bool valid_others = ED_texture_context_check_others(C); - if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) || - ((sbuts->texture_context == SB_TEXC_MATERIAL) && !valid_material) || - ((sbuts->texture_context == SB_TEXC_LAMP) && !valid_lamp) || - ((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) || - ((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others)) + if ((sbuts->mainb == BCONTEXT_WORLD) && valid_world) { + sbuts->texture_context = SB_TEXC_WORLD; + } + else if ((sbuts->mainb == BCONTEXT_MATERIAL) && valid_material) { + sbuts->texture_context = SB_TEXC_MATERIAL; + } + else if ((sbuts->mainb == BCONTEXT_DATA) && valid_lamp) { + sbuts->texture_context = SB_TEXC_LAMP; + } + else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) { + sbuts->texture_context = SB_TEXC_PARTICLES; + } + else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && valid_others) { + sbuts->texture_context = SB_TEXC_OTHER; + } + /* Else, just be sure that current context is valid! */ + else if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) || + ((sbuts->texture_context == SB_TEXC_MATERIAL) && !valid_material) || + ((sbuts->texture_context == SB_TEXC_LAMP) && !valid_lamp) || + ((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) || + ((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others)) { if (valid_others) { sbuts->texture_context = SB_TEXC_OTHER; @@ -368,7 +383,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) Scene *scene = CTX_data_scene(C); ID *pinid = sbuts->pinid; - buttons_check_texture_context(C, sbuts); + set_texture_context(C, sbuts); if (!(BKE_scene_use_new_shading_nodes(scene) || (sbuts->texture_context == SB_TEXC_OTHER))) { if (ct) { diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 02b06e08eed..e6c6df416bf 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -87,7 +87,7 @@ static SpaceLink *buttons_new(const bContext *UNUSED(C)) BLI_addtail(&sbuts->regionbase, ar); ar->regiontype = RGN_TYPE_WINDOW; - + return (SpaceLink *)sbuts; } @@ -200,22 +200,17 @@ static void buttons_keymap(struct wmKeyConfig *keyconf) /* add handlers, stuff you only do once or on area/region changes */ static void buttons_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar) { - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); + ED_region_header_init(ar); } static void buttons_header_area_draw(const bContext *C, ARegion *ar) { - /* clear */ - UI_ThemeClearColor(ED_screen_area_active(C) ? TH_HEADER : TH_HEADERDESEL); - glClear(GL_COLOR_BUFFER_BIT); - - /* set view2d view matrix for scrolling (without scrollers) */ - UI_view2d_view_ortho(&ar->v2d); - - buttons_header_buttons(C, ar); + SpaceButs *sbuts = CTX_wm_space_buts(C); + + /* Needed for RNA to get the good values! */ + buttons_context_compute(C, sbuts); - /* restore view matrix? */ - UI_view2d_view_restore(C); + ED_region_header(C, ar); } /* draw a certain button set only if properties area is currently diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 60420649093..986b71abc8a 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -807,7 +807,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_PATH) - if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */ + if (ELEM4(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */ return TRUE; return FALSE; diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index e5c6a839380..240106d37d5 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -105,8 +105,8 @@ float file_string_width(const char *str); float file_font_pointsize(void); void file_change_dir(bContext *C, int checkdir); int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file); -void autocomplete_directory(struct bContext *C, char *str, void *arg_v); -void autocomplete_file(struct bContext *C, char *str, void *arg_v); +bool autocomplete_directory(struct bContext *C, char *str, void *arg_v); +bool autocomplete_file(struct bContext *C, char *str, void *arg_v); /* file_panels.c */ void file_panels_register(struct ARegionType *art); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 25d865d857b..a31af851575 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -609,6 +609,7 @@ void file_change_dir(bContext *C, int checkdir) folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + file_draw_check_cb(C, NULL, NULL); } } @@ -637,9 +638,10 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche return match; } -void autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) +bool autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) { SpaceFile *sfile = CTX_wm_space_file(C); + bool change = false; /* search if str matches the beginning of name */ if (str[0] && sfile->files) { @@ -674,20 +676,25 @@ void autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) } closedir(dir); - autocomplete_end(autocpl, str); - if (BLI_exists(str)) { - BLI_add_slash(str); - } - else { - BLI_strncpy(sfile->params->dir, str, sizeof(sfile->params->dir)); + change = autocomplete_end(autocpl, str); + if (change) { + if (BLI_exists(str)) { + BLI_add_slash(str); + } + else { + BLI_strncpy(sfile->params->dir, str, sizeof(sfile->params->dir)); + } } } } + + return change; } -void autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) +bool autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) { SpaceFile *sfile = CTX_wm_space_file(C); + bool change = false; /* search if str matches the beginning of name */ if (str[0] && sfile->files) { @@ -701,8 +708,9 @@ void autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) autocomplete_do_name(autocpl, file->relname); } } - autocomplete_end(autocpl, str); + change = autocomplete_end(autocpl, str); } + return change; } void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 8272222e4c2..0a2bd2aad81 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1441,7 +1441,7 @@ static int image_save_as_exec(bContext *C, wmOperator *op) } -static int image_save_as_check(bContext *UNUSED(C), wmOperator *op) +static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op) { ImageFormatData *imf = op->customdata; return WM_operator_filesel_ensure_ext_imtype(op, imf); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 164382c300d..159cc74af56 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -425,8 +425,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) if (items == 0) { BKE_report(op->reports, RPT_ERROR, - "No active track(s) to add strip to. " - "Select an existing track or add one before trying again"); + "No active track(s) to add strip to, select an existing track or add one before trying again"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 0d875acb040..2fa901a2f28 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -773,8 +773,12 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float #define B_VGRP_PNL_COPY 1 #define B_VGRP_PNL_NORMALIZE 2 -#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */ -#define B_VGRP_PNL_COPY_SINGLE 16384 /* or greater */ +#define B_VGRP_PNL_TOGGLE_USE_ALL 4 +#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */ +#define B_VGRP_PNL_DELETE_SINGLE 4096 /* or greater */ +#define B_VGRP_PNL_COPY_SINGLE 8192 /* or greater */ +#define B_VGRP_PNL_ACTIVE 16384 /* or greater */ + static MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index) { @@ -904,6 +908,18 @@ static void vgroup_adjust_active(Object *ob, int def_nr) } } +static void vgroup_remove_weight(Object *ob, const int def_nr) +{ + MDeformVert *dvert_act; + MDeformWeight *dw; + + dvert_act = ED_mesh_active_dvert_get_only(ob); + + dw = defvert_find_index(dvert_act, def_nr); + defvert_remove_group(dvert_act, dw); + +} + static void vgroup_copy_active_to_sel(Object *ob) { Mesh *me = ob->data; @@ -1064,9 +1080,15 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) else if (event == B_VGRP_PNL_COPY) { vgroup_copy_active_to_sel(ob); } + else if (event >= B_VGRP_PNL_ACTIVE) { + ob->actdef = event - B_VGRP_PNL_ACTIVE + 1; + } else if (event >= B_VGRP_PNL_COPY_SINGLE) { vgroup_copy_active_to_sel_single(ob, event - B_VGRP_PNL_COPY_SINGLE); } + else if (event >= B_VGRP_PNL_DELETE_SINGLE) { + vgroup_remove_weight(ob, event - B_VGRP_PNL_DELETE_SINGLE); + } else if (event >= B_VGRP_PNL_EDIT_SINGLE) { vgroup_adjust_active(ob, event - B_VGRP_PNL_EDIT_SINGLE); } @@ -1111,6 +1133,9 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) if (dv && dv->totweight) { uiLayout *col; + uiLayout *row; + uiLayout *box; + uiBut *but; bDeformGroup *dg; unsigned int i; int subset_count, vgroup_tot; @@ -1119,22 +1144,50 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) int yco = 0; uiBlockSetHandleFunc(block, do_view3d_vgroup_buttons, NULL); + box = uiLayoutBox(pa->layout); - col = uiLayoutColumn(pa->layout, FALSE); - block = uiLayoutAbsoluteBlock(col); - - uiBlockBeginAlign(block); + col = uiLayoutColumn(box, true); vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count); for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) { if (vgroup_validmap[i]) { MDeformWeight *dw = defvert_find_index(dv, i); if (dw) { - uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, dg->name, 0, yco, 180, 20, + int x, xco = 0; + row = uiLayoutRow(col, true); + (void)row; + + uiBlockSetEmboss(block, UI_EMBOSSN); + but = uiDefBut(block, BUT, B_VGRP_PNL_ACTIVE + i, dg->name, + xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, + NULL, 0.0, 1.0, 1, 3, ""); + uiButSetFlag(but, UI_TEXT_LEFT); + + if (ob->actdef != i + 1) { + uiButSetFlag(but, UI_BUT_INACTIVE); + } + xco += x; + + //uiBlockSetEmboss(block, UI_EMBOSS); + + but = uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, "", + xco, yco, (x = UI_UNIT_X * 4), UI_UNIT_Y, &dw->weight, 0.0, 1.0, 1, 3, ""); - uiDefBut(block, BUT, B_VGRP_PNL_COPY_SINGLE + i, "C", 180, yco, 20, 20, - NULL, 0, 0, 0, 0, TIP_("Copy this group's weight to other selected verts")); - yco -= 20; + uiButSetFlag(but, UI_TEXT_LEFT); + xco += x; + + uiDefIconBut(block, BUT, B_VGRP_PNL_COPY_SINGLE + i, ICON_PASTEDOWN, + xco, yco, (x = UI_UNIT_X), UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Copy this group's weight to other selected verts")); + xco += x; + + uiDefIconBut(block, BUT, B_VGRP_PNL_DELETE_SINGLE + i, ICON_X, + xco, yco, (x = UI_UNIT_X), UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Delete this weight from the vertex")); + xco += x; + + yco -= UI_UNIT_Y; + (void)xco; } } } @@ -1142,13 +1195,16 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) yco -= 2; - uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefBut(block, BUT, B_VGRP_PNL_NORMALIZE, IFACE_("Normalize"), 0, yco, 100, 20, + uiBlockSetEmboss(block, UI_EMBOSS); + col = uiLayoutColumn(pa->layout, true); + row = uiLayoutRow(col, true); + + uiDefBut(block, BUT, B_VGRP_PNL_NORMALIZE, IFACE_("Normalize"), + 0, yco, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Normalize active vertex weights")); - uiDefBut(block, BUT, B_VGRP_PNL_COPY, IFACE_("Copy"), 100, yco, 100, 20, + uiDefBut(block, BUT, B_VGRP_PNL_COPY, IFACE_("Copy"), + UI_UNIT_X * 5, yco, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Copy active vertex to other selected verts")); - uiBlockEndAlign(block); } } diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 9e310c84bd0..180686b4b82 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -237,7 +237,7 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const flo foreachScreenFace_userData *data = userData; BMFace *efa = EDBM_face_at_index(data->vc.em, index); - if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { float screen_co[2]; if (ED_view3d_project_float_object(data->vc.ar, cent, screen_co, data->clip_flag) == V3D_PROJ_RET_OK) { data->func(data->userData, efa, screen_co, index); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index bba151f1a5e..c119fe24210 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1166,6 +1166,26 @@ static bool selectbuffer_has_bones(const unsigned int *buffer, const unsigned in return false; } +/* utility function for mixed_bones_object_selectbuffer */ +static short selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const short hits15) +{ + return hits15; +} + +static short selectbuffer_ret_hits_9(unsigned int *buffer, const short hits15, const short hits9) +{ + const int offs = 4 * hits15; + memcpy(buffer, buffer + offs, 4 * offs); + return hits9; +} + +static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, const short hits9, const short hits5) +{ + const int offs = 4 * hits15 + 4 * hits9; + memcpy(buffer, buffer + offs, 4 * offs); + return hits5; +} + /* we want a select buffer with bones, if there are... */ /* so check three selection levels and compare */ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2]) @@ -1177,48 +1197,39 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14); hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect); - if (hits15 > 0) { + if (hits15 == 1) { + return selectbuffer_ret_hits_15(buffer, hits15); + } + else if (hits15 > 0) { has_bones15 = selectbuffer_has_bones(buffer, hits15); offs = 4 * hits15; BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9); hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect); - if (hits9 > 0) { + if (hits9 == 1) { + return selectbuffer_ret_hits_9(buffer, hits15, hits9); + } + else if (hits9 > 0) { has_bones9 = selectbuffer_has_bones(buffer + offs, hits9); offs += 4 * hits9; BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5); hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect); - if (hits5 > 0) { + if (hits5 == 1) { + return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + } + else if (hits5 > 0) { has_bones5 = selectbuffer_has_bones(buffer + offs, hits5); } } + + if (has_bones5) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + else if (has_bones9) return selectbuffer_ret_hits_9(buffer, hits15, hits9); + else if (has_bones15) return selectbuffer_ret_hits_15(buffer, hits15); - if (has_bones5) { - offs = 4 * hits15 + 4 * hits9; - memcpy(buffer, buffer + offs, 4 * offs); - return hits5; - } - if (has_bones9) { - offs = 4 * hits15; - memcpy(buffer, buffer + offs, 4 * offs); - return hits9; - } - if (has_bones15) { - return hits15; - } - - if (hits5 > 0) { - offs = 4 * hits15 + 4 * hits9; - memcpy(buffer, buffer + offs, 4 * offs); - return hits5; - } - if (hits9 > 0) { - offs = 4 * hits15; - memcpy(buffer, buffer + offs, 4 * offs); - return hits9; - } - return hits15; + if (hits5 > 0) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + else if (hits9 > 0) return selectbuffer_ret_hits_9(buffer, hits15, hits9); + else return selectbuffer_ret_hits_15(buffer, hits15); } return 0; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d8f763c6a54..ac5727a116c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -196,7 +196,7 @@ static void sort_trans_data(TransInfo *t) /* distance calculated from not-selected vertex to nearest selected vertex * warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */ -static void set_prop_dist(TransInfo *t, short with_dist) +static void set_prop_dist(TransInfo *t, const bool with_dist) { TransData *tob; int a; @@ -216,12 +216,9 @@ static void set_prop_dist(TransInfo *t, short with_dist) if (td->flag & TD_SELECTED) { sub_v3_v3v3(vec, tob->center, td->center); mul_m3_v3(tob->mtx, vec); - dist = normalize_v3(vec); - if (tob->rdist == -1.0f) { - tob->rdist = dist; - } - else if (dist < tob->rdist) { - tob->rdist = dist; + dist = len_squared_v3(vec); + if ((tob->rdist == -1.0f) || (dist < (tob->rdist * tob->rdist))) { + tob->rdist = sqrtf(dist); } } else { @@ -1778,90 +1775,125 @@ void flushTransParticles(TransInfo *t) /* ********************* mesh ****************** */ -/* I did this wrong, it should be a breadth-first search - * but instead it's a depth-first search, fudged - * to report shortest distances. I have no idea how fast - * or slow this is. */ -static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[3][3], float *dists) +static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, + float *dists, const float *dists_prev, + float mtx[3][3]) { - BMVert **queue = NULL; - float *dqueue = NULL; - int *tots = MEM_callocN(sizeof(int) * em->bm->totvert, "tots editmesh_set_connectivity_distance"); - BLI_array_declare(queue); - BLI_array_declare(dqueue); - SmallHash svisit, *visit = &svisit; - BMVert *v; - BMIter viter; - int i, start; - - fill_vn_fl(dists, em->bm->totvert, FLT_MAX); + if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && + (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) + { + const int i = BM_elem_index_get(v); + const int i_other = BM_elem_index_get(v_other); + float vec[3]; + float dist_other; + sub_v3_v3v3(vec, v->co, v_other->co); + mul_m3_v3(mtx, vec); + + dist_other = dists_prev[i] + len_v3(vec); + if (dist_other < dists[i_other]) { + dists[i_other] = dist_other; + return true; + } + } - BM_mesh_elem_index_ensure(em->bm, BM_VERT); + return false; +} - BLI_smallhash_init(visit); +static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists) +{ + /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ + float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__); - BM_ITER_MESH (v, &viter, em->bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) - continue; - - - BLI_smallhash_insert(visit, (uintptr_t)v, NULL); - BLI_array_append(queue, v); - BLI_array_append(dqueue, 0.0f); - dists[BM_elem_index_get(v)] = 0.0f; + BMVert **queue = MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__); + STACK_DECLARE(queue); + + /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ + BMVert **queue_next = MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__); + STACK_DECLARE(queue_next); + + STACK_INIT(queue); + STACK_INIT(queue_next); + + { + BMIter viter; + BMVert *v; + int i; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + BM_elem_index_set(v, i); /* set_inline */ + BM_elem_flag_disable(v, BM_ELEM_TAG); + + if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + dists[i] = FLT_MAX; + } + else { + STACK_PUSH(queue, v); + + dists[i] = 0.0f; + } + } } - - start = 0; - while (start < BLI_array_count(queue)) { - BMIter eiter; - BMEdge *e; - BMVert *v3, *v2; - float d, vec[3]; - - v2 = queue[start]; - d = dqueue[start]; - - BM_ITER_ELEM (e, &eiter, v2, BM_EDGES_OF_VERT) { - float d2; - v3 = BM_edge_other_vert(e, v2); - - if (BM_elem_flag_test(v3, BM_ELEM_SELECT) || BM_elem_flag_test(v3, BM_ELEM_HIDDEN)) - continue; - - sub_v3_v3v3(vec, v2->co, v3->co); - mul_m3_v3(mtx, vec); - - d2 = d + len_v3(vec); - - if (dists[BM_elem_index_get(v3)] != FLT_MAX) - dists[BM_elem_index_get(v3)] = min_ff(d2, dists[BM_elem_index_get(v3)]); - else - dists[BM_elem_index_get(v3)] = d2; - - tots[BM_elem_index_get(v3)] = 1; - if (BLI_smallhash_haskey(visit, (uintptr_t)v3)) - continue; - - BLI_smallhash_insert(visit, (uintptr_t)v3, NULL); + do { + BMVert *v; + unsigned int i; + + memcpy(dists_prev, dists, sizeof(float) * bm->totvert); + + while ((v = STACK_POP(queue))) { + BMIter iter; + BMEdge *e; + BMLoop *l; + + /* connected edge-verts */ + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { + BM_elem_flag_enable(v_other, BM_ELEM_TAG); + STACK_PUSH(queue_next, v_other); + } + } + } + } - BLI_array_append(queue, v3); - BLI_array_append(dqueue, d2); + /* connected face-verts (excluding adjacent verts) */ + BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len > 3)) { + BMLoop *l_end = l->prev; + l = l->next->next; + do { + BMVert *v_other = l->v; + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { + BM_elem_flag_enable(v_other, BM_ELEM_TAG); + STACK_PUSH(queue_next, v_other); + } + } + } while ((l = l->next) != l_end); + } + } } - - start++; - } - BLI_smallhash_release(visit); - - for (i = 0; i < em->bm->totvert; i++) { - if (tots[i]) - dists[i] /= (float)tots[i]; - } - - BLI_array_free(queue); - BLI_array_free(dqueue); - MEM_freeN(tots); + /* clear for the next loop */ + for (i = 0; i < STACK_SIZE(queue_next); i++) { + BM_elem_flag_disable(queue_next[i], BM_ELEM_TAG); + } + + STACK_SWAP(queue, queue_next); + + /* none should be tagged now since 'queue_next' is empty */ + BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0); + + } while (STACK_SIZE(queue)); + + STACK_FREE(queue); + STACK_FREE(queue_next); + + MEM_freeN(queue); + MEM_freeN(queue_next); + MEM_freeN(dists_prev); } static BMElem *bm_vert_single_select_face(BMVert *eve) @@ -2099,7 +2131,7 @@ static void createTransEditVerts(TransInfo *t) pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); if (propmode & T_PROP_CONNECTED) { - editmesh_set_connectivity_distance(em, mtx, dists); + editmesh_set_connectivity_distance(em->bm, mtx, dists); } /* detect CrazySpace [tm] */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 917335e2068..386eda7dd38 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2113,7 +2113,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo hitlen = hit.efa->len; } else if (selectmode == UV_SELECT_ISLAND) { - uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_edge(scene, ima, em, co, &hit); if (hit.efa == NULL) { return OPERATOR_CANCELLED; @@ -2378,7 +2378,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent RNA_float_get_array(op->ptr, "location", co); } - uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_edge(scene, ima, em, co, &hit); hit_p = &hit; } diff --git a/source/blender/freestyle/intern/application/AppCanvas.cpp b/source/blender/freestyle/intern/application/AppCanvas.cpp index e1f300b3ce0..f621f45ff77 100644 --- a/source/blender/freestyle/intern/application/AppCanvas.cpp +++ b/source/blender/freestyle/intern/application/AppCanvas.cpp @@ -136,8 +136,8 @@ void AppCanvas::readColorPixels(int x, int y, int w, int h, RGBImage& oImage) co int ymin = border().getMin().y(); int xmax = border().getMax().x(); int ymax = border().getMax().y(); - int rectx = _pass_z.width; - int recty = _pass_z.height; + int rectx = _pass_diffuse.width; + int recty = _pass_diffuse.height; float xfac = ((float)rectx) / ((float)(xmax - xmin)); float yfac = ((float)recty) / ((float)(ymax - ymin)); #if 0 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index a846ac697f0..e0c5cd5608e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -360,6 +360,12 @@ typedef struct bAddon { IDProperty *prop; /* User-Defined Properties on this Addon (for storing preferences) */ } bAddon; +typedef struct bPathCompare { + struct bPathCompare *next, *prev; + char path[768]; /* FILE_MAXDIR */ + char flag, pad[7]; +} bPathCompare; + typedef struct SolidLight { int flag, pad; float col[4], spec[4], vec[4]; @@ -412,6 +418,7 @@ typedef struct UserDef { struct ListBase keymaps DNA_DEPRECATED; /* deprecated in favor of user_keymaps */ struct ListBase user_keymaps; struct ListBase addons; + struct ListBase autoexec_paths; char keyconfigstr[64]; short undosteps; @@ -522,7 +529,12 @@ typedef enum eUserPref_Flag { USER_TXT_TABSTOSPACES_DISABLE = (1 << 25), USER_TOOLTIPS_PYTHON = (1 << 26), } eUserPref_Flag; - + +/* flag */ +typedef enum ePathCompare_Flag { + USER_PATHCMP_GLOB = (1 << 0), +} ePathCompare_Flag; + /* helper macro for checking frame clamping */ #define FRAMENUMBER_MIN_CLAMP(cfra) { \ if ((U.flag & USER_NONEGFRAMES) && (cfra < 0)) \ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 36da4e3508c..4513694e59d 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -138,6 +138,25 @@ EnumPropertyItem clip_editor_mode_items[] = { }; /* Actually populated dynamically trough a function, but helps for context-less access (e.g. doc, i18n...). */ +static EnumPropertyItem buttons_context_items[] = { + {BCONTEXT_SCENE, "SCENE", ICON_SCENE_DATA, "Scene", "Scene"}, + {BCONTEXT_RENDER, "RENDER", ICON_SCENE, "Render", "Render"}, + {BCONTEXT_RENDER_LAYER, "RENDER_LAYER", ICON_RENDERLAYERS, "Render Layers", "Render layers"}, + {BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"}, + {BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"}, + {BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Object constraints"}, + {BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Object modifiers"}, + {BCONTEXT_DATA, "DATA", ICON_NONE, "Data", "Object data"}, + {BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"}, + {BCONTEXT_BONE_CONSTRAINT, "BONE_CONSTRAINT", ICON_CONSTRAINT, "Bone Constraints", "Bone constraints"}, + {BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"}, + {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"}, + {BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"}, + {BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"}, + {0, NULL, 0, NULL, NULL} +}; + +/* Actually populated dynamically trough a function, but helps for context-less access (e.g. doc, i18n...). */ static EnumPropertyItem buttons_texture_context_items[] = { {SB_TEXC_MATERIAL, "MATERIAL", ICON_MATERIAL, "", "Show material textures"}, {SB_TEXC_WORLD, "WORLD", ICON_WORLD, "", "Show world textures"}, @@ -831,6 +850,76 @@ static void rna_SpaceProperties_context_set(PointerRNA *ptr, int value) sbuts->mainbuser = value; } +static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *C, PointerRNA *ptr, + PropertyRNA *UNUSED(prop), int *free) +{ + SpaceButs *sbuts = (SpaceButs *)(ptr->data); + EnumPropertyItem *item = NULL; + int totitem = 0; + + if (sbuts->pathflag & (1 << BCONTEXT_RENDER)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_RENDER); + } + + if (sbuts->pathflag & (1 << BCONTEXT_RENDER_LAYER)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_RENDER_LAYER); + } + + if (sbuts->pathflag & (1 << BCONTEXT_SCENE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_SCENE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_WORLD)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORLD); + } + + if (sbuts->pathflag & (1 << BCONTEXT_OBJECT)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_OBJECT); + } + + if (sbuts->pathflag & (1 << BCONTEXT_CONSTRAINT)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_CONSTRAINT); + } + + if (sbuts->pathflag & (1 << BCONTEXT_MODIFIER)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_MODIFIER); + } + + if (sbuts->pathflag & (1 << BCONTEXT_DATA)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_DATA); + (item + totitem - 1)->icon = sbuts->dataicon; + } + + if (sbuts->pathflag & (1 << BCONTEXT_BONE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_BONE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_BONE_CONSTRAINT)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_BONE_CONSTRAINT); + } + + if (sbuts->pathflag & (1 << BCONTEXT_MATERIAL)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_MATERIAL); + } + + if (sbuts->pathflag & (1 << BCONTEXT_TEXTURE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_TEXTURE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_PARTICLE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_PARTICLE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_PHYSICS)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_PHYSICS); + } + + RNA_enum_item_end(&item, &totitem); + *free = 1; + + return item; +} + static void rna_SpaceProperties_align_set(PointerRNA *ptr, int value) { SpaceButs *sbuts = (SpaceButs *)(ptr->data); @@ -2068,24 +2157,6 @@ static void rna_def_space_buttons(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static EnumPropertyItem buttons_context_items[] = { - {BCONTEXT_SCENE, "SCENE", ICON_SCENE, "Scene", "Scene"}, - {BCONTEXT_RENDER, "RENDER", ICON_SCENE_DATA, "Render", "Render"}, - {BCONTEXT_RENDER_LAYER, "RENDER_LAYER", ICON_RENDERLAYERS, "Render Layers", "Render Layers"}, - {BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"}, - {BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"}, - {BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Constraints"}, - {BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Modifiers"}, - {BCONTEXT_DATA, "DATA", 0, "Data", "Data"}, - {BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"}, - {BCONTEXT_BONE_CONSTRAINT, "BONE_CONSTRAINT", ICON_CONSTRAINT, "Bone Constraints", "Bone Constraints"}, - {BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"}, - {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"}, - {BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"}, - {BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"}, - {0, NULL, 0, NULL, NULL} - }; - static EnumPropertyItem align_items[] = { {BUT_HORIZONTAL, "HORIZONTAL", 0, "Horizontal", ""}, {BUT_VERTICAL, "VERTICAL", 0, "Vertical", ""}, @@ -2099,7 +2170,7 @@ static void rna_def_space_buttons(BlenderRNA *brna) prop = RNA_def_property(srna, "context", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mainb"); RNA_def_property_enum_items(prop, buttons_context_items); - RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_context_set", NULL); + RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_context_set", "rna_SpaceProperties_context_itemf"); RNA_def_property_ui_text(prop, "Context", "Type of active data to display and edit"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 347c57f9044..f34366a23c7 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -339,9 +339,9 @@ static bAddon *rna_userdef_addon_new(void) return bext; } -static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *bext_ptr) +static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *path_cmp_ptr) { - bAddon *bext = bext_ptr->data; + bAddon *bext = path_cmp_ptr->data; if (BLI_findindex(&U.addons, bext) == -1) { BKE_report(reports, RPT_ERROR, "Addon is no longer valid"); return; @@ -353,7 +353,26 @@ static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *bext_ptr) } BLI_freelinkN(&U.addons, bext); - RNA_POINTER_INVALIDATE(bext_ptr); + RNA_POINTER_INVALIDATE(path_cmp_ptr); +} + +static bPathCompare *rna_userdef_pathcompare_new(void) +{ + bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); + BLI_addtail(&U.autoexec_paths, path_cmp); + return path_cmp; +} + +static void rna_userdef_pathcompare_remove(ReportList *reports, PointerRNA *path_cmp_ptr) +{ + bPathCompare *path_cmp = path_cmp_ptr->data; + if (BLI_findindex(&U.autoexec_paths, path_cmp) == -1) { + BKE_report(reports, RPT_ERROR, "Addon is no longer valid"); + return; + } + + BLI_freelinkN(&U.autoexec_paths, path_cmp); + RNA_POINTER_INVALIDATE(path_cmp_ptr); } static void rna_userdef_temp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) @@ -2733,6 +2752,25 @@ static void rna_def_userdef_addon(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Addon_preferences_get", NULL, NULL, NULL); } +static void rna_def_userdef_pathcompare(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "PathCompare", NULL); + RNA_def_struct_sdna(srna, "bPathCompare"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Path Compare", "Match paths against this value"); + + prop = RNA_def_property(srna, "path", PROP_STRING, PROP_DIRPATH); + RNA_def_property_ui_text(prop, "Path", ""); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "use_glob", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_PATHCMP_GLOB); + RNA_def_property_ui_text(prop, "Use Wildcard", "Enable wildcard globbing"); +} + static void rna_def_userdef_addon_pref(BlenderRNA *brna) { StructRNA *srna; @@ -4027,6 +4065,32 @@ static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cpro RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } +static void rna_def_userdef_autoexec_path_collection(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "PathCompareCollection"); + srna = RNA_def_struct(brna, "PathCompareCollection", NULL); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Paths Compare", "Collection of paths"); + + func = RNA_def_function(srna, "new", "rna_userdef_pathcompare_new"); + RNA_def_function_flag(func, FUNC_NO_SELF); + RNA_def_function_ui_description(func, "Add a new addon"); + /* return type */ + parm = RNA_def_pointer(func, "pathcmp", "PathCompare", "", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_userdef_pathcompare_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove path"); + parm = RNA_def_pointer(func, "pathcmp", "PathCompare", "", ""); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); +} + void RNA_def_userdef(BlenderRNA *brna) { StructRNA *srna; @@ -4074,6 +4138,11 @@ void RNA_def_userdef(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Addon", ""); rna_def_userdef_addon_collection(brna, prop); + prop = RNA_def_property(srna, "autoexec_paths", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "autoexec_paths", NULL); + RNA_def_property_struct_type(prop, "PathCompare"); + RNA_def_property_ui_text(prop, "Autoexec Paths", ""); + rna_def_userdef_autoexec_path_collection(brna, prop); /* nested structs */ prop = RNA_def_property(srna, "view", PROP_POINTER, PROP_NONE); @@ -4113,6 +4182,7 @@ void RNA_def_userdef(BlenderRNA *brna) rna_def_userdef_system(brna); rna_def_userdef_addon(brna); rna_def_userdef_addon_pref(brna); + rna_def_userdef_pathcompare(brna); } diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 6bf3beec57b..b70ab7c15f2 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -955,7 +955,7 @@ static int operator_execute(bContext *C, wmOperator *op) } /* same as execute() but no return value */ -static int operator_check(bContext *C, wmOperator *op) +static bool operator_check(bContext *C, wmOperator *op) { extern FunctionRNA rna_Operator_check_func; @@ -963,7 +963,7 @@ static int operator_check(bContext *C, wmOperator *op) ParameterList list; FunctionRNA *func; void *ret; - int result; + bool result; RNA_pointer_create(NULL, op->type->ext.srna, op, &opr); func = &rna_Operator_check_func; /* RNA_struct_find_function(&opr, "check"); */ @@ -973,7 +973,7 @@ static int operator_check(bContext *C, wmOperator *op) op->type->ext.call(C, &opr, func, &list); RNA_parameter_get_lookup(&list, "result", &ret); - result = *(int *)ret; + result = (*(int *)ret) != 0; RNA_parameter_list_free(&list); diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index d877932b81d..e37fc56d08c 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -49,7 +49,7 @@ #include "DNA_object_types.h" -static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Object *UNUSED(ob)) +static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd) { DerivedMesh *result; BMesh *bm; @@ -97,7 +97,8 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj result = CDDM_from_bmesh(bm, TRUE); BM_mesh_free(bm); - + + result->dirty |= DM_DIRTY_NORMALS; return result; } @@ -119,25 +120,16 @@ static void copyData(ModifierData *md, ModifierData *target) temd->flags = emd->flags; } -static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, - Object *ob, DerivedMesh *dm) -{ - if (!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))) - return dm; - - return doEdgeSplit(dm, emd, ob); -} - -static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, +static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), DerivedMesh *dm, ModifierApplyFlag UNUSED(flag)) { DerivedMesh *result; EdgeSplitModifierData *emd = (EdgeSplitModifierData *) md; - result = edgesplitModifier_do(emd, ob, derivedData); + if (!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))) + return dm; - if (result != derivedData) - result->dirty |= DM_DIRTY_NORMALS; + result = doEdgeSplit(dm, emd); return result; } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 189c30b02e8..72b54e2f1f7 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -112,6 +112,7 @@ bool WM_is_draw_triple(struct wmWindow *win); /* files */ +void WM_file_autoexec_init(const char *filepath); void WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports); void WM_autosave_init(struct wmWindowManager *wm); void WM_recover_last_session(struct bContext *C, struct ReportList *reports); @@ -193,7 +194,7 @@ int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const str int WM_operator_confirm (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); /* invoke callback, file selector "filepath" unset + exec */ int WM_operator_filesel (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); -int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format); +bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format); /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); /* invoke callback, exec + redo popup */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index cb060077166..cd3899897a1 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -531,7 +531,7 @@ typedef struct wmOperatorType { * is changed. It can correct its own properties or report errors for * invalid settings in exceptional cases. * Boolean return value, True denotes a change has been made and to redraw */ - int (*check)(struct bContext *, struct wmOperator *); + bool (*check)(struct bContext *, struct wmOperator *); /* for modal temporary operators, initially invoke is called. then * any further events are handled in modal. if the operation is diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index b6aecf120cc..f4b50667b2f 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -70,6 +70,7 @@ #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" +#include "BKE_autoexec.h" #include "BKE_blender.h" #include "BKE_context.h" #include "BKE_depsgraph.h" @@ -364,6 +365,21 @@ static int wm_read_exotic(Scene *UNUSED(scene), const char *name) return retval; } +void WM_file_autoexec_init(const char *filepath) +{ + if (G.f & G_SCRIPT_OVERRIDE_PREF) { + return; + } + + if (G.f & G_SCRIPT_AUTOEXEC) { + char path[FILE_MAX]; + BLI_split_dir_part(filepath, path, sizeof(path)); + if (BKE_autoexec_match(path)) { + G.f &= ~G_SCRIPT_AUTOEXEC; + } + } +} + void WM_file_read(bContext *C, const char *filepath, ReportList *reports) { int retval; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 3d4bd2a1bc6..e71be6052d0 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -60,6 +60,7 @@ #include "BLO_readfile.h" +#include "BKE_autoexec.h" #include "BKE_blender.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -1038,7 +1039,7 @@ int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *UNUSED(event } } -int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format) +bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format) { PropertyRNA *prop; char filepath[FILE_MAX]; @@ -1868,6 +1869,47 @@ static void WM_OT_save_homefile(wmOperatorType *ot) ot->poll = WM_operator_winactive; } +static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); + BLI_addtail(&U.autoexec_paths, path_cmp); + return OPERATOR_FINISHED; +} + +static void WM_OT_userpref_autoexec_path_add(wmOperatorType *ot) +{ + ot->name = "Add Autoexec Path"; + ot->idname = "WM_OT_userpref_autoexec_path_add"; + + ot->exec = wm_userpref_autoexec_add_exec; + ot->poll = WM_operator_winactive; + + ot->flag = OPTYPE_INTERNAL; +} + +static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) +{ + const int index = RNA_int_get(op->ptr, "index"); + bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); + if (path_cmp) { + BLI_freelinkN(&U.autoexec_paths, path_cmp); + } + return OPERATOR_FINISHED; +} + +static void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot) +{ + ot->name = "Remove Autoexec Path"; + ot->idname = "WM_OT_userpref_autoexec_path_remove"; + + ot->exec = wm_userpref_autoexec_remove_exec; + ot->poll = WM_operator_winactive; + + ot->flag = OPTYPE_INTERNAL; + + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); +} + static void WM_OT_save_userpref(wmOperatorType *ot) { ot->name = "Save User Settings"; @@ -1916,6 +1958,12 @@ static void WM_OT_read_factory_settings(wmOperatorType *ot) /* *************** open file **************** */ +/* currently fits in a pointer */ +struct FileRuntime { + bool is_untrusted; +}; + + static void open_set_load_ui(wmOperator *op, bool use_prefs) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "load_ui"); @@ -1960,6 +2008,7 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U RNA_string_set(op->ptr, "filepath", openname); open_set_load_ui(op, true); open_set_use_scripts(op, true); + op->customdata = NULL; WM_event_add_fileselect(C, op); @@ -1990,11 +2039,65 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op) /* do it before for now, but is this correct with multiple windows? */ WM_event_add_notifier(C, NC_WINDOW, NULL); + /* autoexec is already set correctly for invoke() for exec() though we need to initialize */ + if (!RNA_struct_property_is_set(op->ptr, "use_scripts")) { + WM_file_autoexec_init(path); + } WM_file_read(C, path, op->reports); - + return OPERATOR_FINISHED; } +static bool wm_open_mainfile_check(bContext *UNUSED(C), wmOperator *op) +{ + struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts"); + bool is_untrusted = false; + char path[FILE_MAX]; + char *lslash; + + RNA_string_get(op->ptr, "filepath", path); + + /* get the dir */ + lslash = (char *)BLI_last_slash(path); + if (lslash) *(lslash + 1) = '\0'; + + if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { + if (BKE_autoexec_match(path) == true) { + RNA_property_boolean_set(op->ptr, prop, false); + is_untrusted = true; + } + } + + if (file_info) { + file_info->is_untrusted = is_untrusted; + } + + return is_untrusted; +} + +static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op) +{ + struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; + uiLayout *layout = op->layout; + uiLayout *col = op->layout; + const char *autoexec_text = NULL; + + uiItemR(layout, op->ptr, "load_ui", 0, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, false); + if (file_info->is_untrusted) { + autoexec_text = "Trusted Source [Untrusted Path]"; + uiLayoutSetActive(col, false); + uiLayoutSetEnabled(col, false); + } + else { + autoexec_text = "Trusted Source"; + } + + uiItemR(col, op->ptr, "use_scripts", 0, autoexec_text, ICON_NONE); +} + static void WM_OT_open_mainfile(wmOperatorType *ot) { ot->name = "Open Blender File"; @@ -2003,6 +2106,8 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) ot->invoke = wm_open_mainfile_invoke; ot->exec = wm_open_mainfile_exec; + ot->check = wm_open_mainfile_check; + ot->ui = wm_open_mainfile_ui; /* ommit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_OPENFILE, @@ -2233,6 +2338,7 @@ void WM_recover_last_session(bContext *C, ReportList *reports) WM_event_add_notifier(C, NC_WINDOW, NULL); /* load file */ + WM_file_autoexec_init(filename); WM_file_read(C, filename, reports); G.fileflags &= ~G_FILE_RECOVER; @@ -2279,6 +2385,7 @@ static int wm_recover_auto_save_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_WINDOW, NULL); /* load file */ + WM_file_autoexec_init(path); WM_file_read(C, path, op->reports); G.fileflags &= ~G_FILE_RECOVER; @@ -2400,7 +2507,7 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) } /* function used for WM_OT_save_mainfile too */ -static int blend_save_check(bContext *UNUSED(C), wmOperator *op) +static bool blend_save_check(bContext *UNUSED(C), wmOperator *op) { char filepath[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filepath); @@ -4044,6 +4151,8 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_read_factory_settings); WM_operatortype_append(WM_OT_save_homefile); WM_operatortype_append(WM_OT_save_userpref); + WM_operatortype_append(WM_OT_userpref_autoexec_path_add); + WM_operatortype_append(WM_OT_userpref_autoexec_path_remove); WM_operatortype_append(WM_OT_window_fullscreen_toggle); WM_operatortype_append(WM_OT_quit_blender); WM_operatortype_append(WM_OT_open_mainfile); @@ -4101,13 +4210,12 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_SELECT); -#if 0 /* Durien guys like this :S */ + /* left mouse shift for deselect too */ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_SHIFT, 0, GESTURE_MODAL_DESELECT); WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_SHIFT, 0, GESTURE_MODAL_NOP); -#else + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_DESELECT); // default 2.4x WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_NOP); // default 2.4x -#endif WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_NOP); @@ -4175,21 +4283,22 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) /* items for modal map */ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, GESTURE_MODAL_CANCEL); + /* Note: cancel only on press otherwise you cannot map this to RMB-gesture */ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, GESTURE_MODAL_CANCEL); - - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_BEGIN); - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); -#if 0 /* Durian guys like this */ + /* allow shift leftclick for deselect too */ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_SHIFT, 0, GESTURE_MODAL_BEGIN); WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_SHIFT, 0, GESTURE_MODAL_DESELECT); -#else + + /* any unhandled leftclick release handles select */ + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_BEGIN); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_BEGIN); WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_DESELECT); -#endif - + /* assign map to operators */ WM_modalkeymap_assign(keymap, "ACTION_OT_select_border"); WM_modalkeymap_assign(keymap, "ANIM_OT_channels_select_border"); diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 7c744d10d63..8ff4ec445ea 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -488,18 +488,16 @@ elseif(WIN32) ) if(WITH_PYTHON) - set_lib_path(PYLIB "python") - string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) install( - FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}.dll + FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel ) install( - FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll + FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Debug ) diff --git a/source/creator/creator.c b/source/creator/creator.c index 302467c6b3d..817bc4fcf60 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1262,6 +1262,7 @@ static int load_file(int UNUSED(argc), const char **argv, void *data) * a file - this should do everything a 'load file' does */ ReportList reports; BKE_reports_init(&reports, RPT_PRINT); + WM_file_autoexec_init(filename); WM_file_read(C, filename, &reports); BKE_reports_clear(&reports); } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 3abc129521e..f02e842ad2e 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -521,10 +521,23 @@ void KX_KetsjiEngine::EndFrame() RenderDebugProperties(); } - m_average_framerate = m_logger->GetAverage(); - if (m_average_framerate < 1e-6) - m_average_framerate = 1e-6; - m_average_framerate = 1.0/m_average_framerate; + double tottime = m_logger->GetAverage(), time; + if (tottime < 1e-6) + tottime = 1e-6; + +#ifdef WITH_PYTHON + for (int i = tc_first; i < tc_numCategories; ++i) { + time = m_logger->GetAverage((KX_TimeCategory)i); + PyObject *val = PyTuple_New(2); + PyTuple_SetItem(val, 0, PyFloat_FromDouble(time*1000.f)); + PyTuple_SetItem(val, 1, PyFloat_FromDouble(time/tottime * 100.f)); + + PyDict_SetItemString(m_pyprofiledict, m_profileLabels[i], val); + Py_DECREF(val); + } +#endif + + m_average_framerate = 1.0/tottime; // Go to next profiling measurement, time spend after this call is shown in the next frame. m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds()); @@ -1526,15 +1539,6 @@ void KX_KetsjiEngine::RenderDebugProperties() m_rendertools->RenderBox2D(xcoord + (int)(2.2 * profile_indent), ycoord, m_canvas->GetWidth(), m_canvas->GetHeight(), time/tottime); ycoord += const_ysize; - -#ifdef WITH_PYTHON - PyObject *val = PyTuple_New(2); - PyTuple_SetItem(val, 0, PyFloat_FromDouble(time*1000.f)); - PyTuple_SetItem(val, 1, PyFloat_FromDouble(time/tottime * 100.f)); - - PyDict_SetItemString(m_pyprofiledict, m_profileLabels[j], val); - Py_DECREF(val); -#endif } } // Add the ymargin for titles below the other section of debug info @@ -1645,10 +1649,10 @@ void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overla } else { if (overlay) { - m_addingOverlayScenes.insert(scenename); + m_addingOverlayScenes.push_back(scenename); } else { - m_addingBackgroundScenes.insert(scenename); + m_addingBackgroundScenes.push_back(scenename); } } } @@ -1660,7 +1664,7 @@ void KX_KetsjiEngine::RemoveScene(const STR_String& scenename) { if (FindScene(scenename)) { - m_removingScenes.insert(scenename); + m_removingScenes.push_back(scenename); } else { @@ -1675,7 +1679,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes() { if (m_removingScenes.size()) { - set<STR_String>::iterator scenenameit; + vector<STR_String>::iterator scenenameit; for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++) { STR_String scenename = *scenenameit; @@ -1721,7 +1725,7 @@ KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename) void KX_KetsjiEngine::AddScheduledScenes() { - set<STR_String>::iterator scenenameit; + vector<STR_String>::iterator scenenameit; if (m_addingOverlayScenes.size()) { @@ -1757,7 +1761,7 @@ void KX_KetsjiEngine::AddScheduledScenes() void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene) { - m_replace_scenes.insert(std::make_pair(oldscene,newscene)); + m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); } // replace scene is not the same as removing and adding because the @@ -1768,7 +1772,7 @@ void KX_KetsjiEngine::ReplaceScheduledScenes() { if (m_replace_scenes.size()) { - set<pair<STR_String,STR_String> >::iterator scenenameit; + vector<pair<STR_String,STR_String> >::iterator scenenameit; for (scenenameit = m_replace_scenes.begin(); scenenameit != m_replace_scenes.end(); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 0d7e41d7568..3cba3558db3 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -41,7 +41,6 @@ #include "KX_Python.h" #include "KX_WorldInfo.h" #include <vector> -#include <set> class KX_TimeCategoryLogger; @@ -88,13 +87,13 @@ private: class KX_Dome* m_dome; // dome stereo mode /** Lists of scenes scheduled to be removed at the end of the frame. */ - std::set<STR_String> m_removingScenes; + std::vector<STR_String> m_removingScenes; /** Lists of overley scenes scheduled to be added at the end of the frame. */ - std::set<STR_String> m_addingOverlayScenes; + std::vector<STR_String> m_addingOverlayScenes; /** Lists of background scenes scheduled to be added at the end of the frame. */ - std::set<STR_String> m_addingBackgroundScenes; + std::vector<STR_String> m_addingBackgroundScenes; /** Lists of scenes scheduled to be replaced at the end of the frame. */ - std::set<std::pair<STR_String,STR_String> > m_replace_scenes; + std::vector<std::pair<STR_String,STR_String> > m_replace_scenes; /* The current list of scenes. */ KX_SceneList m_scenes; |